Skip to content

Receiver

Daniel Collingwood edited this page Sep 20, 2023 · 39 revisions

Installation NuGet Downloads

Package Manager Console: > Install-Package MailKitSimplified.Receiver # -Version x.x.x

.NET CLI Console: > dotnet add package MailKitSimplified.Receiver # --version x.x.x

Example:

cd ./MailKitSimplified/samples/ConsoleServiceExample
dotnet add package MailKitSimplified.Receiver --version 2.4.8-tags-v2-4-8-eta0001
../MailKitSimplified.ConsoleServiceExample.sln

Setup

Receiving emails can be as simple as one line of code if you specify IMAP options in appsettings.json, read how to do that in the dependency injection wiki.

var mimeMessages = await _readMail.GetMimeMessagesAsync();

If you're not familiar with dependency injection then you can specify how to connect to the IMAP host like this:

using var imapReceiver = ImapReceiver.Create("imap.example.com:993")
    .SetCredential("user@example.com", "App1icati0nP455w0rd")
    .SetProtocolLog("Logs/ImapClient.txt")
    .SetFolder("INBOX/My Subfolder");

An email receiver must have a IMAP host address and a network credential, leaving out the port number will normally choose the right port automatically (e.g. 143 or 993). Use SetProtocolLog("console") to quickly debug with detailed logging to the console.

Receiving Mail

To download full emails with attachments and everything:

var mimeMessages = await imapReceiver.ReadMail
    .Skip(0).Take(250, continuous: true)
    .GetMimeMessagesAsync();

The Skip() and Take() methods are optional, but they allow you to specify a range of message instead of potentially downloading thousands of emails, something that could take a very long time. You should always use a CancellationToken, especially if you don't set Take to a small number.

To just download the email parts you want to use (UniqueId is included by default and very small so all results are returned):

var messageSummaries = await imapReceiver.ReadFrom("INBOX")
    .GetMessageSummariesAsync();

To query the SMTP server and get unique IDs for the top 250 emails:

var messageSummaries = await imapReceiver.ReadMail.Query(SearchQuery.All)
    .Items(MailFolderReader.CoreMessageItems)
    .GetMessageSummariesAsync();

Other useful MessageSummaryItems to know about are Size, InternalDate, Envelope, and BodyStructure.

Further examples (how to set up MailKit IMAP server logs etc.) can be found in the samples and tests folders on GitHub.

Mail Folder Idle Monitor

To asynchronously monitor the mail folder for incoming messages:

await new MailFolderMonitor(imapReceiver).SetMessageSummaryItems(MessageSummaryItems.Envelope)
    .SetIgnoreExistingMailOnConnect(true).SetIdleMinutes(29).SetMaxRetries(1)
    .OnMessageArrival((messageSummary) => OnArrivalAsync(messageSummary))
    .OnMessageDeparture((messageSummary) => OnDepartureAsync(messageSummary))
    .IdleAsync();

The values shown above are the default method override values, the de-facto FolderMonitorOptions are UniqueId, false, 9, and 3 respectively. If you're happy with the latter then using MailFolderMonitor is even easier:

await imapReceiver.MonitorFolder.OnMessageArrival(ForwardMessageAsync).IdleAsync();

One line of code instead of 251! It never used to be that easy.

Message Flags

Here's how to mark all incoming messages as Seen:

await imapReceiver.MonitorFolder
	.OnMessageArrival(m => m.AddFlagsAsync(MessageFlags.Seen))
	.IdleAsync(); //cancellationToken

Adding flags to a message summary now also checks to make sure the folder is open and writeable.

Here's how to delete the first 250 Seen messages in the Inbox (v2.5.1-alpha / RC1):

var messageSummaries = await imapReceiver.ReadMail.Query(SearchQuery.Seen).GetMessageSummariesAsync();
await imapReceiver.MailFolderClient.DeleteMessagesAsync(messageSummaries); //cancellationToken

If there's a delete flag then it calls the Expunge method internally.

Forwarding Emails

Here's how to forward an email:

async Task ForwardMessageAsync(IMessageSummary messageSummary)
{
    var mimeForward = await messageSummary.GetForwardMessageAsync(
        "<p>FYI.</p>", includeMessageId: true);
    mimeForward.From.Add("from@example.com");
    mimeForward.To.Add("to@example.com");
    _logger.LogInformation($"Reply: \r\n{mimeForward.HtmlBody}");
    await _smtpSender.SendAsync(mimeForward); //cancellationToken
}

Replying To Emails

Here's how to download an email and reply to it:

var mimeMessages = await _imapReceiver.ReadMail.Take(1).GetMimeMessagesAsync();
var mimeReply = mimeMessages.Single().GetReplyMessage("<p>Reply here.</p>", addRecipients: true);

To only download the email parts you want to use:

var messageSummaries = await imapReceiver.ReadMail.Take(1)
    .Items(MessageSummaryItems.All)
    .GetMessageSummariesAsync();
var mimeReply = await messageSummaries.Single()
    .GetReplyMessageAsync("<p>Reply here.</p>");
mimeReply.From.Add(new MailboxAddress("", "from@localhost"));
mimeReply.To.Add(new MailboxAddress("", "to@localhost"));

One line of code instead of 238! It never used to be that easy.

Download MimeMessage

You can easily save any email and use it again later as a template.

var mimeMessage = await messageSummary.GetMimeMessageAsync(cancellationToken);
string downloadFilePath = Path.GetFullPath(filePath);
await MimeMessageReader.Create(mimeMessage).SetLogger(_loggerFactory)
    .SaveAsync(downloadFilePath, false, cancellationToken);

See Also

Clone this wiki locally