More .NET libraries
-
Rebex Mail Pack
IMAP, MS Graph, EWS, POP3, SMTP, MIME, S/MIME, MSG
-
Rebex Total Pack
All Rebex .NET libraries together
Back to feature list...
Message operations
On this page:
- Getting list of messages
- Sequence numbers and unique IDs
- Message fields
- Getting message info
- Working with multiple messages
- Downloading messages
- Downloading message headers
- Downloading message parts
- Uploading messages
- Uploading raw messages
- Copying messages
- Deleting and undeleting messages
- Message flags (seen/unseen, answered/unanswered and more)
- Message keywords
The sample code on this page assumes you have already connected and authenticated to an IMAP servers and selected a folder.
Getting list of messages
To get a list of messages, use GetMessageList
method.
By default, the Envelope
information is retrieved, which is sufficient to display basic info such as From
, To
, Date
and Subject
headers.
Tip: You can choose which fields to retrieve to improve the performance of your application.
// create IMAP client instance, connect, log in, select folder var imap = new Rebex.Net.Imap(); imap.Connect(hostname, SslMode.Implicit); imap.Login(username, password); imap.SelectFolder("Inbox"); // get list of all messages ImapMessageCollection list = imap.GetMessageList(); // print some info Console.WriteLine("Found {0} message(s).", list.Count); foreach (ImapMessageInfo info in list) { Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject); }
' create IMAP client instance, connect, log in, select folder Dim imap As New Rebex.Net.Imap() imap.Connect(hostname, SslMode.Implicit) imap.Login(username, password) imap.SelectFolder("Inbox") ' get list of all messages Dim list As ImapMessageCollection = imap.GetMessageList() ' print some info Console.WriteLine("Found {0} message(s).", list.Count) For Each info As ImapMessageInfo In list Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject) Next
Sequence numbers and unique IDs
IMAP servers identify a single mail message by sequence number or unique ID.
Sequence number identifies the current position of the message within its folder, and it changes if one (or more) of the messages with a lower sequence number is removed.
On the other hand, unique IDs are supposed to stay the same for a long time, possibly indefinitely, as long as the message stays within its original folder in its original form. Otherwise, they can only changed when the validity ID of their folder has been changed, which should only happen rarely.
The following code converts a unique ID to sequence number:
// create IMAP client instance, connect, log in, select folder // ... // get message info according to Unique ID ImapMessageInfo info = imap.GetMessageInfo(uniqueId, ImapListFields.SequenceNumber); // get the Sequence number from message info int sequenceNumber = info.SequenceNumber;
' create IMAP client instance, connect, log in, select folder ' ... ' get message info according to Unique ID Dim info As ImapMessageInfo = imap.GetMessageInfo(uniqueId, ImapListFields.SequenceNumber) ' get the Sequence number from message info Dim sequenceNumber As Integer = info.SequenceNumber
The following code converts a sequence number to unique ID:
// get message info according to Sequence number ImapMessageInfo info = imap.GetMessageInfo(sequenceNumber, ImapListFields.UniqueId); // get the Unique ID from message info string uniqueId = info.UniqueId;
' get message info according to Sequence number Dim info As ImapMessageInfo = imap.GetMessageInfo(sequenceNumber, ImapListFields.UniqueId) ' get the Unique ID from message info Dim uniqueId As String = info.UniqueId
Almost all Imap
methods have a unique ID overload and a sequence number overload.
Message fields
Some of Imap
methods make it possible to specify which information to retrieve about IMAP messages.
These methods include GetMessageInfo
,
GetMessageList
and Search
.
It's a good idea to only request the information you need - it can save lot of time, bandwidth and processing power.
Use the ImapListFields
argument to specify which information to retrieve:
Parameter value | Description |
---|---|
ImapListFields.SequenceNumber |
Message sequence number for current session. |
ImapListFields.UniqueID |
Message unique ID that is permanent and does not change between sessions. |
ImapListFields.Length |
Message data size in bytes. |
ImapListFields.Flags |
Message flags (see the ImapMessageFlags enum for the list of message flags). |
ImapListFields.ReceivedDate |
Date and time at which the message was received by the mail server. |
ImapListFields.Fast |
Combination of SequenceNumber , UniqueId , Length ,
Flags and ReceivedDate . |
ImapListFields.Envelope |
Same as Fast , but also downloads the message envelope info - a selection
of most important header fields of the message such as Date, From, To, Subject or Message ID fields.
This is the default for methods with optional fields argument. |
ImapListFields.FullHeaders |
Same as Fast , but also downloads complete message headers of each message.
This variant is the most verbose, but also the slowest, and in fact seldom needed,
because nearly all interesting information about the message is already returned
by ImapListFields.Envelope . See the next section for more
discussion about this. |
ImapListFields.Body |
Text and HTML bodies of the message. |
ImapListFields.MessageStructure |
Information about the message structure - list of message parts (bodies, resources and attachments)
with detailed info (file names, lengths, content types, content IDs).
To download a single message part, use GetMessagePart method.
|
Note: These fields are bit flags, which means that combinations such as
UniqueId|Flags
or
UniqueId|SequenceNumber|Length
are possible - use
bitwise OR
operator for this (|
in C#, Or
in VB.NET).
Getting message info
To get information about a message, use GetMessageInfo
method.
By default, the Envelope
information is retrieved, which is sufficient to display basic info such as From
, To
, Date
and Subject
headers.
Tip: You can choose which fields to retrieve to improve the performance of your application.
// create IMAP client instance, connect, log in, select folder // ... // get Envelope and Body parts of a message ImapMessageInfo info = imap.GetMessageInfo(uniqueId, ImapListFields.Envelope | ImapListFields.Body); // print info about the message Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject); if (info.HasBodyText) Console.WriteLine(info.BodyText);
' create IMAP client instance, connect, log in, select folder ' ... ' get Envelope and Body parts of a message Dim info As ImapMessageInfo = imap.GetMessageInfo(uniqueId, ImapListFields.Envelope Or ImapListFields.Body) ' print info about the message Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject) If info.HasBodyText Then Console.WriteLine(info.BodyText) End If
Working with multiple messages
Some methods of the Imap
object accept a message set as a parameter.
This makes it possible to process multiple messages at once, usually in a single round-trip to the server, which can be a benefit on slow connections.
All these methods accept a ImapMessageSet
argument, which is a set of either individual unique IDs or sequence numbers, or their ranges.
The methods that accept ImapMessageSet
argument are:
Search
GetMessageList
CopyMessage
SetMessageFlags
DeleteMessage
UndeleteMessage
Following code demonstrates paged message listing:
// create IMAP client instance, connect, log in, select folder // ... // page index and size int pageIndex = 0; int pageSize = 10; // create set to retrieve only specific page of message listing var set = new ImapMessageSet(); int from = (pageIndex * pageSize) + 1; int to = from + pageSize - 1; if (to > imap.CurrentFolder.TotalMessageCount) to = imap.CurrentFolder.TotalMessageCount; if (from <= imap.CurrentFolder.TotalMessageCount) set.AddRange(from, to); // get list of specified messages ImapMessageCollection list = imap.GetMessageList(set); // print some info Console.WriteLine("Found {0} message(s).", list.Count); foreach (ImapMessageInfo info in list) { Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject); }
' create IMAP client instance, connect, log in, select folder ' ... ' page index and size Dim pageIndex As Integer = 0 Dim pageSize As Integer = 10 ' create set to retrieve only specific page of message listing Dim [set] = New ImapMessageSet() Dim [from] As Integer = (pageIndex * pageSize) + 1 Dim [to] As Integer = [from] + pageSize - 1 If [to] > imap.CurrentFolder.TotalMessageCount Then [to] = imap.CurrentFolder.TotalMessageCount End If If [from] <= imap.CurrentFolder.TotalMessageCount Then [set].AddRange([from], [to]) End If ' get list of specified messages Dim list As ImapMessageCollection = imap.GetMessageList([set]) ' print some info Console.WriteLine("Found {0} message(s).", list.Count) For Each info As ImapMessageInfo In list Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject) Next
Downloading messages
To download and parse a whole mail message into memory, use the GetMailMessage
method:
// create IMAP client instance, connect, log in, select folder // ... // get mail message MailMessage mail = imap.GetMailMessage(uniqueId); // print some info Console.WriteLine("From: {0}", mail.From); Console.WriteLine("Subject: {0}", mail.Subject); if (mail.Attachments.Count > 0) Console.WriteLine("Attachments: {0}", mail.Attachments.Count); if (mail.HasBodyText) Console.WriteLine("Body: {0}", mail.BodyText);
' create IMAP client instance, connect, log in, select folder ' ... ' get mail message Dim mail As MailMessage = imap.GetMailMessage(uniqueId) ' print some info Console.WriteLine("From: {0}", mail.From) Console.WriteLine("Subject: {0}", mail.Subject) If mail.Attachments.Count > 0 Then Console.WriteLine("Attachments: {0}", mail.Attachments.Count) End If If mail.HasBodyText Then Console.WriteLine("Body: {0}", mail.BodyText) End If
This retrieves an instance of high-level MailMessage
object.
If you prefer the low-level API (MimeMessage
object),
call GetMimeMessage
method instead.
Alternatively, you can easily download a message into a file using GetMessage
method:
// save mail directly to disk imap.GetMessage(uniqueId, @"C:\MyData\mail.eml");
' save mail directly to disk imap.GetMessage(uniqueId, "C:\MyData\mail.eml")
To download the message to a Stream
instead, use another GetMessage
overload:
// prepare stream var ms = new MemoryStream(); // save mail directly to a stream imap.GetMessage(uniqueId, ms);
' prepare stream Dim ms = New MemoryStream() ' save mail directly to a stream imap.GetMessage(uniqueId, ms)
Downloading message headers
To retrieve message headers into an instance of ImapMessageInfo
,
use GetMessageInfo
method
with ImapListFields.FullHeaders
argument.
It's possible to retrieve headers for multiple messages as well using GetMessageList
method,
but it may take a long time.
Alternatively, to download the message headers into a file or a stream, use the GetMessageHeaders
method:
// create IMAP client instance, connect, log in, select folder // ... // prepare stream var ms = new MemoryStream(); // get message headers imap.GetMessageHeaders(uniqueId, ms);
' create IMAP client instance, connect, log in, select folder ' ... ' prepare stream Dim ms = New MemoryStream() ' get message headers imap.GetMessageHeaders(uniqueId, ms)
Downloading message parts
IMAP makes it possible to download separate message parts without having to download the whole message. For example, you can download the message envelope and bodies first, but only download individual attachments later when needed.
// create IMAP client instance, connect, log in, select folder // ... // get message structure info ImapMessageInfo info = imap.GetMessageInfo(uniqueId, ImapListFields.MessageStructure); // save all attachments foreach (ImapMessagePart part in info.GetParts()) { // process only attachments if (part.Kind != ImapMessagePartKind.Attachment) continue; // prepare file stream string target = Path.Combine(@"C:\MyData", part.FileName); using (FileStream stream = File.Create(target)) { // download the attachment imap.GetMessagePart(uniqueId, part.Id, stream); } }
' create IMAP client instance, connect, log in, select folder ' ... ' get message structure info Dim info As ImapMessageInfo = imap.GetMessageInfo(uniqueId, ImapListFields.MessageStructure) ' save all attachments For Each part As ImapMessagePart In info.GetParts() ' process only attachments If part.Kind <> ImapMessagePartKind.Attachment Then Continue For End If ' prepare file stream Dim target As String = Path.Combine("C:\MyData", part.FileName) Using stream As FileStream = File.Create(target) ' download the attachment imap.GetMessagePart(uniqueId, part.Id, stream) End Using Next
GetMessagePart
method makes it possible to retrieve the text of the message as well.
However, it usually easier to use GetMessageInfo(ImapListFields.Body)
method
and access the bodies through ImapMessageInfo.BodyText
and ImapMessageInfo.BodyHtml
properties.
Uploading messages
You can even upload a message to a folder in an IMAP mailbox.
The Upload
method accepts a local file, stream, MailMessage
or MimeMessage
objects.
You can set flags and/or keywords for the message as well.
// create IMAP client instance, connect, log in // ... // create new mail message var mail = new Rebex.Mail.MailMessage(); mail.From = "joe@example.org"; mail.To = "john@example.org"; mail.Subject = "Test"; mail.BodyText = "Hello World!"; mail.BodyHtml = "<strong>Hello World!</strong>"; // upload the message to the "Inbox" folder on the IMAP server imap.StoreMessage("Inbox", mail);
' create IMAP client instance, connect, log in ' ... ' create new mail message Dim mail = New Rebex.Mail.MailMessage() mail.From = "joe@example.org" mail.To = "john@example.org" mail.Subject = "Test" mail.BodyText = "Hello World!" mail.BodyHtml = "<strong>Hello World!</strong>" ' upload the message to the "Inbox" folder on the IMAP server imap.StoreMessage("Inbox", mail)
If the IMAP server supports UIDPLUS
extension,
StoreMessage
method returns the unique ID assigned to the newly uploaded message.
Uploading raw messages
The Upload
method parses the supplied message to ensure the IMAP server gets a message in a format
it supports (MIME). When uploading lot of large messages, this can negatively affect the performance.
If you are sure your messages are valid and would like to to skip this step, use the StoreRawMessage
method instead:
// create IMAP client instance, connect, log in // ... // upload a mail directly to "Inbox" without parsing its content using (FileStream input = File.OpenRead(@"C:\MyData\mail.eml")) { imap.StoreRawMessage("Inbox", input, ImapMessageFlags.None, new MailDateTime(DateTime.Now)); }
' create IMAP client instance, connect, log in ' ... ' upload a mail directly to "Inbox" without parsing its content Using input As FileStream = File.OpenRead("C:\MyData\mail.eml") imap.StoreRawMessage("Inbox", input, ImapMessageFlags.None, New MailDateTime(DateTime.Now)) End Using
If the IMAP server supports UIDPLUS
extension,
StoreMessageRaw
method returns the unique ID assigned to the newly uploaded message.
Copying messages
To copy a message from current folder to another one, use the CopyMessage
:
// create IMAP client instance, connect, log in // ... // select "Inbox" imap.SelectFolder("Inbox"); // copy a message from "Inbox" to "My mails" imap.CopyMessage(uniqueId, "My mails");
' create IMAP client instance, connect, log in ' ... ' select "Inbox" imap.SelectFolder("Inbox") ' copy a message from "Inbox" to "My mails" imap.CopyMessage(uniqueId, "My mails")
If the IMAP server supports UIDPLUS
extension,
CopyMessage
method returns an instance of ImapCopyResult
that contains the unique IDs of the original and target messages.
Deleting and undeleting messages
To delete a mail message, use DeleteMessage
method.
Please note that this only sets the Deleted
message flag.
To permanently remove messages marked for deletion, use the Purge
method.
// create IMAP client instance, connect, log in, select folder // ... // delete a message imap.DeleteMessage(uniqueId); // permanently remove messages marked as deleted imap.Purge();
' create IMAP client instance, connect, log in, select folder ' ... ' delete a message imap.DeleteMessage(uniqueId) ' permanently remove messages marked as deleted imap.Purge()
To undelete a message (remove the Deleted
flag), use the UndeleteMessage
method:
// undelete message, which was previously marked as deleted imap.UndeleteMessage(uniqueId);
' undelete message, which was previously marked as deleted imap.UndeleteMessage(uniqueId)
Message flags (seen/unseen, answered/unanswered and more)
IMAP protocol defines several flags, some of which can be added to or removed from messages by clients.
Flags can be retrieved by specifying a ImapListFields.Flags
field in GetMessageInfo
or GetMessageList
calls,
and they can be set and removed using SetMessageFlags
method.
The following flags are supported and represented by ImapMessageFlags
enum:
- Seen
- Recent
- Answered
- Deleted
- Flagged
- Keywords
- Draft
The following code shows how to search for messages with specific flags by the Search
method.
It finds all messages that have not been seen yet (not flagged as Seen
):
// create IMAP client instance, connect, log in, select folder // ... // get list of all 'not-Seen' messages ImapMessageCollection list = imap.Search(ImapSearchParameter.HasFlagsNoneOf(ImapMessageFlags.Seen)); // print some info Console.WriteLine("Not-seen messages: {0}", list.Count); foreach (ImapMessageInfo info in list) { Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject); }
' create IMAP client instance, connect, log in, select folder ' ... ' get list of all 'not-Seen' messages Dim list As ImapMessageCollection = imap.Search(ImapSearchParameter.HasFlagsNoneOf(ImapMessageFlags.Seen)) ' print some info Console.WriteLine("Not-seen messages: {0}", list.Count) For Each info As ImapMessageInfo In list Console.WriteLine("[{0}] {1}: {2}", info.ReceivedDate, info.From, info.Subject) Next
The following code shows how to mark a message as Answered
once a reply has been sent:
// create IMAP client instance, connect, log in, select folder // ... // get the message MailMessage mail = imap.GetMailMessage(uniqueId); // create reply message MailMessage reply = mail.CreateReply(sender, ReplyBodyTransformation.None); reply.BodyText = "I am on holidays till 1st November.\n" + "John\n" + "\n" + "Original message:\n" + mail.BodyText; // send the reply Smtp.Send(reply, smtpHostName); // mark the message as answered imap.SetMessageFlags(uniqueId, ImapFlagAction.Add, ImapMessageFlags.Answered);
' create IMAP client instance, connect, log in, select folder ' ... ' get the message Dim mail As MailMessage = imap.GetMailMessage(uniqueId) ' create reply message Dim reply As MailMessage = mail.CreateReply(sender, ReplyBodyTransformation.None) reply.BodyText = "I am on holidays till 1st November." & vbLf & "John" & vbLf & vbLf & "Original message:" & vbLf & Convert.ToString(mail.BodyText) ' send the reply Smtp.Send(reply, smtpHostName) ' mark the message as answered imap.SetMessageFlags(uniqueId, ImapFlagAction.Add, ImapMessageFlags.Answered)
Finally, the following code shows how to retrieve flags, and how to remove the Seen
flag
(added by the server automatically) once the message has been downloaded:
// create IMAP client instance, connect, log in, select folder // ... // get message flags ImapMessageInfo info = imap.GetMessageInfo(uniqueId, ImapListFields.Flags); // download the message // this should set the SEEN flag automatically by the IMAP server imap.GetMessage(uniqueId, @"C:\MyData\file.txt"); // mark the message as not-Seen if not seen before downloading // it means Seen flag has to be removed from the message if ((info.Flags & ImapMessageFlags.Seen) == 0) imap.SetMessageFlags(uniqueId, ImapFlagAction.Remove, ImapMessageFlags.Seen);
' create IMAP client instance, connect, log in, select folder ' ... ' get message flags Dim info As ImapMessageInfo = imap.GetMessageInfo(uniqueId, ImapListFields.Flags) ' download the message ' this should set the Seen flag automatically by the IMAP server imap.GetMessage(uniqueId, "C:\MyData\file.txt") ' mark the message as not-Seen if not seen before downloading ' it means that Seen flag has to be removed from the message If (info.Flags And ImapMessageFlags.Seen) = 0 Then imap.SetMessageFlags(uniqueId, ImapFlagAction.Remove, ImapMessageFlags.Seen) End If
Message keywords
Many IMAP servers (such as Gmail) support custom keywords. These are similar to flags, but are user-defined.
The following code demonstrates how to set message keywords and how to use them when searching for messages later:
// create IMAP client instance, connect, log in, select folder // ... // add some keywords to some messages imap.SetMessageFlags(1, ImapFlagAction.Add, ImapMessageFlags.Keywords, "A"); imap.SetMessageFlags(2, ImapFlagAction.Add, ImapMessageFlags.Keywords, "B"); imap.SetMessageFlags(3, ImapFlagAction.Add, ImapMessageFlags.Keywords, "A", "B"); // finds message 1 and 3 ImapMessageCollection listA = imap.Search(ImapSearchParameter.Keyword("A")); // finds message 2 and 3 ImapMessageCollection listB = imap.Search(ImapSearchParameter.Keyword("B")); // finds message 3 ImapMessageCollection listAandB = imap.Search( ImapSearchParameter.Keyword("A"), ImapSearchParameter.Keyword("B")); // finds message 1,2,3 ImapMessageCollection listAorB = imap.Search( ImapSearchParameter.Or( ImapSearchParameter.Keyword("A"), ImapSearchParameter.Keyword("B")));
' create IMAP client instance, connect, log in, select folder ' ... ' add some keywords to some messages imap.SetMessageFlags(1, ImapFlagAction.Add, ImapMessageFlags.Keywords, "A") imap.SetMessageFlags(2, ImapFlagAction.Add, ImapMessageFlags.Keywords, "B") imap.SetMessageFlags(3, ImapFlagAction.Add, ImapMessageFlags.Keywords, "A", "B") ' finds message 1 and 3 Dim listA As ImapMessageCollection = imap.Search(ImapSearchParameter.Keyword("A")) ' finds message 2 and 3 Dim listB As ImapMessageCollection = imap.Search(ImapSearchParameter.Keyword("B")) ' finds message 3 Dim listAandB As ImapMessageCollection = imap.Search( ImapSearchParameter.Keyword("A"), ImapSearchParameter.Keyword("B")) ' finds message 1,2,3 Dim listAorB As ImapMessageCollection = imap.Search( ImapSearchParameter.Or( ImapSearchParameter.Keyword("A"), ImapSearchParameter.Keyword("B")))
Back to feature list...