A specialized query for searching messages in a IMailFolder.
A specialized query for searching messages in a IMailFolder.
		public bool CanReduce (SearchQuery expr)
		{
			if (expr.Term == SearchTerm.Not) {
				var unary = (UnarySearchQuery) expr;

				if (unary.Operand == SearchQuery.Answered)
					return true;

				if (unary.Operand == SearchQuery.Deleted)
					return true;

				if (unary.Operand == SearchQuery.Draft)
					return true;

				if (unary.Operand == SearchQuery.Flagged)
					return true;

				if (unary.Operand == SearchQuery.Recent)
					return true;

				if (unary.Operand == SearchQuery.Seen)
					return true;

				if (unary.Operand.Term == SearchTerm.Keyword)
					return true;

				if (unary.Operand.Term == SearchTerm.NotKeyword)
					return true;
			}

			return false;
		}
		public SearchQuery Reduce (SearchQuery expr)
		{
			if (expr.Term == SearchTerm.Not) {
				var unary = (UnarySearchQuery) expr;

				if (unary.Operand == SearchQuery.Answered)
					return SearchQuery.NotAnswered;

				if (unary.Operand == SearchQuery.Deleted)
					return SearchQuery.NotDeleted;

				if (unary.Operand == SearchQuery.Draft)
					return SearchQuery.NotDraft;

				if (unary.Operand == SearchQuery.Flagged)
					return SearchQuery.NotFlagged;

				if (unary.Operand == SearchQuery.Recent)
					return SearchQuery.NotRecent;

				if (unary.Operand == SearchQuery.Seen)
					return SearchQuery.NotSeen;

				if (unary.Operand.Term == SearchTerm.Keyword)
					return new TextSearchQuery (SearchTerm.NotKeyword, ((TextSearchQuery) unary.Operand).Text);

				if (unary.Operand.Term == SearchTerm.NotKeyword)
					return new TextSearchQuery (SearchTerm.Keyword, ((TextSearchQuery) unary.Operand).Text);
			}

			return expr;
		}
예제 #3
0
		/// <summary>
		/// Creates a conditional AND operation.
		/// </summary>
		/// <remarks>
		/// A conditional AND operation only evaluates the second operand if the first operand evaluates to true.
		/// </remarks>
		/// <returns>A <see cref="BinarySearchQuery"/> representing the conditional AND operation.</returns>
		/// <param name="left">The first operand.</param>
		/// <param name="right">The second operand.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="left"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="right"/> is <c>null</c>.</para>
		/// </exception>
		public static BinarySearchQuery And (SearchQuery left, SearchQuery right)
		{
			if (left == null)
				throw new ArgumentNullException ("left");

			if (right == null)
				throw new ArgumentNullException ("right");

			return new BinarySearchQuery (SearchTerm.And, left, right);
		}
예제 #4
0
		public SearchQuery Reduce (SearchQuery expr)
		{
			if (expr.Term == SearchTerm.And) {
				var and = (BinarySearchQuery) expr;

				if (and.Left.Term == SearchTerm.All)
					return and.Right;

				if (and.Right.Term == SearchTerm.All)
					return and.Left;
			} else if (expr.Term == SearchTerm.Or) {
				var or = (BinarySearchQuery) expr;

				if (or.Left.Term == SearchTerm.All)
					return SearchQuery.All;

				if (or.Right.Term == SearchTerm.All)
					return SearchQuery.All;
			} else if (expr.Term == SearchTerm.Not) {
				var unary = (UnarySearchQuery) expr;

				switch (unary.Operand.Term) {
				case SearchTerm.NotAnswered: return SearchQuery.Answered;
				case SearchTerm.Answered: return SearchQuery.NotAnswered;
				case SearchTerm.NotDeleted: return SearchQuery.Deleted;
				case SearchTerm.Deleted: return SearchQuery.NotDeleted;
				case SearchTerm.NotDraft: return SearchQuery.Draft;
				case SearchTerm.Draft: return SearchQuery.NotDraft;
				case SearchTerm.NotFlagged: return SearchQuery.Flagged;
				case SearchTerm.Flagged: return SearchQuery.NotFlagged;
				case SearchTerm.NotRecent: return SearchQuery.Recent;
				case SearchTerm.Recent: return SearchQuery.NotRecent;
				case SearchTerm.NotSeen: return SearchQuery.Seen;
				case SearchTerm.Seen: return SearchQuery.NotSeen;
				}

				if (unary.Operand.Term == SearchTerm.Keyword)
					return new TextSearchQuery (SearchTerm.NotKeyword, ((TextSearchQuery) unary.Operand).Text);

				if (unary.Operand.Term == SearchTerm.NotKeyword)
					return new TextSearchQuery (SearchTerm.Keyword, ((TextSearchQuery) unary.Operand).Text);
			}

			return expr;
		}
예제 #5
0
		/// <summary>
		/// Asynchronously search the folder for messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// Asynchronously searches the folder for messages matching the specified query,
		/// returning only the specified search results.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="query"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The IMAP server does not support the ESEARCH extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The <see cref="MailFolder"/> is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task<SearchResults> SearchAsync (SearchOptions options, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (query == null)
				throw new ArgumentNullException ("query");

			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Search (options, query, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
예제 #6
0
		/// <summary>
		/// Searches the subset of UIDs in the folder for messages matching the specified query,
		/// returning them in the preferred sort order.
		/// </summary>
		/// <remarks>
		/// Searches the folder for messages matching the specified query and ordering,
		/// returning only the requested search results.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="orderBy">The sort order.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is empty.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the ESORT extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public abstract SearchResults Search (SearchOptions options, IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken));
예제 #7
0
    private bool PrintMails(bool login_only = false)
    {
        try
        {
            this.mailclient.Connect(this.mail_server_name, this.mail_server_port_number, this.mail_server_ssl);
            this.mailclient.Authenticate(this.mail_server_username, this.mail_server_password);

            if (!login_only)
            {
                /*
                 * imapclient.Inbox.Open(MailKit.FolderAccess.ReadOnly);
                 * var uids = imapclient.Inbox.Search(MailKit.Search.SearchQuery.All);
                 * foreach(var uid in uids)
                 * {
                 *  //var message = imapclient.Inbox.GetMessage(uid);
                 *  //Console.Write(message.Body);
                 * }
                 */
                if (this.mailclient is MailKit.Net.Pop3.Pop3Client)
                {
                    MailKit.Net.Pop3.Pop3Client popclient = (MailKit.Net.Pop3.Pop3Client) this.mailclient;
                    for (int i = 0; i < popclient.Count; i++)
                    {
                        var message = popclient.GetMessage(i);

                        if (this.mail_from_condition != null && this.mail_from_condition != "")
                        {
                            bool contains_addr = false;
                            foreach (var addr in message.From)
                            {
                                if (addr is MimeKit.MailboxAddress)
                                {
                                    var mailbox_addr = (MimeKit.MailboxAddress)addr;
                                    if (mailbox_addr.Address == this.mail_from_condition)
                                    {
                                        contains_addr = true;
                                        break;
                                    }
                                }
                            }
                            if (!contains_addr)
                            {
                                continue;
                            }
                        }

                        if (this.mail_subject_condition != null && this.mail_subject_condition != "")
                        {
                            if (!message.Subject.Contains(this.mail_subject_condition))
                            {
                                continue;
                            }
                        }

                        if (this.mail_body_condition != null && this.mail_body_condition != "")
                        {
                            if (!message.TextBody.Contains(this.mail_body_condition))
                            {
                                continue;
                            }
                        }

                        if (SendStringToStarPRNT(message.TextBody))
                        {
                            popclient.DeleteMessage(i);
                        }
                    }
                }
                else if (this.mailclient is MailKit.Net.Imap.ImapClient)
                {
                    MailKit.Net.Imap.ImapClient imapclient = (MailKit.Net.Imap.ImapClient) this.mailclient;

                    MailKit.Search.TextSearchQuery from_query = null, subject_query = null, body_query = null;

                    if (this.mail_from_condition != null && this.mail_from_condition != "")
                    {
                        from_query = MailKit.Search.SearchQuery.FromContains(this.mail_from_condition);
                    }

                    if (this.mail_subject_condition != null && this.mail_subject_condition != "")
                    {
                        subject_query = MailKit.Search.SearchQuery.SubjectContains(this.mail_subject_condition);
                    }

                    if (this.mail_body_condition != null && this.mail_body_condition != "")
                    {
                        body_query = MailKit.Search.SearchQuery.BodyContains(this.mail_body_condition);
                    }

                    MailKit.Search.SearchQuery query = MailKit.Search.SearchQuery.All;
                    if (from_query != null)
                    {
                        Trace.WriteLine(from_query.Term + " " + from_query.Text);
                        query = query.And(from_query);
                    }
                    if (subject_query != null)
                    {
                        Trace.WriteLine(subject_query.Term + " " + subject_query.Text);
                        query = query.And(subject_query);
                    }
                    if (body_query != null)
                    {
                        Trace.WriteLine(body_query.Term + " " + body_query.Text);
                        query = query.And(body_query);
                    }

                    imapclient.Inbox.Open(MailKit.FolderAccess.ReadWrite);
                    var uids         = imapclient.Inbox.Search(query);
                    var deleted_uids = new List <MailKit.UniqueId>();
                    foreach (MailKit.UniqueId uid in uids)
                    {
                        var message = imapclient.Inbox.GetMessage(uid);
                        if (SendStringToStarPRNT(message.TextBody))
                        {
                            imapclient.Inbox.AddFlags(uid, MailKit.MessageFlags.Deleted, true);
                            deleted_uids.Add(uid);
                        }
                    }
                    if (deleted_uids.Count > 0)
                    {
                        imapclient.Inbox.Expunge(deleted_uids);
                    }
                }
            }
        }
        catch (Exception e) when(e is System.IO.IOException || e is System.Net.Sockets.SocketException)
        {
            Trace.TraceError("メールサーバーとの通信に失敗しました。\n" + e.ToString());
            if (this.print_on_error)
            {
                SendStringToStarPRNT("【エラー】" +
                                     DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " +
                                     "メールサーバーとの通信に失敗しました。自動印刷ができない状態です。ネットワークかメールサーバーに異常が発生している可能性があります。このエラーが出続ける場合は管理者にお問い合わせ下さい。\n" +
                                     e.GetType().ToString() + ": " + e.Message + "\n\n\n\n\n\n\n\n\n\n");
            }
        }
        catch (MailKit.Security.AuthenticationException e)
        {
            Trace.TraceError("メールサーバーへのログインに失敗しました。ユーザー名かパスワードが間違っているか、サーバー側でアカウントロックされた可能性があります。\n" + e.ToString());
            if (this.print_on_error)
            {
                SendStringToStarPRNT("【エラー】" +
                                     DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " +
                                     "メールサーバーへのログインに失敗しました。自動印刷ができない状態です。管理者にお問い合わせ下さい。" +
                                     e.Message + "\n\n\n\n\n\n\n\n\n\n");
            }
        }
        catch (Exception e)
        {
            Trace.TraceError("メール処理でエラーが発生しました。\n" + e.ToString());
            if (this.print_on_error)
            {
                SendStringToStarPRNT("【エラー】" +
                                     DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " +
                                     "自動印刷ができない状態です。管理者にお問い合わせ下さい。\n" +
                                     e.GetType().ToString() + ": " + e.Message + "\n\n\n\n\n\n\n\n\n\n");
            }
        }
        finally
        {
            if (this.mailclient.IsConnected)
            {
                this.mailclient.Disconnect(true);
            }
        }

        return(true);
    }
예제 #8
0
		/// <summary>
		/// Search the folder for messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// Searches the folder for messages matching the specified query,
		/// returning only the specified search results.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="query"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The IMAP server does not support the ESEARCH extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The <see cref="MailFolder"/> is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public abstract SearchResults Search (SearchOptions options, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken));
예제 #9
0
		public Task<SearchResults> SearchAsync (SearchOptions options, IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken))
		{
			return SortAsync (options, uids, query, orderBy, cancellationToken);
		}
예제 #10
0
		/// <summary>
		/// Creates a logical negation of the specified expression.
		/// </summary>
		/// <remarks>
		/// Creates a logical negation of the specified expression.
		/// </remarks>
		/// <returns>A <see cref="UnarySearchQuery"/>.</returns>
		/// <param name="expr">The expression</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="expr"/> is <c>null</c>.
		/// </exception>
		public static UnarySearchQuery Not (SearchQuery expr)
		{
			if (expr == null)
				throw new ArgumentNullException ("expr");

			return new UnarySearchQuery (SearchTerm.Not, expr);
		}
예제 #11
0
        void BuildQuery(StringBuilder builder, SearchQuery query, List<string> args, bool parens)
        {
            NumericSearchQuery numeric;
            HeaderSearchQuery header;
            BinarySearchQuery binary;
            UnarySearchQuery unary;
            DateSearchQuery date;
            TextSearchQuery text;

            if (builder.Length > 0)
                builder.Append (' ');

            switch (query.Term) {
            case SearchTerm.All:
                builder.Append ("ALL");
                break;
            case SearchTerm.And:
                binary = (BinarySearchQuery) query;
                if (parens)
                    builder.Append ('(');
                BuildQuery (builder, binary.Left, args, false);
                BuildQuery (builder, binary.Right, args, false);
                if (parens)
                    builder.Append (')');
                break;
            case SearchTerm.Answered:
                builder.Append ("ANSWERED");
                break;
            case SearchTerm.BccContains:
                text = (TextSearchQuery) query;
                builder.Append ("BCC %S");
                args.Add (text.Text);
                break;
            case SearchTerm.BodyContains:
                text = (TextSearchQuery) query;
                builder.Append ("BODY %S");
                args.Add (text.Text);
                break;
            case SearchTerm.CcContains:
                text = (TextSearchQuery) query;
                builder.Append ("CC %S");
                args.Add (text.Text);
                break;
            case SearchTerm.Deleted:
                builder.Append ("DELETED");
                break;
            case SearchTerm.DeliveredAfter:
                date = (DateSearchQuery) query;
                builder.AppendFormat ("SINCE {0}", date.Date.ToString ("d-MMM-yyyy", CultureInfo.InvariantCulture));
                break;
            case SearchTerm.DeliveredBefore:
                date = (DateSearchQuery) query;
                builder.AppendFormat ("BEFORE {0}", date.Date.ToString ("d-MMM-yyyy", CultureInfo.InvariantCulture));
                break;
            case SearchTerm.DeliveredOn:
                date = (DateSearchQuery) query;
                builder.AppendFormat ("ON {0}", date.Date.ToString ("d-MMM-yyyy", CultureInfo.InvariantCulture));
                break;
            case SearchTerm.Draft:
                builder.Append ("DRAFT");
                break;
            case SearchTerm.Flagged:
                builder.Append ("FLAGGED");
                break;
            case SearchTerm.FromContains:
                text = (TextSearchQuery) query;
                builder.Append ("FROM %S");
                args.Add (text.Text);
                break;
            case SearchTerm.HeaderContains:
                header = (HeaderSearchQuery) query;
                builder.AppendFormat ("HEADER {0} %S", header.Field);
                args.Add (header.Value);
                break;
            case SearchTerm.Keyword:
                text = (TextSearchQuery) query;
                builder.Append ("KEYWORD %S");
                args.Add (text.Text);
                break;
            case SearchTerm.LargerThan:
                numeric = (NumericSearchQuery) query;
                builder.AppendFormat ("LARGER {0}", numeric.Value);
                break;
            case SearchTerm.MessageContains:
                text = (TextSearchQuery) query;
                builder.Append ("TEXT %S");
                args.Add (text.Text);
                break;
            case SearchTerm.ModSeq:
                numeric = (NumericSearchQuery) query;
                builder.AppendFormat ("MODSEQ {0}", numeric.Value);
                break;
            case SearchTerm.New:
                builder.Append ("NEW");
                break;
            case SearchTerm.Not:
                builder.Append ("NOT");
                unary = (UnarySearchQuery) query;
                BuildQuery (builder, unary.Operand, args, true);
                break;
            case SearchTerm.NotAnswered:
                builder.Append ("UNANSWERED");
                break;
            case SearchTerm.NotDeleted:
                builder.Append ("UNDELETED");
                break;
            case SearchTerm.NotDraft:
                builder.Append ("UNDRAFT");
                break;
            case SearchTerm.NotFlagged:
                builder.Append ("UNFLAGGED");
                break;
            case SearchTerm.NotKeyword:
                text = (TextSearchQuery) query;
                builder.Append ("UNKEYWORD %S");
                args.Add (text.Text);
                break;
            case SearchTerm.NotRecent:
                builder.Append ("OLD");
                break;
            case SearchTerm.NotSeen:
                builder.Append ("UNSEEN");
                break;
            case SearchTerm.Or:
                builder.Append ("OR");
                binary = (BinarySearchQuery) query;
                BuildQuery (builder, binary.Left, args, true);
                BuildQuery (builder, binary.Right, args, true);
                break;
            case SearchTerm.Recent:
                builder.Append ("RECENT");
                break;
            case SearchTerm.Seen:
                builder.Append ("SEEN");
                break;
            case SearchTerm.SentAfter:
                date = (DateSearchQuery) query;
                builder.AppendFormat ("SENTSINCE {0}", date.Date.ToString ("d-MMM-yyyy", CultureInfo.InvariantCulture));
                break;
            case SearchTerm.SentBefore:
                date = (DateSearchQuery) query;
                builder.AppendFormat ("SENTBEFORE {0}", date.Date.ToString ("d-MMM-yyyy", CultureInfo.InvariantCulture));
                break;
            case SearchTerm.SentOn:
                date = (DateSearchQuery) query;
                builder.AppendFormat ("SENTON {0}", date.Date.ToString ("d-MMM-yyyy", CultureInfo.InvariantCulture));
                break;
            case SearchTerm.SmallerThan:
                numeric = (NumericSearchQuery) query;
                builder.AppendFormat ("SMALLER {0}", numeric.Value);
                break;
            case SearchTerm.SubjectContains:
                text = (TextSearchQuery) query;
                builder.Append ("SUBJECT %S");
                args.Add (text.Text);
                break;
            case SearchTerm.ToContains:
                text = (TextSearchQuery) query;
                builder.Append ("TO %S");
                args.Add (text.Text);
                break;
            case SearchTerm.Uid:
                break;
            case SearchTerm.GMailMessageId:
                if ((Engine.Capabilities & ImapCapabilities.GMailExt1) == 0)
                    throw new NotSupportedException ("The X-GM-MSGID search term is not supported by the IMAP server.");

                numeric = (NumericSearchQuery) query;
                builder.AppendFormat ("X-GM-MSGID {0}", numeric.Value);
                break;
            case SearchTerm.GMailThreadId:
                if ((Engine.Capabilities & ImapCapabilities.GMailExt1) == 0)
                    throw new NotSupportedException ("The X-GM-THRID search term is not supported by the IMAP server.");

                numeric = (NumericSearchQuery) query;
                builder.AppendFormat ("X-GM-THRID {0}", numeric.Value);
                break;
            default:
                throw new ArgumentOutOfRangeException ();
            }
        }
예제 #12
0
		/// <summary>
		/// Thread the messages in the folder that match the search query using the specified threading algorithm.
		/// </summary>
		/// <remarks>
		/// The <see cref="MessageThread.UniqueId"/> can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of message threads.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="algorithm">The threading algorithm to use.</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="algorithm"/> is not supported.
		/// </exception>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="uids"/> is empty.</para>
		/// <para>-or-</para>
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the mail store.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the THREAD extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public abstract IList<MessageThread> Thread (IList<UniqueId> uids, ThreadingAlgorithm algorithm, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken));
예제 #13
0
        /// <summary>
        /// Searches the subset of UIDs in the folder for messages matching the specified query,
        /// returning them in the preferred sort order.
        /// </summary>
        /// <remarks>
        /// The returned array of unique identifiers will be sorted in the preferred order and
        /// can be used with <see cref="IFolder.GetMessage(UniqueId,CancellationToken)"/>.
        /// </remarks>
        /// <returns>An array of matching UIDs.</returns>
        /// <param name="uids">The subset of UIDs</param>
        /// <param name="query">The search query.</param>
        /// <param name="orderBy">The sort order.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="uids"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="query"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="orderBy"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// <para><paramref name="uids"/> contains one or more invalid UIDs.</para>
        /// <para>-or-</para>
        /// <para><paramref name="orderBy"/> is empty.</para>
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
        /// <para>-or-</para>
        /// <para>The server does not support the SORT extension.</para>
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="ImapClient"/> has been disposed.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// <para>The <see cref="ImapClient"/> is not connected.</para>
        /// <para>-or-</para>
        /// <para>The <see cref="ImapClient"/> is not authenticated.</para>
        /// <para>-or-</para>
        /// <para>The folder is not currently open.</para>
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="ImapProtocolException">
        /// The server's response contained unexpected tokens.
        /// </exception>
        /// <exception cref="ImapCommandException">
        /// The server replied with a NO or BAD response.
        /// </exception>
        public UniqueId[] Search(UniqueId[] uids, SearchQuery query, OrderBy[] orderBy, CancellationToken cancellationToken)
        {
            var set = ImapUtils.FormatUidSet (uids);
            var args = new List<string> ();

            if (query == null)
                throw new ArgumentNullException ("query");

            if (orderBy == null)
                throw new ArgumentNullException ("orderBy");

            if (orderBy.Length == 0)
                throw new ArgumentException ("No sort order provided.", "orderBy");

            CheckState (true, false);

            if ((Engine.Capabilities & ImapCapabilities.Sort) == 0)
                throw new NotSupportedException ("The IMAP server does not support the SORT extension.");

            if (uids.Length == 0)
                return new UniqueId[0];

            var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
            var expr = BuildQueryExpression (optimized, args);
            var order = BuildSortOrder (orderBy);
            var command = "UID SORT " + order + " ";

            if ((Engine.Capabilities & ImapCapabilities.ESort) != 0)
                command += "RETURN () ";

            command += "UTF-8 UID " + set + " " + expr + "\r\n";

            var ic = Engine.QueueCommand (cancellationToken, this, command, args.ToArray ());
            if ((Engine.Capabilities & ImapCapabilities.ESort) != 0)
                ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches);
            else
                ic.RegisterUntaggedHandler ("SORT", SearchMatches);

            Engine.Wait (ic);

            ProcessResponseCodes (ic, null);

            if (ic.Result != ImapCommandResult.Ok)
                throw new ImapCommandException ("SORT", ic.Result);

            return (UniqueId[]) ic.UserData;
        }
예제 #14
0
        /// <summary>
        /// Threads the messages in the folder that match the search query using the specified threading algorithm.
        /// </summary>
        /// <remarks>
        /// The <see cref="MessageThread.UniqueId"/> can be used with <see cref="IFolder.GetMessage(UniqueId,CancellationToken)"/>.
        /// </remarks>
        /// <returns>An array of message threads.</returns>
        /// <param name="algorithm">The threading algorithm to use.</param>
        /// <param name="query">The search query.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <paramref name="algorithm"/> is not supported.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="query"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
        /// <para>-or-</para>
        /// <para>The server does not support the THREAD extension.</para>
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="ImapClient"/> has been disposed.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// <para>The <see cref="ImapClient"/> is not connected.</para>
        /// <para>-or-</para>
        /// <para>The <see cref="ImapClient"/> is not authenticated.</para>
        /// <para>-or-</para>
        /// <para>The folder is not currently open.</para>
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="ImapProtocolException">
        /// The server's response contained unexpected tokens.
        /// </exception>
        /// <exception cref="ImapCommandException">
        /// The server replied with a NO or BAD response.
        /// </exception>
        public MessageThread[] Thread(ThreadingAlgorithm algorithm, SearchQuery query, CancellationToken cancellationToken)
        {
            var method = algorithm.ToString ().ToUpperInvariant ();
            var args = new List<string> ();

            if ((Engine.Capabilities & ImapCapabilities.Thread) == 0)
                throw new NotSupportedException ("The IMAP server does not support the THREAD extension.");

            if (!Engine.ThreadingAlgorithms.Contains (algorithm))
                throw new ArgumentOutOfRangeException ("algorithm", "The specified threading algorithm is not supported.");

            if (query == null)
                throw new ArgumentNullException ("query");

            CheckState (true, false);

            var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
            var expr = BuildQueryExpression (optimized, args);
            var command = "UID THREAD " + method + " UTF-8 ";

            command += expr + "\r\n";

            var ic = Engine.QueueCommand (cancellationToken, this, command, args.ToArray ());
            ic.RegisterUntaggedHandler ("THREAD", ThreadMatches);

            Engine.Wait (ic);

            ProcessResponseCodes (ic, null);

            if (ic.Result != ImapCommandResult.Ok)
                throw new ImapCommandException ("THREAD", ic.Result);

            return (MessageThread[]) ic.UserData;
        }
예제 #15
0
        /// <summary>
        /// Searches the subset of UIDs in the folder for messages matching the specified query.
        /// </summary>
        /// <remarks>
        /// The returned array of unique identifiers can be used with <see cref="IFolder.GetMessage(UniqueId,CancellationToken)"/>.
        /// </remarks>
        /// <returns>An array of matching UIDs.</returns>
        /// <param name="uids">The subset of UIDs</param>
        /// <param name="query">The search query.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="uids"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="query"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="uids"/> contains one or more invalid UIDs.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="ImapClient"/> has been disposed.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// <para>The <see cref="ImapClient"/> is not connected.</para>
        /// <para>-or-</para>
        /// <para>The <see cref="ImapClient"/> is not authenticated.</para>
        /// <para>-or-</para>
        /// <para>The folder is not currently open.</para>
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="ImapProtocolException">
        /// The server's response contained unexpected tokens.
        /// </exception>
        /// <exception cref="ImapCommandException">
        /// The server replied with a NO or BAD response.
        /// </exception>
        public UniqueId[] Search(UniqueId[] uids, SearchQuery query, CancellationToken cancellationToken)
        {
            var set = ImapUtils.FormatUidSet (uids);
            var args = new List<string> ();

            if (query == null)
                throw new ArgumentNullException ("query");

            CheckState (true, false);

            if (uids.Length == 0)
                return new UniqueId[0];

            var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
            var expr = BuildQueryExpression (optimized, args);
            var command = "UID SEARCH ";

            if ((Engine.Capabilities & ImapCapabilities.ESearch) != 0)
                command += "RETURN () ";

            if (args.Count > 0)
                command += "CHARSET UTF-8 ";

            command += "UID " + set + " " + expr + "\r\n";

            var ic = Engine.QueueCommand (cancellationToken, this, command, args.ToArray ());
            if ((Engine.Capabilities & ImapCapabilities.ESearch) != 0)
                ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches);
            else
                ic.RegisterUntaggedHandler ("SEARCH", SearchMatches);

            Engine.Wait (ic);

            ProcessResponseCodes (ic, null);

            if (ic.Result != ImapCommandResult.Ok)
                throw new ImapCommandException ("SEARCH", ic.Result);

            return (UniqueId[]) ic.UserData;
        }
예제 #16
0
		/// <summary>
		/// Creates a conditional AND operation.
		/// </summary>
		/// <remarks>
		/// A conditional AND operation only evaluates the second operand if the first operand evaluates to true.
		/// </remarks>
		/// <returns>A <see cref="BinarySearchQuery"/> representing the conditional AND operation.</returns>
		/// <param name="expr">An additional query to execute.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="expr"/> is <c>null</c>.
		/// </exception>
		public BinarySearchQuery And (SearchQuery expr)
		{
			if (expr == null)
				throw new ArgumentNullException ("expr");

			return new BinarySearchQuery (SearchTerm.And, this, expr);
		}
예제 #17
0
		/// <summary>
		/// Asynchronously sort messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// The returned array of unique identifiers will be sorted in the preferred order and
		/// can be used with <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of matching UIDs in the specified sort order.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="orderBy">The sort order.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="uids"/> is empty.</para>
		/// <para>-or-</para>
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is empty.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported.</para>
		/// <para>-or-</para>
		/// <para>The server does not support sorting search results.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task<IList<UniqueId>> SortAsync (IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (uids == null)
				throw new ArgumentNullException (nameof (uids));

			if (query == null)
				throw new ArgumentNullException (nameof (query));

			if (orderBy == null)
				throw new ArgumentNullException (nameof (orderBy));

			if (orderBy.Count == 0)
				throw new ArgumentException ("No sort order provided.", nameof (orderBy));

			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Sort (uids, query, orderBy, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
예제 #18
0
		/// <summary>
		/// Asynchronously searches the subset of UIDs in the folder for messages matching the specified query,
		/// returning them in the preferred sort order.
		/// </summary>
		/// <remarks>
		/// Asynchronously searches the folder for messages matching the specified query and ordering,
		/// returning only the requested search results.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="orderBy">The sort order.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is empty.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the ESORT extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task<SearchResults> SearchAsync (SearchOptions options, IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (uids == null)
				throw new ArgumentNullException ("uids");

			if (query == null)
				throw new ArgumentNullException ("query");

			if (orderBy == null)
				throw new ArgumentNullException ("orderBy");

			if (orderBy.Count == 0)
				throw new ArgumentException ("No sort order provided.", "orderBy");

			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Search (options, uids, query, orderBy, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
예제 #19
0
파일: ImapFolder.cs 프로젝트: dcga/MailKit
		void BuildQuery (StringBuilder builder, SearchQuery query, List<string> args, bool parens, ref bool ascii)
		{
			TextSearchQuery text = null;
			NumericSearchQuery numeric;
			HeaderSearchQuery header;
			BinarySearchQuery binary;
			UnarySearchQuery unary;
			DateSearchQuery date;
			bool isFlag;

			if (builder.Length > 0)
				builder.Append (' ');

			switch (query.Term) {
			case SearchTerm.All:
				builder.Append ("ALL");
				break;
			case SearchTerm.And:
				binary = (BinarySearchQuery) query;
				if (parens)
					builder.Append ('(');
				BuildQuery (builder, binary.Left, args, false, ref ascii);
				BuildQuery (builder, binary.Right, args, false, ref ascii);
				if (parens)
					builder.Append (')');
				break;
			case SearchTerm.Answered:
				builder.Append ("ANSWERED");
				break;
			case SearchTerm.BccContains:
				text = (TextSearchQuery) query;
				builder.Append ("BCC %S");
				args.Add (text.Text);
				break;
			case SearchTerm.BodyContains:
				text = (TextSearchQuery) query;
				builder.Append ("BODY %S");
				args.Add (text.Text);
				break;
			case SearchTerm.CcContains:
				text = (TextSearchQuery) query;
				builder.Append ("CC %S");
				args.Add (text.Text);
				break;
			case SearchTerm.Deleted:
				builder.Append ("DELETED");
				break;
			case SearchTerm.DeliveredAfter:
				date = (DateSearchQuery) query;
				builder.AppendFormat ("SINCE {0}", FormatDateTime (date.Date));
				break;
			case SearchTerm.DeliveredBefore:
				date = (DateSearchQuery) query;
				builder.AppendFormat ("BEFORE {0}", FormatDateTime (date.Date));
				break;
			case SearchTerm.DeliveredOn:
				date = (DateSearchQuery) query;
				builder.AppendFormat ("ON {0}", FormatDateTime (date.Date));
				break;
			case SearchTerm.Draft:
				builder.Append ("DRAFT");
				break;
			case SearchTerm.Flagged:
				builder.Append ("FLAGGED");
				break;
			case SearchTerm.FromContains:
				text = (TextSearchQuery) query;
				builder.Append ("FROM %S");
				args.Add (text.Text);
				break;
			case SearchTerm.Fuzzy:
				if ((Engine.Capabilities & ImapCapabilities.FuzzySearch) == 0)
					throw new NotSupportedException ("The FUZZY search term is not supported by the IMAP server.");

				builder.Append ("FUZZY");
				unary = (UnarySearchQuery) query;
				BuildQuery (builder, unary.Operand, args, true, ref ascii);
				break;
			case SearchTerm.HeaderContains:
				header = (HeaderSearchQuery) query;
				builder.AppendFormat ("HEADER {0} %S", header.Field);
				args.Add (header.Value);
				break;
			case SearchTerm.Keyword:
				text = (TextSearchQuery) query;
				builder.Append ("KEYWORD %S");
				args.Add (text.Text);
				break;
			case SearchTerm.LargerThan:
				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("LARGER {0}", numeric.Value);
				break;
			case SearchTerm.MessageContains:
				text = (TextSearchQuery) query;
				builder.Append ("TEXT %S");
				args.Add (text.Text);
				break;
			case SearchTerm.ModSeq:
				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("MODSEQ {0}", numeric.Value);
				break;
			case SearchTerm.New:
				builder.Append ("NEW");
				break;
			case SearchTerm.Not:
				builder.Append ("NOT");
				unary = (UnarySearchQuery) query;
				BuildQuery (builder, unary.Operand, args, true, ref ascii);
				break;
			case SearchTerm.NotAnswered:
				builder.Append ("UNANSWERED");
				break;
			case SearchTerm.NotDeleted:
				builder.Append ("UNDELETED");
				break;
			case SearchTerm.NotDraft:
				builder.Append ("UNDRAFT");
				break;
			case SearchTerm.NotFlagged:
				builder.Append ("UNFLAGGED");
				break;
			case SearchTerm.NotKeyword:
				text = (TextSearchQuery) query;
				builder.Append ("UNKEYWORD %S");
				args.Add (text.Text);
				break;
			case SearchTerm.NotRecent:
				builder.Append ("OLD");
				break;
			case SearchTerm.NotSeen:
				builder.Append ("UNSEEN");
				break;
			case SearchTerm.Older:
				if ((Engine.Capabilities & ImapCapabilities.Within) == 0)
					throw new NotSupportedException ("The OLDER search term is not supported by the IMAP server.");

				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("OLDER {0}", numeric.Value);
				break;
			case SearchTerm.Or:
				builder.Append ("OR");
				binary = (BinarySearchQuery) query;
				BuildQuery (builder, binary.Left, args, true, ref ascii);
				BuildQuery (builder, binary.Right, args, true, ref ascii);
				break;
			case SearchTerm.Recent:
				builder.Append ("RECENT");
				break;
			case SearchTerm.Seen:
				builder.Append ("SEEN");
				break;
			case SearchTerm.SentAfter:
				date = (DateSearchQuery) query;
				builder.AppendFormat ("SENTSINCE {0}", FormatDateTime (date.Date));
				break;
			case SearchTerm.SentBefore:
				date = (DateSearchQuery) query;
				builder.AppendFormat ("SENTBEFORE {0}", FormatDateTime (date.Date));
				break;
			case SearchTerm.SentOn:
				date = (DateSearchQuery) query;
				builder.AppendFormat ("SENTON {0}", FormatDateTime (date.Date));
				break;
			case SearchTerm.SmallerThan:
				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("SMALLER {0}", numeric.Value);
				break;
			case SearchTerm.SubjectContains:
				text = (TextSearchQuery) query;
				builder.Append ("SUBJECT %S");
				args.Add (text.Text);
				break;
			case SearchTerm.ToContains:
				text = (TextSearchQuery) query;
				builder.Append ("TO %S");
				args.Add (text.Text);
				break;
			case SearchTerm.Uid:
				break;
			case SearchTerm.Younger:
				if ((Engine.Capabilities & ImapCapabilities.Within) == 0)
					throw new NotSupportedException ("The YOUNGER search term is not supported by the IMAP server.");

				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("YOUNGER {0}", numeric.Value);
				break;
			case SearchTerm.GMailMessageId:
				if ((Engine.Capabilities & ImapCapabilities.GMailExt1) == 0)
					throw new NotSupportedException ("The X-GM-MSGID search term is not supported by the IMAP server.");

				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("X-GM-MSGID {0}", numeric.Value);
				break;
			case SearchTerm.GMailThreadId:
				if ((Engine.Capabilities & ImapCapabilities.GMailExt1) == 0)
					throw new NotSupportedException ("The X-GM-THRID search term is not supported by the IMAP server.");

				numeric = (NumericSearchQuery) query;
				builder.AppendFormat ("X-GM-THRID {0}", numeric.Value);
				break;
			case SearchTerm.GMailLabels:
				if ((Engine.Capabilities & ImapCapabilities.GMailExt1) == 0)
					throw new NotSupportedException ("The X-GM-LABELS search term is not supported by the IMAP server.");

				text = (TextSearchQuery) query;

				if ((isFlag = text.Text[0] == '\\')) {
					for (int i = 1; i < text.Text.Length; i++) {
						if (text.Text[i] < 'A' || (text.Text[i] > 'Z' && text.Text[i] < 'a') || text.Text[i] > 'z') {
							isFlag = false;
							break;
						}
					}
				}

				if (isFlag) {
					builder.AppendFormat ("X-GM-LABELS {0}", text.Text);
				} else {
					builder.Append ("X-GM-LABELS %S");
					args.Add (text.Text);
				}
				break;
			case SearchTerm.GMailRaw:
				if ((Engine.Capabilities & ImapCapabilities.GMailExt1) == 0)
					throw new NotSupportedException ("The X-GM-RAW search term is not supported by the IMAP server.");

				text = (TextSearchQuery) query;
				builder.Append ("X-GM-RAW %S");
				args.Add (text.Text);
				break;
			default:
				throw new ArgumentOutOfRangeException ();
			}

			if (text != null && !IsAscii (text.Text))
				ascii = false;
		}
예제 #20
0
		/// <summary>
		/// Asynchronously thread the messages in the folder that match the search query using the specified threading algorithm.
		/// </summary>
		/// <remarks>
		/// The <see cref="MessageThread.UniqueId"/> can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of message threads.</returns>
		/// <param name="algorithm">The threading algorithm to use.</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="algorithm"/> is not supported.
		/// </exception>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="query"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the mail store.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the THREAD extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task<IList<MessageThread>> ThreadAsync (ThreadingAlgorithm algorithm, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (query == null)
				throw new ArgumentNullException ("query");

			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Thread (algorithm, query, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
예제 #21
0
파일: ImapFolder.cs 프로젝트: dcga/MailKit
		/// <summary>
		/// Searches the subset of UIDs in the folder for messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// The returned array of unique identifiers can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of matching UIDs.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// One or more of the <paramref name="uids"/> is invalid.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="ImapClient"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="ImapClient"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="ImapClient"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The <see cref="ImapFolder"/> is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ImapProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="ImapCommandException">
		/// The server replied with a NO or BAD response.
		/// </exception>
		public override IList<UniqueId> Search (IList<UniqueId> uids, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			var set = ImapUtils.FormatUidSet (uids);
			var args = new List<string> ();
			string charset;

			if (query == null)
				throw new ArgumentNullException ("query");

			CheckState (true, false);

			if (uids.Count == 0)
				return new UniqueId[0];

			var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
			var expr = BuildQueryExpression (optimized, args, out charset);
			var command = "UID SEARCH ";

			if ((Engine.Capabilities & ImapCapabilities.ESearch) != 0)
				command += "RETURN () ";

			if (args.Count > 0 && !Engine.UTF8Enabled)
				command += "CHARSET " + charset + " ";

			command += "UID " + set + " " + expr + "\r\n";

			var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ());
			if ((Engine.Capabilities & ImapCapabilities.ESearch) != 0)
				ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches);

			// Note: always register the untagged SEARCH handler because some servers will brokenly
			// respond with "* SEARCH ..." instead of "* ESEARCH ..." even when using the extended
			// search syntax.
			ic.RegisterUntaggedHandler ("SEARCH", SearchMatches);

			Engine.QueueCommand (ic);
			Engine.Wait (ic);

			ProcessResponseCodes (ic, null);

			if (ic.Response != ImapCommandResponse.Ok)
				throw ImapCommandException.Create ("SEARCH", ic);

			var results = (SearchResults) ic.UserData;

			if (results == null)
				return new UniqueId[0];

			return results.UniqueIds;
		}
예제 #22
0
		/// <summary>
		/// Asynchronously thread the messages in the folder that match the search query using the specified threading algorithm.
		/// </summary>
		/// <remarks>
		/// The <see cref="MessageThread.UniqueId"/> can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of message threads.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="algorithm">The threading algorithm to use.</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="algorithm"/> is not supported.
		/// </exception>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="uids"/> is empty.</para>
		/// <para>-or-</para>
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the mail store.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the THREAD extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task<IList<MessageThread>> ThreadAsync (IList<UniqueId> uids, ThreadingAlgorithm algorithm, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (uids == null)
				throw new ArgumentNullException ("uids");

			if (uids.Count == 0)
				throw new ArgumentException ("No uids were specified.", "uids");

			if (query == null)
				throw new ArgumentNullException ("query");

			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Thread (uids, algorithm, query, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
예제 #23
0
파일: ImapFolder.cs 프로젝트: dcga/MailKit
		/// <summary>
		/// Searches the subset of UIDs in the folder for messages matching the specified query,
		/// returning them in the preferred sort order.
		/// </summary>
		/// <remarks>
		/// Searches the folder for messages matching the specified query and ordering,
		/// returning only the requested search results.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="orderBy">The sort order.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is empty.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The IMAP server does not support the ESORT extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="ImapClient"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="ImapClient"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="ImapClient"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The <see cref="ImapFolder"/> is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ImapProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="ImapCommandException">
		/// The server replied with a NO or BAD response.
		/// </exception>
		public override SearchResults Search (SearchOptions options, IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken))
		{
			var set = ImapUtils.FormatUidSet (uids);
			var args = new List<string> ();
			string charset;

			if (query == null)
				throw new ArgumentNullException ("query");

			if (orderBy == null)
				throw new ArgumentNullException ("orderBy");

			if (orderBy.Count == 0)
				throw new ArgumentException ("No sort order provided.", "orderBy");

			CheckState (true, false);

			if ((Engine.Capabilities & ImapCapabilities.ESort) == 0)
				throw new NotSupportedException ("The IMAP server does not support the ESORT extension.");

			if ((Engine.Capabilities & ImapCapabilities.SortDisplay) == 0) {
				for (int i = 0; i < orderBy.Count; i++) {
					if (orderBy[i].Type == OrderByType.DisplayFrom || orderBy[i].Type == OrderByType.DisplayTo)
						throw new NotSupportedException ("The IMAP server does not support the SORT=DISPLAY extension.");
				}
			}

			if (uids.Count == 0)
				return new SearchResults ();

			var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
			var expr = BuildQueryExpression (optimized, args, out charset);
			var order = BuildSortOrder (orderBy);
			var command = "UID SORT RETURN (";

			if ((options & SearchOptions.Count) != 0)
				command += "COUNT ";
			if ((options & SearchOptions.Min) != 0)
				command += "MIN ";
			if ((options & SearchOptions.Max) != 0)
				command += "MAX ";
			command = command.TrimEnd ();
			command += ") ";

			command += order + " " + charset + " UID " + set + " " + expr + "\r\n";

			var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ());
			ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches);
			ic.UserData = new SearchResults ();

			Engine.QueueCommand (ic);
			Engine.Wait (ic);

			ProcessResponseCodes (ic, null);

			if (ic.Response != ImapCommandResponse.Ok)
				throw ImapCommandException.Create ("SORT", ic);

			return (SearchResults) ic.UserData;
		}
예제 #24
0
        string BuildQueryExpression(SearchQuery query, List<string> args)
        {
            var builder = new StringBuilder ();

            BuildQuery (builder, query, args, false);

            return builder.ToString ();
        }
예제 #25
0
		/// <summary>
		/// Sort messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// Searches the folder for messages matching the specified query, returning the search results in the specified sort order.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="orderBy">The sort order.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="uids"/> is empty.</para>
		/// <para>-or-</para>
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is empty.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the specified search options.</para>
		/// <para>-or-</para>
		/// <para>The server does not support sorting search results.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual SearchResults Sort (SearchOptions options, IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken))
		{
			var uidSet = new UidSearchQuery (uids);

			if (query == null)
				throw new ArgumentNullException (nameof (query));

			return Sort (options, uidSet.And (query), orderBy, cancellationToken);
		}
예제 #26
0
파일: ImapFolder.cs 프로젝트: dcga/MailKit
		string BuildQueryExpression (SearchQuery query, List<string> args, out string charset)
		{
			var builder = new StringBuilder ();
			bool ascii = true;

			BuildQuery (builder, query, args, false, ref ascii);

			charset = ascii ? "US-ASCII" : "UTF-8";

			return builder.ToString ();
		}
예제 #27
0
		/// <summary>
		/// Search the folder for messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// The returned array of unique identifiers can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of matching UIDs.</returns>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="query"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// One or more search terms in the <paramref name="query"/> are not supported by the mail store.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public abstract IList<UniqueId> Search (SearchQuery query, CancellationToken cancellationToken = default (CancellationToken));
예제 #28
0
파일: ImapFolder.cs 프로젝트: dcga/MailKit
		/// <summary>
		/// Searches the subset of UIDs in the folder for messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// Searches the fsubset of UIDs in the folder for messages matching the specified query,
		/// returning only the specified search results.
		/// </remarks>
		/// <returns>The search results.</returns>
		/// <param name="options">The search options.</param>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// One or more of the <paramref name="uids"/> is invalid.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The IMAP server does not support the ESEARCH extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="ImapClient"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="ImapClient"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="ImapClient"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The <see cref="ImapFolder"/> is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ImapProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="ImapCommandException">
		/// The server replied with a NO or BAD response.
		/// </exception>
		public override SearchResults Search (SearchOptions options, IList<UniqueId> uids, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			var set = ImapUtils.FormatUidSet (uids);
			var args = new List<string> ();
			string charset;

			if (query == null)
				throw new ArgumentNullException ("query");

			CheckState (true, false);

			if ((Engine.Capabilities & ImapCapabilities.ESearch) == 0)
				throw new NotSupportedException ("The IMAP server does not support the ESEARCH extension.");

			if (uids.Count == 0)
				return new SearchResults ();

			var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
			var expr = BuildQueryExpression (optimized, args, out charset);
			var command = "UID SEARCH RETURN (";

			if ((options & SearchOptions.Count) != 0)
				command += "COUNT ";
			if ((options & SearchOptions.Min) != 0)
				command += "MIN ";
			if ((options & SearchOptions.Max) != 0)
				command += "MAX ";
			command = command.TrimEnd ();
			command += ") ";

			if (args.Count > 0 && !Engine.UTF8Enabled)
				command += "CHARSET " + charset + " ";

			command += "UID " + set + " " + expr + "\r\n";

			var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ());
			ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches);
			ic.UserData = new SearchResults ();

			Engine.QueueCommand (ic);
			Engine.Wait (ic);

			ProcessResponseCodes (ic, null);

			if (ic.Response != ImapCommandResponse.Ok)
				throw ImapCommandException.Create ("SEARCH", ic);

			return (SearchResults) ic.UserData;
		}
예제 #29
0
		/// <summary>
		/// Asynchronously search the subset of UIDs in the folder for messages matching the specified query.
		/// </summary>
		/// <remarks>
		/// The returned array of unique identifiers can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of matching UIDs in the specified sort order.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// One or more of the <paramref name="uids"/> is invalid.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// One or more search terms in the <paramref name="query"/> are not supported by the mail store.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public virtual Task<IList<UniqueId>> SearchAsync (IList<UniqueId> uids, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (uids == null)
				throw new ArgumentNullException ("uids");

			if (query == null)
				throw new ArgumentNullException ("query");

			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Search (uids, query, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
예제 #30
0
파일: ImapFolder.cs 프로젝트: dcga/MailKit
		/// <summary>
		/// Threads the messages in the folder that match the search query using the specified threading algorithm.
		/// </summary>
		/// <remarks>
		/// The <see cref="MessageThread.UniqueId"/> can be used with methods such as
		/// <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of message threads.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="algorithm">The threading algorithm to use.</param>
		/// <param name="query">The search query.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="algorithm"/> is not supported.
		/// </exception>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="uids"/> is empty.</para>
		/// <para>-or-</para>
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the IMAP server.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the THREAD extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="ImapClient"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="ImapClient"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="ImapClient"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The <see cref="ImapFolder"/> is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ImapProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="ImapCommandException">
		/// The server replied with a NO or BAD response.
		/// </exception>
		public override IList<MessageThread> Thread (IList<UniqueId> uids, ThreadingAlgorithm algorithm, SearchQuery query, CancellationToken cancellationToken = default (CancellationToken))
		{
			var method = algorithm.ToString ().ToUpperInvariant ();
			var set = ImapUtils.FormatUidSet (uids);
			var args = new List<string> ();
			string charset;

			if ((Engine.Capabilities & ImapCapabilities.Thread) == 0)
				throw new NotSupportedException ("The IMAP server does not support the THREAD extension.");

			if (!Engine.ThreadingAlgorithms.Contains (algorithm))
				throw new ArgumentOutOfRangeException ("algorithm", "The specified threading algorithm is not supported.");

			if (query == null)
				throw new ArgumentNullException ("query");

			CheckState (true, false);

			var optimized = query.Optimize (new ImapSearchQueryOptimizer ());
			var expr = BuildQueryExpression (optimized, args, out charset);
			var command = "UID THREAD " + method + " " + charset + " ";

			command += "UID " + set + " " + expr + "\r\n";

			var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ());
			ic.RegisterUntaggedHandler ("THREAD", ThreadMatches);

			Engine.QueueCommand (ic);
			Engine.Wait (ic);

			ProcessResponseCodes (ic, null);

			if (ic.Response != ImapCommandResponse.Ok)
				throw ImapCommandException.Create ("THREAD", ic);

			var threads = (IList<MessageThread>) ic.UserData;

			if (threads == null)
				return new MessageThread[0];

			return threads;
		}
예제 #31
0
		/// <summary>
		/// Search the subset of UIDs in the folder for messages matching the specified query,
		/// returning them in the preferred sort order.
		/// </summary>
		/// <remarks>
		/// The returned array of unique identifiers will be sorted in the preferred order and
		/// can be used with <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken,ITransferProgress)"/>.
		/// </remarks>
		/// <returns>An array of matching UIDs.</returns>
		/// <param name="uids">The subset of UIDs</param>
		/// <param name="query">The search query.</param>
		/// <param name="orderBy">The sort order.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="uids"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="query"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para>One or more of the <paramref name="uids"/> is invalid.</para>
		/// <para>-or-</para>
		/// <para><paramref name="orderBy"/> is empty.</para>
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <para>One or more search terms in the <paramref name="query"/> are not supported by the mail store.</para>
		/// <para>-or-</para>
		/// <para>The server does not support the SORT extension.</para>
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="IMailStore"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="IMailStore"/> is not connected.
		/// </exception>
		/// <exception cref="ServiceNotAuthenticatedException">
		/// The <see cref="IMailStore"/> is not authenticated.
		/// </exception>
		/// <exception cref="FolderNotOpenException">
		/// The folder is not currently open.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled via the cancellation token.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="ProtocolException">
		/// The server's response contained unexpected tokens.
		/// </exception>
		/// <exception cref="CommandException">
		/// The command failed.
		/// </exception>
		public abstract IList<UniqueId> Search (IList<UniqueId> uids, SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken));