Back to feature list...
Message operations
On this page:
The sample code on this page assumes you have already connected and authenticated to Microsoft 365 (Exchange Online) server.
Getting list of messages
To get a list of messages, use
GetMessageList() method.
The following code shows how to get the top page of messages in the Inbox folder.
// create Graph client instance, connect, log in
// ...
// get top page of messages from 'Inbox'
GraphMessageCollection messages = client.GetMessageList(GraphFolderId.Inbox);
// show info about them
foreach (GraphMessageInfo info in messages)
{
Console.WriteLine("From: {0}", info.From);
Console.WriteLine("To: {0}", info.To);
Console.WriteLine("Subject: {0}", info.Subject);
}
Getting list of messages with paging
A folder can contain thousands of items. Retrieving all of them might consume a lot of bandwidth and take a very long time. Additionally, it's usually not even possible because Exchange server limits the maximum number of items it can return in response to a single API call.
For many applications, working with several hundreds of latest items is entirely sufficient.
When it isn't, use
GraphPageView.
The following code shows how to retrieve a list of all messages in the 'Inbox' folder by calling
GetMessageList() multiple times using the paging functionality:
// create Graph client instance, connect, log in
// ...
// list all messages in 'Inbox' using paging functionality
int offset = 0;
int pageSize = 1000;
while (true)
{
// get next page
GraphMessageCollection messages = client.GetMessageList(
GraphFolderId.Inbox,
new GraphPageView(offset, pageSize));
// show info about messages
foreach (GraphMessageInfo m in messages)
{
Console.WriteLine("[{0}] ({1}) {2}", m.ReceivedDate, m.From, m.Subject);
}
// break if there are no more messages
if (messages.Count == 0)
break;
// set next offset
offset += messages.Count;
}
// final offset corresponds to total number of messages listed
Console.WriteLine("Total messages: {0}", offset);
Getting message info
To get information about a message, use
GetMessageInfo() method.
By default, information specified by
GraphMessageFields.Default is retrieved,
which includes the default set of properties as returned by Microsoft 365 (Exchange Online) server.
// create Graph client instance, connect, log in
// ...
// construct message ID
GraphMessageId id = new GraphMessageId(messageIdString);
// retrieve envelope of the message
GraphMessageInfo message = client.GetMessageInfo(id, GraphMessageFields.Envelope);
// show some info about the message
Console.WriteLine("Subject: {0}", message.Subject);
Console.WriteLine("From: {0}", message.From);
Console.WriteLine("To: {0}", message.To);
Tip: Limiting the fields to those you need to retrieve might improve the performance of your application.
Downloading messages
To download and parse a whole mail message into a
MailMessage object, use
GetMailMessage() method:
// create Graph client instance, connect, log in
// ...
// get a message
MailMessage message = client.GetMailMessage(messageId);
// show some info about the message
Console.WriteLine("Subject: {0}", message.Subject);
Console.WriteLine("From: {0}", message.From);
Console.WriteLine("To: {0}", message.To);
foreach (Attachment item in message.Attachments)
{
Console.WriteLine(" * {0} <{1}>", item.DisplayName, item.ContentType);
}
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 download a message into a file using
GetMessage() method:
// create Graph client instance, connect, log in // ... // download a message to a file in MIME format client.GetMessage(messageId, @"C:\data\message.eml");
To download a message into a Stream, use another
GetMessage()
overload:
// create Graph client instance, connect, log in
// ...
using (Stream writer = File.Create(@"C:\data\message.eml"))
{
// download a message to a stream in MIME format
client.GetMessage(messageId, writer);
}
Tip: When downloaded, messages are marked as Read by default.
To keep messages unread, set
client.Settings.MarkDownloadedMessageAsRead
to false.
Uploading messages
You can also upload messages to a folder at the server without sending them. The
StoreMessage()
method accepts
MailMessage or
MimeMessage object.
To upload a mail message from a file or stream, load it to
MailMessage or
MimeMessage object first:
// create Graph client instance, connect, log in // ... // load a mail message MailMessage mail = new MailMessage(); mail.Load(@"C:\data\message.eml"); // upload the mail to 'Drafts' folder GraphMessageInfo message = client.StoreMessage(GraphFolderId.Drafts, mail); // keep its ID for later use if needed var messageId = message.Id;
Updating messages
The UpdateMessage() method
can update a message on the server without downloading and re-uploading it.
Intended changes are specified using an instance of the
GraphMessageData class
and then applied to a message on the server.
// create Graph client instance, connect, log in
// ...
// prepare updates of a message
var updateSet = new GraphMessageData();
updateSet.Flag = GraphFlag.CreateFlagged(
startDateTime: DateTime.Today,
dueDateTime: DateTime.Today.AddDays(1));
updateSet.Categories = new GraphCategoryCollection("Project A", "Project B");
updateSet.Subject = "Updated subject";
updateSet.SetBodyHtml("Updated <b>body</b>.");
updateSet.Importance = GraphImportance.High;
updateSet.IsRead = false;
// apply updates
client.UpdateMessage(messageId, updateSet);
Moving messages
To move a message to another folder, use
MoveMessage() method.
// create Graph client instance, connect, log in
// ...
DateTime yesterday = DateTime.Today.AddDays(-1);
// find top page of messages that arrived to 'Inbox' yesterday
var items = client.Search(GraphFolderId.Inbox,
GraphMessageSearchParameter.Arrived(yesterday));
// move all of them to 'Archive' folder
foreach (GraphMessageInfo item in items)
{
client.MoveMessage(item.Id, GraphFolderId.Archive);
}
Tip: The MoveMessage()
method returns info about the new item, including its new ID.
Deleting messages
To delete a message, use DeleteMessage() method.
By default, messages are soft-deleted, which means they are moved to the Deletions subfolder of Recoverable Items folder.
They can still be accessed using GraphFolderId.Deletions for a while.
To enforce hard-delete, set the permanent argument of the
DeleteMessage()
method to true.
// create Graph client instance, connect, log in // ... // hard-delete desired message (do not move it to 'Deletions' folder) client.DeleteMessage(messageId, permanent: true);
Searching for messages
Use Search() method to search for messages matching the specified criteria.
Check out Searching section for more information.
Working with attachments
Rebex Graph makes it possible to list, add and download attachments of existing messages.
To add an attachment to a message, use AddAttachment() method:
// create Graph client instance, connect, log in
// ...
// prepare attachment metadata
var meta = new GraphAddAttachmentOptions()
{
Name = "image.jpg",
ContentType = MediaTypeNames.Image.Jpeg
};
// add an attachment to the existing message
var attInfo = client.AddAttachment(messageId, @"C:\data\image.jpg", meta);
// show some info about the attachment
Console.WriteLine("Added attachment {0} ({1}B).", attInfo.Name, attInfo.Size);
To list attachments of a message, use GetMessageInfo() method
and specify GraphMessageFields.AttachmentInfo.
To download an attachment, use GetAttachment() method:
// get info about message attachments
var info = client.GetMessageInfo(messageId, GraphMessageFields.AttachmentInfo);
// iterate through all message attachments
foreach (var att in info.Attachments)
{
// filter image attachments
if (att.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
{
// download it
var attachment = client.GetAttachment(att.Id);
// save it
attachment.Save(@"C:\data\images\" + attachment.FileName);
}
}
Graph IDs and MIME IDs
Graph API provides various types of objects IDs. In Rebex Graph, these are represented by different classes:
- Folder:
GraphFolderId- represents mailbox folders and subfolders (such as 'Inbox', 'Sent Items' or 'Drafts'). - Message:
GraphMessageId- represents e-mail messages. - Attachment:
GraphAttachmentId- represents attachments of e-mail messages.
These IDs are available as Id property of
GraphFolderInfo,
GraphMessageInfo and
GraphAttachmentInfo classes.
There are also several pre-defined folder IDs
that can be used to access well-known folders.
Note: GraphMessageInfo and
MailMessage classes also feature the
MessageId property.
This represents the Message-ID MIME header that is not related to Graph IDs.
To convert a Graph message ID to a MIME Message-ID, retrieve the message envelope info:
// get Envelope info of a message with desired Exchange ID (graphMessageId) var message = client.GetMessageInfo(graphMessageId, GraphMessageFields.Envelope); // read Message-ID (MIME header) from the message info var mimeMessageId = message.MessageId;
To convert a MIME Message-ID to a Graph message ID, use the
Search() method:
// search for messages with desired Message-ID MIME header
// the header is represented by 'internetMessageId' in Microsoft Graph API
// specify null folder to search anywhere in the mailbox
var messages = client.Search(folderId: null, new GraphMessageSearchQuery()
{
Fields = GraphMessageFields.Id,
RawFilter = $"internetMessageId eq '{mimeMessageId}'"
});
Console.WriteLine("Messages with Message-ID '{0}':", mimeMessageId);
foreach (GraphMessageInfo info in messages)
{
Console.WriteLine(info.Id);
}
Note: Graph API IDs are case-sensitive strings, which makes them unsuitable to be used as a file name on case-insensitive file systems.
Message body type
A body of a mail message can use HTML, plain text, or both.
The GraphMessageInfo class
has properties for both formats:
BodyText
and BodyHtml.
However, due to a limitation of Graph API (which only exposes a single body object with one
content type), only one of these properties is set at any given time.
Additionally, a BodyPreview property is available,
which contains the beginning of the message body (at most 255 characters) and is always in plain text (no HTML tags).
To specify which type of message body to retrieve from the server into
GraphMessageInfo, set the
PreferredBodyType option:
// create Graph client instance, connect, log in
// ...
// prepare options
GraphMessageInfoOptions options = new GraphMessageInfoOptions
{
// request basic info and body
Fields = GraphMessageFields.Envelope | GraphMessageFields.Body,
// request HTML body
PreferredBodyType = GraphBodyContentType.Html
};
// get the message info from the server
GraphMessageInfo messageInfo = client.GetMessageInfo(messageId, options);
// show preview of the message body (it has a value regardless PreferredBodyType)
Console.WriteLine("Body preview: {0}", messageInfo.BodyPreview);
// you can rely on BodyHtml having a value
Console.WriteLine("HTML body: {0}", messageInfo.BodyHtml);
// BodyText will be null in this case
//Console.WriteLine("Text body: {0}", messageInfo.BodyText);
Tip: Retrieving both HTML and plain text message bodies requires two separate API calls. Alternatively, download the whole mail message instead of getting message info.
If the message stored on the server does not include the specified body format (HTML or plain text), the server generates it by converting the available body content to the requested format.
If PreferredBodyType
is set to Default,
the server returns the message body in its preferred format
(BodyHtml).
Note: Microsoft Graph generates the plain text body from the HTML body, even when the message contains a separate plain text body. To retrieve the original plain text body of the message, download the whole MIME message.
Message fields
Many GraphClient methods make it possible to specify which message information to retrieve.
These methods include
GetMessageInfo(),
GetMessageList(),
Search().
It's recommended to only request the information you need - this can save a lot of time, bandwidth and processing power.
Use the GraphMessageFields
argument to specify which information to retrieve:
| Parameter value | Description |
|---|---|
GraphMessageFields.Default |
Default set of fields defined by Exchange Online (Microsoft 365) server.
This is the default for methods with optional fields argument.
|
GraphMessageFields.Id |
Only retrieves the Exchange message ID. |
GraphMessageFields.Subject |
Retrieves message subject. |
GraphMessageFields.Body |
Retrieves message body (HTML if available, plain text otherwise). |
GraphMessageFields.AttachmentInfo |
Retrieves information about attachments. |
GraphMessageFields.Envelope |
Retrieves message ID and envelope info. This includes the most important fields such as Date, From, To, Subject, and Message-ID. |
GraphMessageFields.Info |
Retrieves message ID, envelope info, attachment info and additional fields such as Importance, Flag, Categories, IsRead, and LastModifiedDate. |
Note: These fields are bit flags, which means that combinations such as
Envelope | Body are possible - use
bitwise OR operator (| in C#, Or in VB.NET).
The following code shows how to combine multiple
GraphMessageFields to get desired results:
// create Graph client instance, connect, log in
// ...
// get message envelope and attachment info
GraphMessageInfo message = client.GetMessageInfo(messageId,
GraphMessageFields.Envelope | GraphMessageFields.AttachmentInfo);
// show some info about the message
Console.WriteLine("Subject: {0}", message.Subject);
Console.WriteLine("From: {0}", message.From);
Console.WriteLine("To: {0}", message.To);
if (message.HasAttachments)
{
Console.WriteLine("Message has attachment(s).");
}
Back to feature list...