jstedfast / MailKit

A cross-platform .NET library for IMAP, POP3, and SMTP.

Home Page:http://www.mimekit.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can MailKit save a message to file?

SetTrend opened this issue · comments

Is your feature request related to a problem? Please describe.

The System.Net.Mail.SmtpClient class comes with a great feature that I need to perform automated tests: It can save messages to a pickup folder:

SmtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory
SmtpClient.PickupDirectory = ...

Describe the solution you'd like

MailKit should be able to do so, too.

Based on Microsoft's referencesource, when SmtpDeliveryMethod.SpecifiedPickupDirectory is used, the SmtpClient saves the message to the specified pickup directory location using a randomly generated filename based on Guid.NewGuid ().ToString () + ".eml", so to achieve the same results with MailKit, you could do something like this:

public static void SaveToPickupDirectory (MimeMessage message, string pickupDirectory)
{
    do {
        // Generate a random file name to save the message to.
        var path = Path.Combine (pickupDirectory, Guid.NewGuid ().ToString () + ".eml");
        Stream stream;

        try {
            // Attempt to create the new file.
            stream = File.Open (path, FileMode.CreateNew);
        } catch (IOException) {
            // If the file already exists, try again with a new Guid.
            if (File.Exists (path))
                continue;

            // Otherwise, fail immediately since it probably means that there is
            // no graceful way to recover from this error.
            throw;
        }

        try {
            using (stream) {
                // IIS pickup directories expect the message to be "byte-stuffed"
                // which means that lines beginning with "." need to be escaped
                // by adding an extra "." to the beginning of the line.
                //
                // Use an SmtpDataFilter "byte-stuff" the message as it is written
                // to the file stream. This is the same process that an SmtpClient
                // would use when sending the message in a `DATA` command.
                using (var filtered = new FilteredStream (stream)) {
                    filtered.Add (new SmtpDataFilter ());

                    // Make sure to write the message in DOS (<CR><LF>) format.
                    var options = FormatOptions.Default.Clone ();
                    options.NewLineFormat = NewLineFormat.Dos;

                    message.WriteTo (options, filtered);
                    filtered.Flush ();
                    return;
                }
            }
        } catch {
            // An exception here probably means that the disk is full.
            //
            // Delete the file that was created above so that incomplete files are not
            // left behind for IIS to send accidentally.
            File.Delete (path);
            throw;
        }
    } while (true);
}

Excellent. Thanks a lot for this valuable answer!

PS: Wouldn't an information like this be valuable by being added to the MailKit documentation?

It's in the FAQ: https://github.com/jstedfast/MailKit/blob/master/FAQ.md#smtp-specified-pickup-directory

I couldn't figure out how to grab the link from my phone last night or I would have posted that :-)