示例#1
0
		void FetchStream (ImapEngine engine, ImapCommand ic, int index)
		{
			var token = engine.ReadToken (ic.CancellationToken);
			var labels = new MessageLabelsChangedEventArgs (index);
			var flags = new MessageFlagsChangedEventArgs (index);
			var ctx = (FetchStreamContext) ic.UserData;
			var section = new StringBuilder ();
			bool labelsChanged = false;
			bool flagsChanged = false;
			var buf = new byte[4096];
			long nread = 0, size = 0;
			UniqueId? uid = null;
			Stream stream;
			int n;

			if (token.Type != ImapTokenType.OpenParen)
				throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);

			do {
				token = engine.ReadToken (ic.CancellationToken);

				if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
					break;

				if (token.Type != ImapTokenType.Atom)
					throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);

				var atom = (string) token.Value;
				int offset = 0, length;
				ulong modseq;
				uint value;

				switch (atom) {
				case "BODY":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.OpenBracket)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					section.Clear ();

					do {
						token = engine.ReadToken (ic.CancellationToken);

						if (token.Type == ImapTokenType.CloseBracket)
							break;

						if (token.Type == ImapTokenType.OpenParen) {
							section.Append (" (");

							do {
								token = engine.ReadToken (ic.CancellationToken);

								if (token.Type == ImapTokenType.CloseParen)
									break;

								// the header field names will generally be atoms or qstrings but may also be literals
								switch (token.Type) {
								case ImapTokenType.Literal:
									section.Append (engine.ReadLiteral (ic.CancellationToken));
									section.Append (' ');
									break;
								case ImapTokenType.QString:
								case ImapTokenType.Atom:
									section.Append ((string) token.Value);
									break;
								default:
									throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);
								}
							} while (true);

							if (section[section.Length - 1] == ' ')
								section.Length--;

							section.Append (')');
						} else if (token.Type != ImapTokenType.Atom) {
							throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);
						} else {
							section.Append ((string) token.Value);
						}
					} while (true);

					if (token.Type != ImapTokenType.CloseBracket)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type == ImapTokenType.Atom) {
						// this might be a region ("<###>")
						var expr = (string) token.Value;

						if (expr.Length > 2 && expr[0] == '<' && expr[expr.Length - 1] == '>') {
							var region = expr.Substring (1, expr.Length - 2);
							int.TryParse (region, out offset);

							token = engine.ReadToken (ic.CancellationToken);
						}
					}

					switch (token.Type) {
					case ImapTokenType.Literal:
						length = (int) token.Value;
						size += length;

						stream = CreateStream (uid, section.ToString (), offset, length);

						try {
							while ((n = engine.Stream.Read (buf, 0, buf.Length, ic.CancellationToken)) > 0) {
								stream.Write (buf, 0, n);
								nread += n;

								ctx.Report (nread, size);
							}

							stream.Position = 0;
						} catch {
							stream.Dispose ();
							throw;
						}
						break;
					case ImapTokenType.QString:
					case ImapTokenType.Atom:
						var buffer = Encoding.UTF8.GetBytes ((string) token.Value);
						length = buffer.Length;
						nread += length;
						size += length;

						stream = CreateStream (uid, section.ToString (), offset, length);

						try {
							stream.Write (buffer, 0, length);
							ctx.Report (nread, size);
							stream.Position = 0;
						} catch {
							stream.Dispose ();
							throw;
						}
						break;
					case ImapTokenType.Nil:
						stream = CreateStream (uid, section.ToString (), offset, 0);
						break;
					default:
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);
					}

					if (uid.HasValue)
						ctx.Sections[section.ToString ()] = CommitStream (stream, uid.Value);
					else
						ctx.Sections[section.ToString ()] = stream;

					break;
				case "UID":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value) || value == 0)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					uid = new UniqueId (UidValidity, value);

					foreach (var key in ctx.Sections.Keys.ToArray ())
						ctx.Sections[key] = CommitStream (ctx.Sections[key], uid.Value);

					labels.UniqueId = uid.Value;
					flags.UniqueId = uid.Value;
					break;
				case "MODSEQ":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.OpenParen)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out modseq))
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.CloseParen)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					labels.ModSeq = modseq;
					flags.ModSeq = modseq;
					break;
				case "FLAGS":
					// even though we didn't request this piece of information, the IMAP server
					// may send it if another client has recently modified the message flags.
					flags.Flags = ImapUtils.ParseFlagsList (engine, atom, flags.UserFlags, ic.CancellationToken);
					flagsChanged = true;
					break;
				case "X-GM-LABELS":
					// even though we didn't request this piece of information, the IMAP server
					// may send it if another client has recently modified the message labels.
					labels.Labels = ImapUtils.ParseLabelsList (engine, ic.CancellationToken);
					labelsChanged = true;
					break;
				default:
					throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);
				}
			} while (true);

			if (token.Type != ImapTokenType.CloseParen)
				throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);

			if (flagsChanged)
				ic.Folder.OnMessageFlagsChanged (flags);

			if (labelsChanged)
				ic.Folder.OnMessageLabelsChanged (labels);
		}
示例#2
0
		static string ReadStringToken (ImapEngine engine, string format, CancellationToken cancellationToken)
		{
			var token = engine.ReadToken (cancellationToken);

			switch (token.Type) {
			case ImapTokenType.Literal: return engine.ReadLiteral (cancellationToken);
			case ImapTokenType.QString: return (string) token.Value;
			case ImapTokenType.Atom:    return (string) token.Value;
			default:
				throw ImapEngine.UnexpectedToken (format, token);
			}
		}
示例#3
0
		void FetchSummaryItems (ImapEngine engine, ImapCommand ic, int index)
		{
			var token = engine.ReadToken (ic.CancellationToken);

			if (token.Type != ImapTokenType.OpenParen)
				throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);

			var ctx = (FetchSummaryContext) ic.UserData;
			IMessageSummary isummary;
			MessageSummary summary;

			if (!ctx.Results.TryGetValue (index, out isummary)) {
				summary = new MessageSummary (index);
				ctx.Results.Add (index, summary);
			} else {
				summary = (MessageSummary) isummary;
			}

			do {
				token = engine.ReadToken (ic.CancellationToken);

				if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
					break;

				if (token.Type != ImapTokenType.Atom)
					throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);

				var atom = (string) token.Value;
				string format;
				ulong value64;
				uint value;
				int idx;

				switch (atom) {
				case "INTERNALDATE":
					token = engine.ReadToken (ic.CancellationToken);

					switch (token.Type) {
					case ImapTokenType.QString:
					case ImapTokenType.Atom:
						summary.InternalDate = ImapUtils.ParseInternalDate ((string) token.Value);
						break;
					case ImapTokenType.Nil:
						summary.InternalDate = null;
						break;
					default:
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);
					}

					summary.Fields |= MessageSummaryItems.InternalDate;
					break;
				case "RFC822.SIZE":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value))
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					summary.Fields |= MessageSummaryItems.MessageSize;
					summary.Size = value;
					break;
				case "BODYSTRUCTURE":
					format = string.Format (ImapEngine.GenericItemSyntaxErrorFormat, "BODYSTRUCTURE", "{0}");
					summary.Body = ImapUtils.ParseBody (engine, format, string.Empty, ic.CancellationToken);
					summary.Fields |= MessageSummaryItems.BodyStructure;
					break;
				case "BODY":
					token = engine.PeekToken (ic.CancellationToken);

					if (token.Type == ImapTokenType.OpenBracket) {
						// consume the '['
						token = engine.ReadToken (ic.CancellationToken);

						if (token.Type != ImapTokenType.OpenBracket)
							throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

						// References and/or other headers were requested...

						do {
							token = engine.ReadToken (ic.CancellationToken);

							if (token.Type == ImapTokenType.CloseBracket)
								break;

							if (token.Type == ImapTokenType.OpenParen) {
								do {
									token = engine.ReadToken (ic.CancellationToken);

									if (token.Type == ImapTokenType.CloseParen)
										break;

									// the header field names will generally be atoms or qstrings but may also be literals
									switch (token.Type) {
									case ImapTokenType.Literal:
										engine.ReadLiteral (ic.CancellationToken);
										break;
									case ImapTokenType.QString:
									case ImapTokenType.Atom:
										break;
									default:
										throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);
									}
								} while (true);
							} else if (token.Type != ImapTokenType.Atom) {
								throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);
							}
						} while (true);

						if (token.Type != ImapTokenType.CloseBracket)
							throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

						token = engine.ReadToken (ic.CancellationToken);

						if (token.Type != ImapTokenType.Literal)
							throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

						summary.References = new MessageIdList ();

						try {
							summary.Headers = engine.ParseHeaders (engine.Stream, ic.CancellationToken);
						} catch (FormatException) {
							// consume any remaining literal data...
							ReadLiteralData (engine, ic.CancellationToken);
							summary.Headers = new HeaderList ();
						}

						if ((idx = summary.Headers.IndexOf (HeaderId.References)) != -1) {
							var references = summary.Headers[idx];
							var rawValue = references.RawValue;

							foreach (var msgid in MimeUtils.EnumerateReferences (rawValue, 0, rawValue.Length))
								summary.References.Add (msgid);
						}

						summary.Fields |= MessageSummaryItems.References;
					} else {
						summary.Fields |= MessageSummaryItems.Body;

						try {
							format = string.Format (ImapEngine.GenericItemSyntaxErrorFormat, "BODY", "{0}");
							summary.Body = ImapUtils.ParseBody (engine, format, string.Empty, ic.CancellationToken);
						} catch (ImapProtocolException ex) {
							if (!ex.UnexpectedToken)
								throw;

							// Note: GMail's IMAP implementation sometimes replies with completely broken BODY values
							// (see issue #32 for the `BODY ("ALTERNATIVE")` example), so to work around this nonsense,
							// we need to drop the remainder of this line.
							do {
								token = engine.PeekToken (ic.CancellationToken);

								if (token.Type == ImapTokenType.Eoln)
									break;

								token = engine.ReadToken (ic.CancellationToken);

								if (token.Type == ImapTokenType.Literal)
									ReadLiteralData (engine, ic.CancellationToken);
							} while (true);

							return;
						}
					}
					break;
				case "ENVELOPE":
					summary.Envelope = ImapUtils.ParseEnvelope (engine, ic.CancellationToken);
					summary.Fields |= MessageSummaryItems.Envelope;
					break;
				case "FLAGS":
					summary.Flags = ImapUtils.ParseFlagsList (engine, atom, summary.UserFlags, ic.CancellationToken);
					summary.Fields |= MessageSummaryItems.Flags;
					break;
				case "MODSEQ":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.OpenParen)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64))
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.CloseParen)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					summary.Fields |= MessageSummaryItems.ModSeq;
					summary.ModSeq = value64;
					break;
				case "UID":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value) || value == 0)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					summary.UniqueId = new UniqueId (ic.Folder.UidValidity, value);
					summary.Fields |= MessageSummaryItems.UniqueId;
					break;
				case "X-GM-MSGID":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					summary.Fields |= MessageSummaryItems.GMailMessageId;
					summary.GMailMessageId = value64;
					break;
				case "X-GM-THRID":
					token = engine.ReadToken (ic.CancellationToken);

					if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
						throw ImapEngine.UnexpectedToken (ImapEngine.GenericItemSyntaxErrorFormat, atom, token);

					summary.Fields |= MessageSummaryItems.GMailThreadId;
					summary.GMailThreadId = value64;
					break;
				case "X-GM-LABELS":
					summary.GMailLabels = ImapUtils.ParseLabelsList (engine, ic.CancellationToken);
					summary.Fields |= MessageSummaryItems.GMailLabels;
					break;
				default:
					throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);
				}
			} while (true);

			if (token.Type != ImapTokenType.CloseParen)
				throw ImapEngine.UnexpectedToken (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "FETCH", token);

			if ((ctx.RequestedItems & summary.Fields) == ctx.RequestedItems)
				OnMessageSummaryFetched (summary);
		}
示例#4
0
		static void SkipBodyExtensions (ImapEngine engine, CancellationToken cancellationToken)
		{
			var token = engine.ReadToken (cancellationToken);

			switch (token.Type) {
			case ImapTokenType.OpenParen:
				do {
					token = engine.PeekToken (cancellationToken);

					if (token.Type == ImapTokenType.CloseParen)
						break;

					SkipBodyExtensions (engine, cancellationToken);
				} while (true);

				// read the ')'
				engine.ReadToken (cancellationToken);
				break;
			case ImapTokenType.Literal:
				engine.ReadLiteral (cancellationToken);
				break;
			case ImapTokenType.QString:
			case ImapTokenType.Atom:
			case ImapTokenType.Nil:
				break;
			default:
				throw ImapEngine.UnexpectedToken (token, false);
			}
		}
示例#5
0
		static EnvelopeAddress ParseEnvelopeAddress (ImapEngine engine, CancellationToken cancellationToken)
		{
			var values = new string[4];
			ImapToken token;
			int index = 0;

			do {
				token = engine.ReadToken (cancellationToken);

				switch (token.Type) {
				case ImapTokenType.Literal:
					values[index] = engine.ReadLiteral (cancellationToken);
					break;
				case ImapTokenType.QString:
				case ImapTokenType.Atom:
					values[index] = (string) token.Value;
					break;
				case ImapTokenType.Nil:
					break;
				default:
					throw ImapEngine.UnexpectedToken (token, false);
				}

				index++;
			} while (index < 4);

			token = engine.ReadToken (cancellationToken);

			if (token.Type != ImapTokenType.CloseParen)
				throw ImapEngine.UnexpectedToken (token, false);

			return new EnvelopeAddress (values);
		}
示例#6
0
		static string[] ParseContentLanguage (ImapEngine engine, CancellationToken cancellationToken)
		{
			var token = engine.ReadToken (cancellationToken);
			var languages = new List<string> ();
			string language;

			switch (token.Type) {
			case ImapTokenType.Literal:
				language = engine.ReadLiteral (cancellationToken);
				languages.Add (language);
				break;
			case ImapTokenType.QString:
			case ImapTokenType.Atom:
				language = (string) token.Value;
				languages.Add (language);
				break;
			case ImapTokenType.Nil:
				return null;
			case ImapTokenType.OpenParen:
				do {
					token = engine.PeekToken (cancellationToken);

					if (token.Type == ImapTokenType.CloseParen)
						break;

					language = ReadStringToken (engine, cancellationToken);
					languages.Add (language);
				} while (true);

				// read the ')'
				engine.ReadToken (cancellationToken);
				break;
			default:
				throw ImapEngine.UnexpectedToken (token, false);
			}

			return languages.ToArray ();
		}
示例#7
0
		static string ReadNStringToken (ImapEngine engine, bool rfc2047, CancellationToken cancellationToken)
		{
			var token = engine.ReadToken (cancellationToken);
			string value;

			switch (token.Type) {
			case ImapTokenType.Literal:
				value = engine.ReadLiteral (cancellationToken);
				break;
			case ImapTokenType.QString:
			case ImapTokenType.Atom:
				value = (string) token.Value;
				break;
			case ImapTokenType.Nil:
				return null;
			default:
				throw ImapEngine.UnexpectedToken (token, false);
			}

			return rfc2047 ? Rfc2047.DecodeText (Latin1.GetBytes (value)) : value;
		}
示例#8
0
		/// <summary>
		/// Parses an untagged LIST or LSUB response.
		/// </summary>
		/// <param name="engine">The IMAP engine.</param>
		/// <param name="ic">The IMAP command.</param>
		/// <param name="index">The index.</param>
		public static void ParseFolderList (ImapEngine engine, ImapCommand ic, int index)
		{
			var token = engine.ReadToken (ic.CancellationToken);
			var list = (List<ImapFolder>) ic.UserData;
			var attrs = FolderAttributes.None;
			string encodedName;
			ImapFolder folder;
			char delim;

			// parse the folder attributes list
			if (token.Type != ImapTokenType.OpenParen)
				throw ImapEngine.UnexpectedToken (token, false);

			token = engine.ReadToken (ic.CancellationToken);

			while (token.Type == ImapTokenType.Flag || token.Type == ImapTokenType.Atom) {
				string atom = (string) token.Value;

				switch (atom) {
				case "\\NoInferiors":   attrs |= FolderAttributes.NoInferiors; break;
				case "\\Noselect":      attrs |= FolderAttributes.NoSelect; break;
				case "\\Marked":        attrs |= FolderAttributes.Marked; break;
				case "\\Unmarked":      attrs |= FolderAttributes.Unmarked; break;
				case "\\NonExistent":   attrs |= FolderAttributes.NonExistent; break;
				case "\\Subscribed":    attrs |= FolderAttributes.Subscribed; break;
				case "\\Remote":        attrs |= FolderAttributes.Remote; break;
				case "\\HasChildren":   attrs |= FolderAttributes.HasChildren; break;
				case "\\HasNoChildren": attrs |= FolderAttributes.HasNoChildren; break;
				case "\\All":           attrs |= FolderAttributes.All; break;
				case "\\Archive":       attrs |= FolderAttributes.Archive; break;
				case "\\Drafts":        attrs |= FolderAttributes.Drafts; break;
				case "\\Flagged":       attrs |= FolderAttributes.Flagged; break;
				case "\\Junk":          attrs |= FolderAttributes.Junk; break;
				case "\\Sent":          attrs |= FolderAttributes.Sent; break;
				case "\\Trash":         attrs |= FolderAttributes.Trash; break;
					// XLIST flags:
				case "\\AllMail":       attrs |= FolderAttributes.All; break;
				case "\\Important":     attrs |= FolderAttributes.Flagged; break;
				case "\\Inbox":         attrs |= FolderAttributes.Inbox; break;
				case "\\Spam":          attrs |= FolderAttributes.Junk; break;
				case "\\Starred":       attrs |= FolderAttributes.Flagged; break;
				}

				token = engine.ReadToken (ic.CancellationToken);
			}

			if (token.Type != ImapTokenType.CloseParen)
				throw ImapEngine.UnexpectedToken (token, false);

			// parse the path delimeter
			token = engine.ReadToken (ic.CancellationToken);

			if (token.Type == ImapTokenType.QString) {
				var qstring = (string) token.Value;

				delim = qstring[0];
			} else if (token.Type == ImapTokenType.Nil) {
				delim = '\0';
			} else {
				throw ImapEngine.UnexpectedToken (token, false);
			}

			// parse the folder name
			token = engine.ReadToken (ImapStream.StringSpecials, ic.CancellationToken);

			switch (token.Type) {
			case ImapTokenType.Literal:
				encodedName = engine.ReadLiteral (ic.CancellationToken);
				break;
			case ImapTokenType.QString:
			case ImapTokenType.Atom:
				encodedName = (string) token.Value;
				break;
			default:
				throw ImapEngine.UnexpectedToken (token, false);
			}

			if (IsInbox (encodedName))
				attrs |= FolderAttributes.Inbox;

			if (engine.GetCachedFolder (encodedName, out folder)) {
				attrs |= (folder.Attributes & ~(FolderAttributes.Marked | FolderAttributes.Unmarked));
				folder.UpdateAttributes (attrs);
			} else {
				folder = engine.CreateImapFolder (encodedName, attrs, delim);
				engine.CacheFolder (folder);
			}

			list.Add (folder);
		}
示例#9
0
		static DateTimeOffset? ParseEnvelopeDate (ImapEngine engine, CancellationToken cancellationToken)
		{
			var token = engine.ReadToken (cancellationToken);
			DateTimeOffset date;
			string value;

			switch (token.Type) {
			case ImapTokenType.Literal:
				value = engine.ReadLiteral (cancellationToken);
				break;
			case ImapTokenType.QString:
			case ImapTokenType.Atom:
				value = (string) token.Value;
				break;
			case ImapTokenType.Nil:
				return null;
			default:
				throw ImapEngine.UnexpectedToken (token, false);
			}

			if (!DateUtils.TryParse (value, out date))
				return null;

			return date;
		}
示例#10
0
        static void AddEnvelopeAddress(InternetAddressList list, ImapEngine engine, CancellationToken cancellationToken)
        {
            var values = new string[4];
            ImapToken token;
            int index = 0;

            do {
                token = engine.ReadToken (cancellationToken);

                switch (token.Type) {
                case ImapTokenType.Literal:
                    values[index] = engine.ReadLiteral (cancellationToken);
                    break;
                case ImapTokenType.QString:
                case ImapTokenType.Atom:
                    values[index] = (string) token.Value;
                    break;
                case ImapTokenType.Nil:
                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }

                index++;
            } while (index < 4);

            token = engine.ReadToken (cancellationToken);

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);

            string name = null;

            if (values[0] != null) {
                // Note: since the ImapEngine.ReadLiteral() uses iso-8859-1
                // to convert bytes to unicode, we can undo that here:
                name = Rfc2047.DecodePhrase (Latin1.GetBytes (values[0]));
            }

            string address = values[3] != null ? values[2] + "@" + values[3] : values[2];

            list.Add (new MailboxAddress (name, address));
        }