/// <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> /// 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> /// 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; }
/// <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 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> /// 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> /// 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> /// Searches 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)"/>. /// </remarks> /// <returns>An array of matching UIDs in the specified sort order.</returns> /// <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="query"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="orderBy"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// <paramref name="orderBy"/> is empty. /// </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 override IList<UniqueId> Search(SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken)) { 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.Sort) == 0) throw new NotSupportedException ("The IMAP server does not support the SORT extension."); var optimized = query.Optimize (new ImapSearchQueryOptimizer ()); var expr = BuildQueryExpression (optimized, args, out charset); var order = BuildSortOrder (orderBy); var command = "UID SORT " + order + " "; if ((Engine.Capabilities & ImapCapabilities.ESort) != 0) command += "RETURN () "; command += charset + " "; command += expr + "\r\n"; var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ()); if ((Engine.Capabilities & ImapCapabilities.ESort) != 0) ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches); else ic.RegisterUntaggedHandler ("SORT", SearchMatches); Engine.QueueCommand (ic); Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Result != ImapCommandResult.Ok) throw ImapCommandException.Create ("SORT", ic); var results = (IList<UniqueId>) ic.UserData; if (results == null) return new UniqueId[0]; return results; }
/// <summary> /// Searches the folder for messages matching the specified query. /// </summary> /// <remarks> /// The returned array of unique identifiers can be used with <see cref="IMailFolder.GetMessage(UniqueId,CancellationToken)"/>. /// </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 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 override IList<UniqueId> Search(SearchQuery query, CancellationToken cancellationToken = default (CancellationToken)) { var args = new List<string> (); string charset; 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 SEARCH "; if ((Engine.Capabilities & ImapCapabilities.ESearch) != 0) command += "RETURN () "; if (args.Count > 0 && !Engine.UTF8Enabled) command += "CHARSET " + charset + " "; command += expr + "\r\n"; var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ()); if ((Engine.Capabilities & ImapCapabilities.ESearch) != 0) ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches); else ic.RegisterUntaggedHandler ("SEARCH", SearchMatches); Engine.QueueCommand (ic); Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Result != ImapCommandResult.Ok) throw ImapCommandException.Create ("SEARCH", ic); var results = (IList<UniqueId>) ic.UserData; if (results == null) return new UniqueId[0]; return results; }
/// <summary> /// 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="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="query"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="orderBy"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// <paramref name="orderBy"/> is empty. /// </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="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> Sort (SearchQuery query, IList<OrderBy> orderBy, CancellationToken cancellationToken = default (CancellationToken)) { var args = new List<string> (); string charset; 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)); CheckState (true, false); if ((Engine.Capabilities & ImapCapabilities.Sort) == 0) throw new NotSupportedException ("The IMAP server does not support the SORT 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."); } } var optimized = query.Optimize (new ImapSearchQueryOptimizer ()); var expr = BuildQueryExpression (optimized, args, out charset); var order = BuildSortOrder (orderBy); var command = "UID SORT "; if ((Engine.Capabilities & ImapCapabilities.ESort) != 0) command += "RETURN () "; command += order + " " + (charset ?? "US-ASCII") + " " + expr + "\r\n"; var ic = new ImapCommand (Engine, cancellationToken, this, command, args.ToArray ()); if ((Engine.Capabilities & ImapCapabilities.ESort) != 0) ic.RegisterUntaggedHandler ("ESEARCH", ESearchMatches); else ic.RegisterUntaggedHandler ("SORT", SearchMatches); 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).UniqueIds; }