ImapSearch Method (Boolean, String, String) |
Namespace: MailBee.ImapMail
public MessageIndexCollection Search( bool returnUids, string searchCondition, string charset )
Exception | Condition |
---|---|
MailBeeException | An error occurred and ThrowExceptions is true. |
The developer must type-cast returned value to UidCollection type (if returnUids was true) or to MessageNumberCollection (if returnUids was false).
If searchCondition is specified, it must strictly match search expression rules defined by the IMAP4 protocol (RFC3501). MailBee simply passes this value to the server without alteration.
When multiple keys are specified, the result is the intersection (AND function) of all the messages that match those keys. For example, the criteria DELETED FROM "SMITH" SINCE 1-Feb-1994 refers to all deleted messages from Smith that were placed in the folder since February 1, 1994. A search key can also be a parenthesized list of one or more search keys (e.g., for use with the OR and NOT keys).
AllOf(String) (AND), AnyOf(String) (OR), Not(String) (NOT) methods simplify building complex queries.
When passing strings to search query, you should use the syntax like "TEXT " + ImapUtils.ToQuotedString(textToSearch) to enclose the text string in quotes. Or, when searching for non-English text, set charset to "UTF-8" and instead of ToQuotedString(String) use ToUtf8QuotedString(String) (with Gmail, use ToLiteral(String)). This is true for all IMAP keys which search for text (such as BODY, CC, FROM, SUBJECT, TEXT, TO).
The entire list of the currently defined IMAP4 search keys:
Key | Meaning |
---|---|
<sequence set> | Messages with message sequence numbers corresponding to the specified message sequence number set. Examples: "1", "589, 1067", "1:*", "5,7,10:25,37:*", "3:4". Multiple values are delimited with commas (,). Colon (:) is used to specify a range. For instance, "1:10" designates message indices in the range from 1 to 10. "*" is a wildcard. When used in a range, sets higher boundary of the range to the index of the last message in the folder. |
ALL | All messages in the folder; the default initial key for ANDing. |
ANSWERED | Messages with the \Answered flag set. |
BCC <string> | Messages that contain the specified string in the envelope structure's BCC field. |
BEFORE <date> | Messages whose internal date (disregarding time and timezone) is earlier than the specified date. |
BODY <string> | Messages that contain the specified string in the body of the message. |
CC <string> | Messages that contain the specified string in the envelope structure's CC field. |
DELETED | Messages with the \Deleted flag set. |
DRAFT | Messages with the \Draft flag set. |
FLAGGED | Messages with the \Flagged flag set. |
FROM <string> | Messages that contain the specified string in the envelope structure's FROM field. |
HEADER <field-name> <string> | Messages that have a header with the specified field-name (as defined in [RFC-2822]) and that contains the specified string in the text of the header (what comes after the colon). If the string to search is zero-length, this matches all messages that have a header line with the specified field-name regardless of the contents. |
KEYWORD <flag> | Messages with the specified keyword flag set. |
LARGER <n> | Messages with an [RFC-2822] size larger than the specified number of octets. |
NEW | Messages that have the \Recent flag set but not the \Seen flag. This is functionally equivalent to "(RECENT UNSEEN)". |
NOT <search-key> | Messages that do not match the specified search key. |
OLD | Messages that do not have the \Recent flag set. This is functionally equivalent to "NOT RECENT" (as opposed to "NOT NEW"). |
ON <date> | Messages whose internal date (disregarding time and timezone) is within the specified date. |
OR <search-key1> <search-key2> | Messages that match either search key. |
RECENT | Messages that have the \Recent flag set. |
SEEN | Messages that have the \Seen flag set. |
SENTBEFORE <date> | Messages whose [RFC-2822] Date: header (disregarding time and timezone) is earlier than the specified date. |
SENTON <date> | Messages whose [RFC-2822] Date: header (disregarding time and timezone) is within the specified date. |
SENTSINCE <date> | Messages whose [RFC-2822] Date: header (disregarding time and timezone) is within or later than the specified date. |
SINCE <date> | Messages whose internal date (disregarding time and timezone) is within or later than the specified date. |
SMALLER <n> | Messages with an [RFC-2822] size smaller than the specified number of octets. |
SUBJECT <string> | Messages that contain the specified string in the envelope structure's SUBJECT field. |
TEXT <string> | Messages that contain the specified string in the header or body of the message. |
TO <string> | Messages that contain the specified string in the envelope structure's TO field. |
UID <sequence set> | Messages with unique identifiers corresponding to the specified unique identifier set. Sequence set ranges are permitted. |
UNANSWERED | Messages that do not have the \Answered flag set. |
UNDELETED | Messages that do not have the \Deleted flag set. |
UNDRAFT | Messages that do not have the \Draft flag set. |
UNFLAGGED | Messages that do not have the \Flagged flag set. |
UNKEYWORD <flag> | Messages that do not have the specified keyword flag set. |
UNSEEN | Messages that do not have the \Seen flag set. |
Dates must be written in IMAP4 format and enclosed with quotes. Example: "06-Apr-2006". See the sample code in BeginSearch(Boolean, String, String, AsyncCallback, Object) topic on how to perform search by date.
Angle brackets (i.e. <> in <string>) only indicate placeholder for actual value, they are not actually a part of the key. For instance, TO <string> means the actual key will look like TO "jdoe@domain.com".Note |
---|
Although searching is case-insensitive, some server implementations cannot perform search of strings containing international characters in case-insensitive manner even if the correct charset value is specified. Also, most IMAP server implementations cannot find searched string when it appears in the message in encoded form (such as Base64, quoted-printable, etc). Due to this, text search via IMAP4 is not as reliable as downloading entire messages and performing search over local copies. |
If you are using Gmail and perform search of international text in non-ASCII charset (e.g. UTF-8), use ToLiteral(String) method instead of ToQuotedString(String). Gmail does not support non-ASCII data in quoted strings. See Gmail IMAP and POP3 issues topic on how to build search queries with ToLiteral(String) method.
With Gmail, however, you have an option to use extended syntax of Gmail search. It supports non-ASCII as well. See GmailSearch(String) for details.
Also, you can search for Gmail labels assigned to messages using X-GM-LABELS verb. For instance: imap.Search(true, ImapUtils.AnyOf(@"X-GM-LABELS label1", @"X-GM-LABELS sent"), null) (in C# syntax). This returns UIDs of all e-mails which have "label1" or "sent" labels set.
Note |
---|
MS Exchange (including Office 365) can search ASCII only. You cannot search for international content there. You can switch to Exchange Web Services (Ews) when working with MS Exchange. |
using System; using MailBee; using MailBee.ImapMail; class Sample { static void Main(string[] args) { Imap imp = new Imap(); // In the log, you can find the actual search queries sent to the server. imp.Log.Filename = "C:\\Temp\\log.txt"; imp.Log.Enabled = true; imp.Log.Clear(); imp.Connect("imap.company.com"); imp.Login("jdoe@company.com", "secret"); // Select Inbox folder. imp.SelectFolder("INBOX"); UidCollection uids = null; MessageNumberCollection msgNums = null; string input = null; // Determine charset to use. This will let us perform search of // messages written in the charset of the current computer. string localComputerCharset = System.Text.Encoding.Default.WebName; // ----------------------------------------------------------------- // Section 1: Search in Subject field. // Demonstrates text search and usage of charsets (for international // applications) and quoted strings (for searching arbitrary text, // including spaces, quotes, and other special characters). // ----------------------------------------------------------------- Console.WriteLine("Input string to be searched in Subject field:"); input = Console.ReadLine(); // 1.1: US-ASCII search (case-insensitive). // 1.1.1: Search for UIDs. uids = (UidCollection)imp.Search(true, "SUBJECT " + ImapUtils.ToQuotedString(input), null); Console.WriteLine(); Console.WriteLine("UIDs of found messages (US-ASCII mode):"); Console.WriteLine(uids.ToString()); // 1.1.2: Search for ordinal message numbers. This demonstrates // how to get search results as message numbers rather UIDs. msgNums = (MessageNumberCollection)imp.Search(false, "SUBJECT " + ImapUtils.ToQuotedString(input), null); Console.WriteLine(); Console.WriteLine("Message numbers of found messages (US-ASCII mode):"); Console.WriteLine(msgNums.ToString()); // 1.2: Search with support of international characters of the current // computer's charset. US-ASCII characters will be searched in case-insensitive // manner but there is no such guarantee for non-US-ASCII characters. uids = (UidCollection)imp.Search(true, "SUBJECT " + ImapUtils.ToQuotedString(input), localComputerCharset); Console.WriteLine(); Console.WriteLine("UIDs of found messages (" + localComputerCharset + " mode):"); Console.WriteLine(uids.ToString()); // 1.3: Search with support of UTF-8. This will let us perform search of any text in any language. uids = (UidCollection)imp.Search(true, "SUBJECT " + ImapUtils.ToUtf8QuotedString(input), System.Text.Encoding.UTF8.WebName); Console.WriteLine(); Console.WriteLine("UIDs of found messages (UTF-8 mode):"); Console.WriteLine(uids.ToString()); // ----------------------------------------------------------------- // Section 2: Search of messages with specific flags set. // Also demonstrates how to specify OR and AND conditions. // ----------------------------------------------------------------- // 2.1: Search for messages having \Deleted flag set. uids = (UidCollection)imp.Search(true, "DELETED", null); Console.WriteLine(); Console.WriteLine(@"UIDs of \Deleted messages:"); Console.WriteLine(uids.ToString()); // 2.2: Search for messages having \Deleted or \Seen flags set. uids = (UidCollection)imp.Search(true, "OR DELETED SEEN", null); Console.WriteLine(); Console.WriteLine(@"UIDs of \Deleted or \Seen messages:"); Console.WriteLine(uids.ToString()); // 2.3: Search for messages having \Deleted or \Seen or \Answered flags set. uids = (UidCollection)imp.Search(true, "OR (OR DELETED SEEN) ANSWERED", null); Console.WriteLine(); Console.WriteLine(@"UIDs of \Deleted or \Seen or \Answered messages:"); Console.WriteLine(uids.ToString()); // 2.4: Search for messages having \Deleted or (\Seen and \Answered) flags set. uids = (UidCollection)imp.Search(true, "OR DELETED (SEEN ANSWERED)", null); Console.WriteLine(); Console.WriteLine(@"UIDs of \Deleted or (\Seen and \Answered) messages:"); Console.WriteLine(uids.ToString()); // ------------------------------------------------------------------ // Section 3: Search of messages meeting complex criteria. // The criteria set (in C# syntax): // (size > 10000 || Flagged || !Spam) && BodyContains(string). // I.e. the message is larger than 10000 bytes or flagged or not spam // (there is no standard \Spam attribute so custom $Spam attribute // is used) and, besides that, the message must contain the specified // string (taken from user input) in the body. // ------------------------------------------------------------------ uids = (UidCollection)imp.Search(true, "OR (OR LARGER 10000 FLAGGED) UNKEYWORD " + ImapUtils.ToQuotedString("$Spam") + " BODY " + ImapUtils.ToQuotedString(input), null); Console.WriteLine(); Console.WriteLine("UIDs of messages meeting complex criteria:"); Console.WriteLine(uids.ToString()); // Using helper methods to repeat the same search: // (size > 10000 || Flagged || !Spam) && BodyContains(string). uids = (UidCollection)imp.Search(true, ImapUtils.AllOf(ImapUtils.AnyOf( "LARGER 10000", "FLAGGED", "UNKEYWORD " + ImapUtils.ToQuotedString("$Spam")), "BODY " + ImapUtils.ToQuotedString(input)), null); Console.WriteLine(); Console.WriteLine("The same search repeated with helper methods:"); Console.WriteLine(uids.ToString()); // Disconnect from the server. imp.Disconnect(); } }