Overview
The Messages API provides operations to manage email messages in user mailboxes. Access through graphClient.Users[userId].Messages or graphClient.Me.Messages.
Request Builders
// For current user
public MessagesRequestBuilder Messages { get ; }
// Access: graphClient.Me.Messages
// For specific user
public MessagesRequestBuilder Messages { get ; }
// Access: graphClient.Users["user-id"].Messages
// For mail folder
public MessagesRequestBuilder Messages { get ; }
// Access: graphClient.Me.MailFolders["folder-id"].Messages
Operations
List Messages
Retrieve messages from a mailbox or folder.
public async Task < MessageCollectionResponse > GetAsync (
Action < RequestConfiguration < MessagesRequestBuilderGetQueryParameters >> requestConfiguration = default ,
CancellationToken cancellationToken = default
)
Query Parameters:
Properties to return (e.g., ["subject", "from", "receivedDateTime"])
Filter expression (e.g., "isRead eq false", "from/emailAddress/address eq '[email protected] '")
Sort order (e.g., ["receivedDateTime desc"])
Number of messages to return
Number of messages to skip
Search query (e.g., "subject:meeting")
Expand related entities (e.g., ["attachments"])
Response:
URL for next page of results
Example:
// Get messages for current user
var messages = await graphClient . Me . Messages . GetAsync ();
foreach ( var message in messages . Value )
{
Console . WriteLine ( $" { message . Subject } - { message . ReceivedDateTime } " );
}
// Get unread messages
var unreadMessages = await graphClient . Me . Messages . GetAsync ( config =>
{
config . QueryParameters . Filter = "isRead eq false" ;
config . QueryParameters . Orderby = new [] { "receivedDateTime desc" };
config . QueryParameters . Top = 50 ;
});
// Search messages
var searchResults = await graphClient . Me . Messages . GetAsync ( config =>
{
config . QueryParameters . Search = " \" subject:project update \" " ;
});
// Get messages with attachments
var messagesWithAttachments = await graphClient . Me . Messages . GetAsync ( config =>
{
config . QueryParameters . Filter = "hasAttachments eq true" ;
config . QueryParameters . Expand = new [] { "attachments" };
});
Create Message (Draft)
Create a new draft message.
public async Task < Message > PostAsync (
Message body ,
Action < RequestConfiguration < DefaultQueryParameters >> requestConfiguration = default ,
CancellationToken cancellationToken = default
)
Example:
var newMessage = new Message
{
Subject = "Project Update" ,
Body = new ItemBody
{
ContentType = BodyType . Html ,
Content = "<h1>Project Status</h1><p>Here's the latest update...</p>"
},
ToRecipients = new List < Recipient >
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "[email protected] " ,
Name = "John Doe"
}
}
},
CcRecipients = new List < Recipient >
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "[email protected] "
}
}
},
Importance = Importance . High ,
IsDeliveryReceiptRequested = true
};
var draft = await graphClient . Me . Messages . PostAsync ( newMessage );
Console . WriteLine ( $"Draft created with ID: { draft . Id } " );
Get Message by ID
Retrieve a specific message.
var message = await graphClient . Me . Messages [ "message-id" ]. GetAsync ();
// Select specific properties
var message = await graphClient . Me . Messages [ "message-id" ]. GetAsync ( config =>
{
config . QueryParameters . Select = new [] { "subject" , "from" , "receivedDateTime" , "body" };
});
// Include attachments
var message = await graphClient . Me . Messages [ "message-id" ]. GetAsync ( config =>
{
config . QueryParameters . Expand = new [] { "attachments" };
});
Update Message
Update message properties.
// Mark as read
var updateMessage = new Message
{
IsRead = true
};
await graphClient . Me . Messages [ "message-id" ]. PatchAsync ( updateMessage );
// Move to folder
var moveMessage = new Message
{
// Update other properties
};
await graphClient . Me . Messages [ "message-id" ]. PatchAsync ( moveMessage );
// Categorize
var categorizeMessage = new Message
{
Categories = new [] { "Important" , "Follow up" }
};
await graphClient . Me . Messages [ "message-id" ]. PatchAsync ( categorizeMessage );
Delete Message
Delete a message (moves to Deleted Items).
await graphClient . Me . Messages [ "message-id" ]. DeleteAsync ();
Message Actions
Send Message
Send an existing draft message.
await graphClient . Me . Messages [ "message-id" ]. Send . PostAsync ();
Send Mail (Create and Send)
Create and send a message in one operation.
var message = new Message
{
Subject = "Quick Update" ,
Body = new ItemBody
{
ContentType = BodyType . Text ,
Content = "Just a quick update on the project."
},
ToRecipients = new List < Recipient >
{
new Recipient
{
EmailAddress = new EmailAddress { Address = "[email protected] " }
}
}
};
var sendMailBody = new SendMailPostRequestBody
{
Message = message ,
SaveToSentItems = true
};
await graphClient . Me . SendMail . PostAsync ( sendMailBody );
Reply to Message
// Reply
var replyBody = new ReplyPostRequestBody
{
Comment = "Thanks for the update!" ,
Message = new Message
{
ToRecipients = new List < Recipient >
{
new Recipient { EmailAddress = new EmailAddress { Address = "[email protected] " } }
}
}
};
await graphClient . Me . Messages [ "message-id" ]. Reply . PostAsync ( replyBody );
// Reply All
var replyAllBody = new ReplyAllPostRequestBody
{
Comment = "Thanks everyone!"
};
await graphClient . Me . Messages [ "message-id" ]. ReplyAll . PostAsync ( replyAllBody );
Forward Message
var forwardBody = new ForwardPostRequestBody
{
Comment = "FYI" ,
ToRecipients = new List < Recipient >
{
new Recipient
{
EmailAddress = new EmailAddress { Address = "[email protected] " }
}
}
};
await graphClient . Me . Messages [ "message-id" ]. Forward . PostAsync ( forwardBody );
Copy/Move Message
// Copy to folder
var copyBody = new CopyPostRequestBody
{
DestinationId = "destination-folder-id"
};
var copiedMessage = await graphClient . Me . Messages [ "message-id" ]. Copy . PostAsync ( copyBody );
// Move to folder
var moveBody = new MovePostRequestBody
{
DestinationId = "destination-folder-id"
};
var movedMessage = await graphClient . Me . Messages [ "message-id" ]. Move . PostAsync ( moveBody );
Attachment Operations
List Attachments
var attachments = await graphClient . Me . Messages [ "message-id" ]. Attachments . GetAsync ();
foreach ( var attachment in attachments . Value )
{
if ( attachment is FileAttachment fileAttachment )
{
Console . WriteLine ( $"File: { fileAttachment . Name } ( { fileAttachment . Size } bytes)" );
}
else if ( attachment is ItemAttachment itemAttachment )
{
Console . WriteLine ( $"Item: { itemAttachment . Name } " );
}
}
Add File Attachment
// Small file (< 3MB)
var fileBytes = File . ReadAllBytes ( "document.pdf" );
var attachment = new FileAttachment
{
Name = "document.pdf" ,
ContentType = "application/pdf" ,
ContentBytes = fileBytes
};
await graphClient . Me . Messages [ "message-id" ]. Attachments . PostAsync ( attachment );
// Large file (using upload session)
using var fileStream = File . OpenRead ( "large-file.zip" );
var uploadSession = await graphClient . Me . Messages [ "message-id" ]
. Attachments
. CreateUploadSession
. PostAsync ( new CreateUploadSessionPostRequestBody
{
AttachmentItem = new AttachmentItem
{
AttachmentType = AttachmentType . File ,
Name = "large-file.zip" ,
Size = fileStream . Length
}
});
// Upload in chunks
var maxChunkSize = 320 * 1024 ; // 320 KB
var largeFileUploadTask = new LargeFileUploadTask < FileAttachment >(
uploadSession , fileStream , maxChunkSize );
await largeFileUploadTask . UploadAsync ();
Remove Attachment
await graphClient . Me . Messages [ "message-id" ]. Attachments [ "attachment-id" ]. DeleteAsync ();
Common Filtering Examples
// Unread messages from specific sender
config . QueryParameters . Filter = "isRead eq false and from/emailAddress/address eq '[email protected] '" ;
// Messages received in date range
config . QueryParameters . Filter = "receivedDateTime ge 2024-01-01T00:00:00Z and receivedDateTime le 2024-01-31T23:59:59Z" ;
// High importance messages
config . QueryParameters . Filter = "importance eq 'high'" ;
// Messages with attachments from domain
config . QueryParameters . Filter = "hasAttachments eq true and from/emailAddress/address endsWith '@contoso.com'" ;
// Flagged messages
config . QueryParameters . Filter = "flag/flagStatus eq 'flagged'" ;
Search Examples
// Search in subject
config . QueryParameters . Search = " \" subject:quarterly report \" " ;
// Search in from field
config . QueryParameters . Search = " \" from:[email protected] \" " ;
// Search message body
config . QueryParameters . Search = " \" body:project timeline \" " ;
// Search with multiple terms
config . QueryParameters . Search = " \" subject:meeting AND from:manager \" " ;
Delta Query
Get incremental changes to messages.
var deltaResponse = await graphClient . Me . Messages . Delta . GetAsync ();
foreach ( var message in deltaResponse . Value )
{
Console . WriteLine ( $"Changed: { message . Subject } " );
}
// Store deltaLink for next query
if ( deltaResponse . OdataDeltaLink != null )
{
// Use this link for next delta query
}
var allMessages = new List < Message >();
var response = await graphClient . Me . Messages . GetAsync ( config =>
{
config . QueryParameters . Top = 50 ;
config . QueryParameters . Orderby = new [] { "receivedDateTime desc" };
});
allMessages . AddRange ( response . Value );
while ( response . OdataNextLink != null )
{
response = await graphClient . Me . Messages
. WithUrl ( response . OdataNextLink )
. GetAsync ();
allMessages . AddRange ( response . Value );
}
Error Handling
using Microsoft . Graph . Models . ODataErrors ;
try
{
var message = await graphClient . Me . Messages [ "invalid-id" ]. GetAsync ();
}
catch ( ODataError error )
{
if ( error . Error . Code == "ErrorItemNotFound" )
{
Console . WriteLine ( "Message not found" );
}
else
{
Console . WriteLine ( $"Error: { error . Error . Message } " );
}
}
See Also
Message Model Message resource properties
Calendar API Calendar operations
Events API Calendar event operations
Mail Folders Mail folder management