An IMAP folder.
An IMAP folder.
Inheritance: MailFolder
Beispiel #1
0
            /// <summary>
            /// Format the IMAP NOTIFY command for this particular IMAP mailbox filter.
            /// </summary>
            /// <remarks>
            /// Formats the IMAP NOTIFY command for this particular IMAP mailbox filter.
            /// </remarks>
            /// <param name="engine">The IMAP engine.</param>
            /// <param name="command">The IMAP command builder.</param>
            /// <param name="args">The IMAP command argument builder.</param>
            /// <param name="isSelectedFilter"><c>true</c> if the event is being registered for a
            /// <see cref="ImapMailboxFilter.Selected"/> or <see cref="ImapMailboxFilter.SelectedDelayed"/>
            /// mailbox filter.</param>
            internal override void Format(ImapEngine engine, StringBuilder command, IList <object> args, bool isSelectedFilter)
            {
                command.Append(Name);

                if (ImapFolder.IsEmptyFetchRequest(request))
                {
                    return;
                }

                if (!isSelectedFilter)
                {
                    throw new InvalidOperationException("The MessageNew event cannot have any parameters for mailbox filters other than SELECTED and SELECTED-DELAYED.");
                }

                command.Append(" ");
                command.Append(ImapFolder.FormatSummaryItems(engine, request, out _, isNotify: true));
            }
Beispiel #2
0
            /// <summary>
            /// Format the IMAP NOTIFY command for this particular IMAP mailbox filter.
            /// </summary>
            /// <remarks>
            /// Formats the IMAP NOTIFY command for this particular IMAP mailbox filter.
            /// </remarks>
            /// <param name="engine">The IMAP engine.</param>
            /// <param name="command">The IMAP command builder.</param>
            /// <param name="args">The IMAP command argument builder.</param>
            /// <param name="isSelectedFilter"><c>true</c> if the event is being registered for a
            /// <see cref="ImapMailboxFilter.Selected"/> or <see cref="ImapMailboxFilter.SelectedDelayed"/>
            /// mailbox filter.</param>
            internal override void Format(ImapEngine engine, StringBuilder command, IList <object> args, bool isSelectedFilter)
            {
                command.Append(Name);

                if (items == MessageSummaryItems.None && headers.Count == 0)
                {
                    return;
                }

                if (!isSelectedFilter)
                {
                    throw new InvalidOperationException("The MessageNew event cannot have any parameters for mailbox filters other than SELECTED and SELECTED-DELAYED.");
                }

                var  xitems = items;
                bool previewText;

                command.Append(" ");
                command.Append(ImapFolder.FormatSummaryItems(engine, ref xitems, headers, out previewText, isNotify: true));
            }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
        /// </summary>
        /// <remarks>
        /// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
        /// </remarks>
        /// <param name="engine">The IMAP engine that will be sending the command.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="folder">The IMAP folder that the command operates on.</param>
        /// <param name="options">The formatting options.</param>
        /// <param name="format">The command format.</param>
        /// <param name="args">The command arguments.</param>
        public ImapCommand(ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, FormatOptions options, string format, params object[] args)
        {
            UntaggedHandlers  = new Dictionary <string, ImapUntaggedHandler> ();
            RespCodes         = new List <ImapResponseCode> ();
            CancellationToken = cancellationToken;
            Status            = ImapCommandStatus.Created;
            Result            = ImapCommandResult.None;
            Engine            = engine;
            Folder            = folder;

            using (var builder = new MemoryStream()) {
                var    plus = (Engine.Capabilities & ImapCapabilities.LiteralPlus) != 0 ? "+" : string.Empty;
                int    argc = 0;
                byte[] buf;
                string str;
                char   c;

                for (int i = 0; i < format.Length; i++)
                {
                    if (format[i] == '%')
                    {
                        switch (format[++i])
                        {
                        case '%':                         // a literal %
                            builder.WriteByte((byte)'%');
                            break;

                        case 'c':                         // a character
                            c = (char)args[argc++];
                            builder.WriteByte((byte)c);
                            break;

                        case 'd':                         // an integer
                            str = ((int)args[argc++]).ToString();
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 'u':                         // an unsigned integer
                            str = ((uint)args[argc++]).ToString();
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 'F':                         // an ImapFolder
                            var utf7 = ((ImapFolder)args[argc++]).EncodedName;
                            AppendString(options, true, builder, utf7);
                            break;

                        case 'L':
                            var literal = new ImapLiteral(options, args[argc++]);
                            var length  = literal.Length;

                            if (options.International)
                            {
                                str = "UTF8 (~{" + length + plus + "}\r\n";
                            }
                            else
                            {
                                str = "{" + length + plus + "}\r\n";
                            }

                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);

                            parts.Add(new ImapCommandPart(builder.ToArray(), literal));
                            builder.SetLength(0);

                            if (options.International)
                            {
                                builder.WriteByte((byte)')');
                            }
                            break;

                        case 'S':                         // a string which may need to be quoted or made into a literal
                            AppendString(options, true, builder, (string)args[argc++]);
                            break;

                        case 'Q':                         // similar to %S but string must be quoted at a minimum
                            AppendString(options, false, builder, (string)args[argc++]);
                            break;

                        case 's':                         // a safe atom string
                            buf = Encoding.ASCII.GetBytes((string)args[argc++]);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        default:
                            throw new FormatException();
                        }
                    }
                    else
                    {
                        builder.WriteByte((byte)format[i]);
                    }
                }

                parts.Add(new ImapCommandPart(builder.ToArray(), null));
            }
        }
Beispiel #4
0
 /// <summary>
 /// Queues the command.
 /// </summary>
 /// <returns>The command.</returns>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <param name="folder">The folder that the command operates on.</param>
 /// <param name="format">The command format.</param>
 /// <param name="args">The command arguments.</param>
 public ImapCommand QueueCommand(CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
 {
     var ic = new ImapCommand (this, cancellationToken, folder, format, args);
     QueueCommand (ic);
     return ic;
 }
Beispiel #5
0
        void UpdateNamespaces(CancellationToken cancellationToken)
        {
            var namespaces = new List<FolderNamespaceCollection> {
                PersonalNamespaces, SharedNamespaces, OtherNamespaces
            };
            ImapFolder folder;
            ImapToken token;
            string path;
            char delim;
            int n = 0;

            PersonalNamespaces.Clear ();
            SharedNamespaces.Clear ();
            OtherNamespaces.Clear ();

            token = stream.ReadToken (cancellationToken);

            do {
                if (token.Type == ImapTokenType.OpenParen) {
                    // parse the list of namespace pairs...
                    token = stream.ReadToken (cancellationToken);

                    while (token.Type == ImapTokenType.OpenParen) {
                        // parse the namespace pair - first token is the path
                        token = stream.ReadToken (cancellationToken);

                        if (token.Type != ImapTokenType.QString && token.Type != ImapTokenType.Atom) {
                            Debug.WriteLine ("Expected string token as first element in namespace pair, but got: {0}", token);
                            throw UnexpectedToken (token, false);
                        }

                        path = (string) token.Value;

                        // second token is the directory separator
                        token = stream.ReadToken (cancellationToken);

                        if (token.Type != ImapTokenType.QString && token.Type != ImapTokenType.Nil) {
                            Debug.WriteLine ("Expected string or nil token as second element in namespace pair, but got: {0}", token);
                            throw UnexpectedToken (token, false);
                        }

                        var qstring = token.Type == ImapTokenType.Nil ? string.Empty : (string) token.Value;

                        if (qstring.Length > 0) {
                            delim = qstring[0];

                            // canonicalize the namespace path
                            path = path.TrimEnd (delim);
                        } else {
                            delim = '\0';
                        }

                        namespaces[n].Add (new FolderNamespace (delim, ImapEncoding.Decode (path)));
                        if (!FolderCache.TryGetValue (path, out folder)) {
                            folder = new ImapFolder (this, path, FolderAttributes.None, delim);
                            FolderCache.Add (path, folder);
                        }

                        folder.IsNamespace = true;

                        do {
                            token = stream.ReadToken (cancellationToken);

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

                            // NAMESPACE extension

                            if (token.Type != ImapTokenType.QString && token.Type != ImapTokenType.Atom)
                                throw UnexpectedToken (token, false);

                            token = stream.ReadToken (cancellationToken);

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

                            do {
                                token = stream.ReadToken (cancellationToken);

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

                                if (token.Type != ImapTokenType.QString && token.Type != ImapTokenType.Atom)
                                    throw UnexpectedToken (token, false);
                            } while (true);
                        } while (true);

                        // read the next token - it should either be '(' or ')'
                        token = stream.ReadToken (cancellationToken);
                    }

                    if (token.Type != ImapTokenType.CloseParen) {
                        Debug.WriteLine ("Expected ')' to close namespace pair, but got: {0}", token);
                        throw UnexpectedToken (token, false);
                    }
                } else if (token.Type != ImapTokenType.Nil) {
                    Debug.WriteLine ("Expected '(' or 'NIL' token after untagged 'NAMESPACE' response, but got: {0}", token);
                    throw UnexpectedToken (token, false);
                }

                token = stream.ReadToken (cancellationToken);
                n++;
            } while (n < 3);

            while (token.Type != ImapTokenType.Eoln)
                token = stream.ReadToken (cancellationToken);
        }
Beispiel #6
0
        /// <summary>
        /// Looks up and sets the <see cref="ImapFolder.ParentFolder"/> property of each of the folders.
        /// </summary>
        /// <param name="folders">The IMAP folders.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        void LookupParentFolders(IEnumerable<ImapFolder> folders, CancellationToken cancellationToken)
        {
            var list = new List<ImapFolder> (folders);
            string encodedName;
            ImapFolder parent;
            int index;

            foreach (var folder in list) {
                if (folder.ParentFolder != null)
                    continue;

                if ((index = folder.FullName.LastIndexOf (folder.DirectorySeparator)) != -1) {
                    if (index == 0)
                        continue;

                    var parentName = folder.FullName.Substring (0, index);
                    encodedName = ImapEncoding.Encode (parentName);
                } else {
                    encodedName = string.Empty;
                }

                if (FolderCache.TryGetValue (encodedName, out parent)) {
                    folder.SetParentFolder (parent);
                    continue;
                }

                var ic = new ImapCommand (this, cancellationToken, null, "LIST \"\" %S\r\n", encodedName);
                ic.RegisterUntaggedHandler ("LIST", ImapUtils.ParseFolderList);
                ic.UserData = new List<ImapFolder> ();

                QueueCommand (ic);
                Wait (ic);

                if (!FolderCache.TryGetValue (encodedName, out parent)) {
                    parent = new ImapFolder (this, encodedName, FolderAttributes.NonExistent, folder.DirectorySeparator);
                    FolderCache.Add (encodedName, parent);
                } else if (parent.ParentFolder == null && !parent.IsNamespace) {
                    list.Add (parent);
                }

                folder.SetParentFolder (parent);
            }
        }
Beispiel #7
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
		/// </summary>
		/// <param name="engine">The IMAP engine that will be sending the command.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <param name="folder">The IMAP folder that the command operates on.</param>
		/// <param name="format">The command format.</param>
		/// <param name="args">The command arguments.</param>
		public ImapCommand (ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
		{
			UntaggedHandlers = new Dictionary<string, ImapUntaggedHandler> ();
			RespCodes = new List<ImapResponseCode> ();
			CancellationToken = cancellationToken;
			Status = ImapCommandStatus.Created;
			Result = ImapCommandResult.None;
			Engine = engine;
			Folder = folder;

			using (var builder = new MemoryStream ()) {
				int argc = 0;
				byte[] buf;
				string str;
				char c;

				for (int i = 0; i < format.Length; i++) {
					if (format[i] == '%') {
						switch (format[++i]) {
						case '%': // a literal %
							builder.WriteByte ((byte) '%');
							break;
						case 'c': // a character
							c = (char) args[argc++];
							builder.WriteByte ((byte) c);
							break;
						case 'd': // an integer
							str = ((int) args[argc++]).ToString ();
							buf = Encoding.ASCII.GetBytes (str);
							builder.Write (buf, 0, buf.Length);
							break;
						case 'u': // an unsigned integer
							str = ((uint) args[argc++]).ToString ();
							buf = Encoding.ASCII.GetBytes (str);
							builder.Write (buf, 0, buf.Length);
							break;
						case 'F': // an ImapFolder
							var utf7 = ((ImapFolder) args[argc++]).EncodedName;
							AppendString (builder, utf7);
							break;
						case 'L':
							var literal = new ImapLiteral (args[argc++]);
							var length = literal.Length;

							buf = Encoding.ASCII.GetBytes (length.ToString ());

							// FIXME: support LITERAL+?
							builder.WriteByte ((byte) '{');
							builder.Write (buf, 0, buf.Length);
							builder.WriteByte ((byte) '}');
							builder.WriteByte ((byte) '\r');
							builder.WriteByte ((byte) '\n');

							parts.Add (new ImapCommandPart (builder.ToArray (), literal));
							builder.SetLength (0);
							break;
						case 'S': // a string which may need to be quoted or made into a literal
							AppendString (builder, (string) args[argc++]);
							break;
						case 's': // a safe atom string
							buf = Encoding.ASCII.GetBytes ((string) args[argc++]);
							builder.Write (buf, 0, buf.Length);
							break;
						default:
							throw new FormatException ();
						}
					} else {
						builder.WriteByte ((byte) format[i]);
					}
				}

				parts.Add (new ImapCommandPart (builder.ToArray (), null));
			}
		}
Beispiel #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
        /// </summary>
        /// <param name="engine">The IMAP engine that will be sending the command.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="folder">The IMAP folder that the command operates on.</param>
        /// <param name="format">The command format.</param>
        /// <param name="args">The command arguments.</param>
        public ImapCommand(ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
        {
            UntaggedHandlers  = new Dictionary <string, ImapUntaggedHandler> ();
            RespCodes         = new List <ImapResponseCode> ();
            CancellationToken = cancellationToken;
            Status            = ImapCommandStatus.Created;
            Result            = ImapCommandResult.None;
            Engine            = engine;
            Folder            = folder;

            using (var builder = new MemoryStream()) {
                int    argc = 0;
                byte[] buf;
                string str;
                char   c;

                for (int i = 0; i < format.Length; i++)
                {
                    if (format[i] == '%')
                    {
                        switch (format[++i])
                        {
                        case '%':                         // a literal %
                            builder.WriteByte((byte)'%');
                            break;

                        case 'c':                         // a character
                            c = (char)args[argc++];
                            builder.WriteByte((byte)c);
                            break;

                        case 'd':                         // an integer
                            str = ((int)args[argc++]).ToString();
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 'u':                         // an unsigned integer
                            str = ((uint)args[argc++]).ToString();
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 'F':                         // an ImapFolder
                            var utf7 = ((ImapFolder)args[argc++]).EncodedName;
                            AppendString(builder, utf7);
                            break;

                        case 'L':
                            var literal = new ImapLiteral(args[argc++]);
                            var length  = literal.Length;

                            buf = Encoding.ASCII.GetBytes(length.ToString());

                            // FIXME: support LITERAL+?
                            builder.WriteByte((byte)'{');
                            builder.Write(buf, 0, buf.Length);
                            builder.WriteByte((byte)'}');
                            builder.WriteByte((byte)'\r');
                            builder.WriteByte((byte)'\n');

                            parts.Add(new ImapCommandPart(builder.ToArray(), literal));
                            builder.SetLength(0);
                            break;

                        case 'S':                         // a string which may need to be quoted or made into a literal
                            AppendString(builder, (string)args[argc++]);
                            break;

                        case 's':                         // a safe atom string
                            buf = Encoding.ASCII.GetBytes((string)args[argc++]);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        default:
                            throw new FormatException();
                        }
                    }
                    else
                    {
                        builder.WriteByte((byte)format[i]);
                    }
                }

                parts.Add(new ImapCommandPart(builder.ToArray(), null));
            }
        }
Beispiel #9
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
		/// </summary>
		/// <remarks>
		/// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
		/// </remarks>
		/// <param name="engine">The IMAP engine that will be sending the command.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <param name="folder">The IMAP folder that the command operates on.</param>
		/// <param name="options">The formatting options.</param>
		/// <param name="format">The command format.</param>
		/// <param name="args">The command arguments.</param>
		public ImapCommand (ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, FormatOptions options, string format, params object[] args)
		{
			UntaggedHandlers = new Dictionary<string, ImapUntaggedHandler> ();
			RespCodes = new List<ImapResponseCode> ();
			CancellationToken = cancellationToken;
			Response = ImapCommandResponse.None;
			Status = ImapCommandStatus.Created;
			Engine = engine;
			Folder = folder;

			using (var builder = new MemoryStream ()) {
				var plus = (Engine.Capabilities & ImapCapabilities.LiteralPlus) != 0 ? "+" : string.Empty;
				int argc = 0;
				byte[] buf;
				string str;
				char c;

				for (int i = 0; i < format.Length; i++) {
					if (format[i] == '%') {
						switch (format[++i]) {
						case '%': // a literal %
							builder.WriteByte ((byte) '%');
							break;
						case 'c': // a character
							c = (char) args[argc++];
							builder.WriteByte ((byte) c);
							break;
						case 'd': // an integer
							str = ((int) args[argc++]).ToString ();
							buf = Encoding.ASCII.GetBytes (str);
							builder.Write (buf, 0, buf.Length);
							break;
						case 'u': // an unsigned integer
							str = ((uint) args[argc++]).ToString ();
							buf = Encoding.ASCII.GetBytes (str);
							builder.Write (buf, 0, buf.Length);
							break;
						case 'F': // an ImapFolder
							var utf7 = ((ImapFolder) args[argc++]).EncodedName;
							AppendString (options, true, builder, utf7);
							break;
						case 'L':
							var literal = new ImapLiteral (options, args[argc++], UpdateProgress);
							var length = literal.Length;

							totalSize += length;

							if (options.International)
								str = "UTF8 (~{" + length + plus + "}\r\n";
							else
								str = "{" + length + plus + "}\r\n";

							buf = Encoding.ASCII.GetBytes (str);
							builder.Write (buf, 0, buf.Length);

							parts.Add (new ImapCommandPart (builder.ToArray (), literal));
							builder.SetLength (0);

							if (options.International)
								builder.WriteByte ((byte) ')');
							break;
						case 'S': // a string which may need to be quoted or made into a literal
							AppendString (options, true, builder, (string) args[argc++]);
							break;
						case 'Q': // similar to %S but string must be quoted at a minimum
							AppendString (options, false, builder, (string) args[argc++]);
							break;
						case 's': // a safe atom string
							buf = Encoding.ASCII.GetBytes ((string) args[argc++]);
							builder.Write (buf, 0, buf.Length);
							break;
						default:
							throw new FormatException ();
						}
					} else {
						builder.WriteByte ((byte) format[i]);
					}
				}

				parts.Add (new ImapCommandPart (builder.ToArray (), null));
			}
		}
Beispiel #10
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>
        /// <param name="tok">The token.</param>
        public static void ParseFolderList(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            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":         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 (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 (engine.FolderCache.TryGetValue (encodedName, out folder)) {
                folder.Attributes = (folder.Attributes & ~(FolderAttributes.Marked | FolderAttributes.Unmarked)) | attrs;
            } else {
                folder = new ImapFolder (engine, encodedName, attrs, delim);
                engine.FolderCache.Add (encodedName, folder);
            }

            list.Add (folder);
        }
Beispiel #11
0
        /// <summary>
        /// Queries the special folders.
        /// </summary>
        /// <returns>The command result.</returns>
        /// <param name="cancellationToken">The cancellation token.</param>
        public void QuerySpecialFolders(CancellationToken cancellationToken)
        {
            if (stream == null)
                throw new InvalidOperationException ();

            ImapFolder folder;

            if (!FolderCache.TryGetValue ("INBOX", out folder)) {
                var list = new List<ImapFolder> ();

                var ic = QueueCommand (cancellationToken, null, "LIST \"\" \"INBOX\"\r\n");
                ic.RegisterUntaggedHandler ("LIST", ImapUtils.HandleUntaggedListResponse);
                ic.UserData = list;

                Wait (ic);

                Inbox = list.Count > 0 ? list[0] : null;
            }

            if ((Capabilities & ImapCapabilities.SpecialUse) != 0) {
                var list = new List<ImapFolder> ();

                var ic = QueueCommand (cancellationToken, null, "LIST (SPECIAL-USE) \"\" \"*\"\r\n");
                ic.RegisterUntaggedHandler ("LIST", ImapUtils.HandleUntaggedListResponse);
                ic.UserData = list;

                Wait (ic);

                ImapUtils.LookupParentFolders (this, list, cancellationToken);

                for (int i = 0; i < list.Count; i++) {
                    folder = list[i];

                    if ((folder.Attributes & FolderAttributes.All) != 0)
                        All = folder;
                    if ((folder.Attributes & FolderAttributes.Archive) != 0)
                        Archive = folder;
                    if ((folder.Attributes & FolderAttributes.Drafts) != 0)
                        Drafts = folder;
                    if ((folder.Attributes & FolderAttributes.Flagged) != 0)
                        Flagged = folder;
                    if ((folder.Attributes & FolderAttributes.Junk) != 0)
                        Junk = folder;
                    if ((folder.Attributes & FolderAttributes.Sent) != 0)
                        Sent = folder;
                    if ((folder.Attributes & FolderAttributes.Trash) != 0)
                        Trash = folder;
                }
            } else if ((Capabilities & ImapCapabilities.XList) != 0) {
                var list = new List<ImapFolder> ();

                var ic = QueueCommand (cancellationToken, null, "XLIST \"\" \"*\"\r\n");
                ic.RegisterUntaggedHandler ("XLIST", ImapUtils.HandleUntaggedListResponse);
                ic.UserData = list;

                Wait (ic);

                ImapUtils.LookupParentFolders (this, list, cancellationToken);

                for (int i = 0; i < list.Count; i++) {
                    folder = list[i];

                    if ((folder.Attributes & FolderAttributes.All) != 0)
                        All = folder;
                    if ((folder.Attributes & FolderAttributes.Archive) != 0)
                        Archive = folder;
                    if ((folder.Attributes & FolderAttributes.Drafts) != 0)
                        Drafts = folder;
                    if ((folder.Attributes & FolderAttributes.Flagged) != 0)
                        Flagged = folder;
                    if ((folder.Attributes & FolderAttributes.Junk) != 0)
                        Junk = folder;
                    if ((folder.Attributes & FolderAttributes.Sent) != 0)
                        Sent = folder;
                    if ((folder.Attributes & FolderAttributes.Trash) != 0)
                        Trash = folder;
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// Looks up and sets the <see cref="ImapFolder.ParentFolder"/> property of each of the folders.
        /// </summary>
        /// <param name="engine">The IMAP engine.</param>
        /// <param name="folders">The IMAP folders.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        public static void LookupParentFolders(ImapEngine engine, IEnumerable<ImapFolder> folders, CancellationToken cancellationToken)
        {
            int index;

            foreach (var folder in folders) {
                if (folder.ParentFolder != null)
                    continue;

                if ((index = folder.FullName.LastIndexOf (folder.DirectorySeparator)) == -1)
                    continue;

                if (index == 0)
                    continue;

                var parentName = folder.FullName.Substring (0, index);
                var encodedName = ImapEncoding.Encode (parentName);
                ImapFolder parent;

                if (engine.FolderCache.TryGetValue (encodedName, out parent)) {
                    folder.SetParentFolder (parent);
                    continue;
                }

                var ic = engine.QueueCommand (cancellationToken, null, "LIST \"\" %S\r\n", encodedName);
                ic.RegisterUntaggedHandler ("LIST", ImapUtils.HandleUntaggedListResponse);
                ic.UserData = new List<ImapFolder> ();

                engine.Wait (ic);

                if (!engine.FolderCache.TryGetValue (encodedName, out parent)) {
                    parent = new ImapFolder (engine, encodedName, FolderAttributes.NonExistent, folder.DirectorySeparator);
                    engine.FolderCache.Add (encodedName, parent);
                }

                folder.SetParentFolder (parent);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
        /// </summary>
        /// <remarks>
        /// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
        /// </remarks>
        /// <param name="engine">The IMAP engine that will be sending the command.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="folder">The IMAP folder that the command operates on.</param>
        /// <param name="options">The formatting options.</param>
        /// <param name="format">The command format.</param>
        /// <param name="args">The command arguments.</param>
        public ImapCommand(ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, FormatOptions options, string format, params object[] args)
        {
            UntaggedHandlers  = new Dictionary <string, ImapUntaggedHandler> (StringComparer.OrdinalIgnoreCase);
            Logout            = format.Equals("LOGOUT\r\n", StringComparison.Ordinal);
            RespCodes         = new List <ImapResponseCode> ();
            CancellationToken = cancellationToken;
            Response          = ImapCommandResponse.None;
            Status            = ImapCommandStatus.Created;
            Engine            = engine;
            Folder            = folder;

            using (var builder = new ByteArrayBuilder(1024)) {
                byte[] buf, utf8 = new byte[8];
                int    argc      = 0;
                string str;

                for (int i = 0; i < format.Length; i++)
                {
                    if (format[i] == '%')
                    {
                        switch (format[++i])
                        {
                        case '%':                         // a literal %
                            builder.Append((byte)'%');
                            break;

                        case 'd':                         // an integer
                            str = ((int)args[argc++]).ToString(CultureInfo.InvariantCulture);
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Append(buf, 0, buf.Length);
                            break;

                        case 'u':                         // an unsigned integer
                            str = ((uint)args[argc++]).ToString(CultureInfo.InvariantCulture);
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Append(buf, 0, buf.Length);
                            break;

                        case 's':
                            str = (string)args[argc++];
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Append(buf, 0, buf.Length);
                            break;

                        case 'F':                         // an ImapFolder
                            var utf7 = ((ImapFolder)args[argc++]).EncodedName;
                            AppendString(options, true, builder, utf7);
                            break;

                        case 'L':                         // a MimeMessage or a byte[]
                            var         arg = args[argc++];
                            ImapLiteral literal;
                            byte[]      prefix;

                            if (arg is MimeMessage message)
                            {
                                prefix  = options.International ? UTF8LiteralTokenPrefix : LiteralTokenPrefix;
                                literal = new ImapLiteral(options, message, UpdateProgress);
                            }
                            else
                            {
                                literal = new ImapLiteral(options, (byte[])arg);
                                prefix  = LiteralTokenPrefix;
                            }

                            var  length = literal.Length;
                            bool wait   = true;

                            builder.Append(prefix, 0, prefix.Length);
                            buf = Encoding.ASCII.GetBytes(length.ToString(CultureInfo.InvariantCulture));
                            builder.Append(buf, 0, buf.Length);

                            if (CanUseNonSynchronizedLiteral(Engine, length))
                            {
                                builder.Append((byte)'+');
                                wait = false;
                            }

                            builder.Append(LiteralTokenSuffix, 0, LiteralTokenSuffix.Length);

                            totalSize += length;

                            parts.Add(new ImapCommandPart(builder.ToArray(), literal, wait));
                            builder.Clear();

                            if (prefix == UTF8LiteralTokenPrefix)
                            {
                                builder.Append((byte)')');
                            }
                            break;

                        case 'S':                         // a string which may need to be quoted or made into a literal
                            AppendString(options, true, builder, (string)args[argc++]);
                            break;

                        case 'Q':                         // similar to %S but string must be quoted at a minimum
                            AppendString(options, false, builder, (string)args[argc++]);
                            break;

                        default:
                            throw new FormatException();
                        }
                    }
                    else if (format[i] < 128)
                    {
                        builder.Append((byte)format[i]);
                    }
                    else
                    {
                        int nchars = char.IsSurrogate(format[i]) ? 2 : 1;
                        int nbytes = Encoding.UTF8.GetBytes(format, i, nchars, utf8, 0);
                        builder.Append(utf8, 0, nbytes);
                        i += nchars - 1;
                    }
                }

                parts.Add(new ImapCommandPart(builder.ToArray(), null));
            }
        }
Beispiel #14
0
		/// <summary>
		/// Instantiate a new <see cref="ImapFolder"/>.
		/// </summary>
		/// <remarks>
		/// <para>Creates a new <see cref="ImapFolder"/> instance.</para>
		/// <note type="note">This method's purpose is to allow subclassing <see cref="ImapFolder"/>.</note>
		/// </remarks>
		/// <returns>The IMAP folder instance.</returns>
		/// <param name="args">The constructior arguments.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="args"/> is <c>null</c>.
		/// </exception>
		protected virtual ImapFolder CreateImapFolder (ImapFolderConstructorArgs args)
		{
			var folder = new ImapFolder (args);

			folder.UpdateAppendLimit (AppendLimit);

			return folder;
		}
Beispiel #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
        /// </summary>
        /// <remarks>
        /// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
        /// </remarks>
        /// <param name="engine">The IMAP engine that will be sending the command.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="folder">The IMAP folder that the command operates on.</param>
        /// <param name="options">The formatting options.</param>
        /// <param name="format">The command format.</param>
        /// <param name="args">The command arguments.</param>
        public ImapCommand(ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, FormatOptions options, string format, params object[] args)
        {
            UntaggedHandlers  = new Dictionary <string, ImapUntaggedHandler> ();
            Logout            = format.Equals("LOGOUT\r\n", StringComparison.Ordinal);
            RespCodes         = new List <ImapResponseCode> ();
            CancellationToken = cancellationToken;
            Response          = ImapCommandResponse.None;
            Status            = ImapCommandStatus.Created;
            Engine            = engine;
            Folder            = folder;

            using (var builder = new MemoryStream()) {
                int    argc = 0;
                byte[] buf;
                string str;

                for (int i = 0; i < format.Length; i++)
                {
                    if (format[i] == '%')
                    {
                        switch (format[++i])
                        {
                        case '%':                         // a literal %
                            builder.WriteByte((byte)'%');
                            break;

                        case 'd':                         // an integer
                            str = ((int)args[argc++]).ToString(CultureInfo.InvariantCulture);
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 'u':                         // an unsigned integer
                            str = ((uint)args[argc++]).ToString(CultureInfo.InvariantCulture);
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 's':
                            str = (string)args[argc++];
                            buf = Encoding.ASCII.GetBytes(str);
                            builder.Write(buf, 0, buf.Length);
                            break;

                        case 'F':                         // an ImapFolder
                            var utf7 = ((ImapFolder)args[argc++]).EncodedName;
                            AppendString(options, true, builder, utf7);
                            break;

                        case 'L':                         // a MimeMessage
                            var  literal = new ImapLiteral(options, (MimeMessage)args[argc++], UpdateProgress);
                            var  prefix  = options.International ? UTF8LiteralTokenPrefix : LiteralTokenPrefix;
                            var  length  = literal.Length;
                            bool wait    = true;

                            builder.Write(prefix, 0, prefix.Length);
                            buf = Encoding.ASCII.GetBytes(length.ToString(CultureInfo.InvariantCulture));
                            builder.Write(buf, 0, buf.Length);

                            if (CanUseNonSynchronizedLiteral(Engine, length))
                            {
                                builder.WriteByte((byte)'+');
                                wait = false;
                            }

                            builder.Write(LiteralTokenSuffix, 0, LiteralTokenSuffix.Length);

                            totalSize += length;

                            parts.Add(new ImapCommandPart(builder.ToArray(), literal, wait));
                            builder.SetLength(0);

                            if (options.International)
                            {
                                builder.WriteByte((byte)')');
                            }
                            break;

                        case 'S':                         // a string which may need to be quoted or made into a literal
                            AppendString(options, true, builder, (string)args[argc++]);
                            break;

                        case 'Q':                         // similar to %S but string must be quoted at a minimum
                            AppendString(options, false, builder, (string)args[argc++]);
                            break;

                        default:
                            throw new FormatException();
                        }
                    }
                    else
                    {
                        builder.WriteByte((byte)format[i]);
                    }
                }

                parts.Add(new ImapCommandPart(builder.ToArray(), null));
            }
        }
Beispiel #16
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>
        /// <param name="tok">The token.</param>
        public static void ParseFolderList(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            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":         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(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 (engine.FolderCache.TryGetValue(encodedName, out folder))
            {
                folder.Attributes = (folder.Attributes & ~(FolderAttributes.Marked | FolderAttributes.Unmarked)) | attrs;
            }
            else
            {
                folder = new ImapFolder(engine, encodedName, attrs, delim);
                engine.FolderCache.Add(encodedName, folder);
            }

            list.Add(folder);
        }
Beispiel #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
 /// </summary>
 /// <remarks>
 /// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
 /// </remarks>
 /// <param name="engine">The IMAP engine that will be sending the command.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <param name="folder">The IMAP folder that the command operates on.</param>
 /// <param name="format">The command format.</param>
 /// <param name="args">The command arguments.</param>
 public ImapCommand(ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
     : this(engine, cancellationToken, folder, FormatOptions.Default, format, args)
 {
 }
Beispiel #18
0
 /// <summary>
 /// Queues the command.
 /// </summary>
 /// <returns>The command.</returns>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <param name="folder">The folder that the command operates on.</param>
 /// <param name="format">The command format.</param>
 /// <param name="args">The command arguments.</param>
 public ImapCommand QueueCommand(CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
 {
     return QueueCommand (cancellationToken, folder, FormatOptions.Default, format, args);
 }
Beispiel #19
0
		/// <summary>
		/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
		/// </summary>
		/// <remarks>
		/// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
		/// </remarks>
		/// <param name="engine">The IMAP engine that will be sending the command.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <param name="folder">The IMAP folder that the command operates on.</param>
		/// <param name="format">The command format.</param>
		/// <param name="args">The command arguments.</param>
		public ImapCommand (ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
			: this (engine, cancellationToken, folder, FormatOptions.Default, format, args)
		{
		}
Beispiel #20
0
 public MessageNew(MessageSummaryItems messageSummaryItems, HashSet <HeaderId> fields) : base("MessageNew", true)
 {
     MessageSummaryItems = messageSummaryItems;
     Headers             = ImapFolder.GetHeaderNames(fields);
 }