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; }
/// <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); }
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; }
/// <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); }
/// <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));
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); }
/// <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));
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); }
/// <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); }
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 (); } }
/// <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));
/// <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; }
/// <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; }
/// <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; }
/// <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); }
/// <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); }
/// <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); }
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; }
/// <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); }
/// <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; }
/// <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); }
/// <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; }
string BuildQueryExpression(SearchQuery query, List<string> args) { var builder = new StringBuilder (); BuildQuery (builder, query, args, false); return builder.ToString (); }
/// <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); }
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 (); }
/// <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));
/// <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; }
/// <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); }
/// <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; }
/// <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));