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...