Save all attachments to disk using IMAP

This article describes how to save all email messages’ attachments to disk. The messages are downloaded using Mail.dll IMAP component and IMAP protocol.

The first thing you need to know is that email attachments are downloaded along with the email message. This means that invoking GetMessageByUID method is going to download entire email message, including all attachments. Attachments are stored within the email as part of a mime tree. Usually Quoted-Printable or Base64 encoding is used. Mail.dll is going to parse such tree for you and expose all attachments as well-known .NET collections.

There are 4 collections that may contain attachments:

  • IMail.Attachments – all attachments (includes Visuals, NonVisuals and Alternatives).
  • IMail.Visuals – visual elements, files that should be displayed to the user, such as images embedded in an HTML email.
  • IMail.NonVisuals – non visual elements, “real” attachments.
  • IMail.Alternatives – alternative content representations, for example ical appointment.

You should use IMail.Attachments collection to get all attachments. Every attachment is represented by MimeData object.

// C#

using Limilabs.Client.IMAP;
using Limilabs.Mail;
using Limilabs.Mail.MIME
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        using(Imap imap = new Imap())
        {
            imap.Connect("imap.example.com"); // or ConnectSSL for SSL
            imap.UseBestLogin("user", "password");
    
            imap.SelectInbox();
            List<long> uids = imap.Search(Flag.Unseen);
            foreach (long uid in uids)
            {
                var eml = imap.GetMessageByUID(uid);
                IMail email = new MailBuilder()
                    .CreateFromEml(eml);
                Console.WriteLine(email.Subject);
    
                foreach (MimeData mime in email.Attachments)
                {
                    mime.Save(@"c:\" + mime.SafeFileName);
                }
            }
            imap.Close();
        }
    }
};
' VB.NET

Imports Limilabs.Client.IMAP
Imports Limilabs.Mail
Imports Limilabs.Mail.MIME
Imports System
Imports System.Collections.Generic

Public Module Module1
    Public Sub Main(ByVal args As String())

        Using imap As New Imap()
            imap.Connect("imap.example.com") ' or ConnectSSL for SSL
            imap.UseBestLogin("user", "password")

            imap.SelectInbox()
            Dim uids As List(Of Long) = imap.Search(Flag.Unseen)

            For Each uid As Long In uids
                Dim eml = imap.GetMessageByUID(uid)
                Dim email As IMail = New MailBuilder() _
                    .CreateFromEml(eml)
                Console.WriteLine(email.Subject)

                For Each mime As MimeData In email.Attachments
                    mime.Save("c:\" + mime.SafeFileName)
                Next
            Next
            imap.Close()
        End Using

    End Sub
End Module

Accessing attachment’s data

You can also save attachment to stream MimeData.Save(Stream stream), get direct access to it as stream MemoryStream MimeData.GetMemoryStream()
or as byte array using byte[] MimeData.Data property.

Downloading only parts of the message

IMAP protocol provides very useful features in regard to working with attachments.
You can download only parts of email message, which in conjunction with getting basic email information without downloading entire message can make your code very fast.

Process emails embedded as attachments

In many situations you’ll receive a message that has another message attached. You can use Mail.dll to extract all attachments from such inner messages no matter on how deep the embedding level is.

Tags: , , , , ,

10 Responses to “Save all attachments to disk using IMAP”

  1. A K Das Says:

    Dear all i need to download attachment in web application how can i download attachments from any mail server in asp.net (C#) Application

  2. Limilabs support Says:

    @A K Das
    Please take a look at this post:
    http://www.limilabs.com/blog/receive-unseen-emails-using-imap
    It describes how to download unseen emails using IMAP protocol.

  3. Receive unseen emails using IMAP | Blog | Limilabs Says:

    […] At that point you can also access attachments. […]

  4. Shadowfax Says:

    Hi there
    using the library is it possible to save the entire email (including all attachments) as a .eml file ? I need to store the raw format of the mail and when opening the file – it will use the default mail application .

  5. Limilabs support Says:

    @Shadowfax,

    Yes, it is possible. You should simply save the eml data you get from GetMessageByUID method:
    http://www.limilabs.com/blog/save-raw-eml-file-imap-pop3

  6. ThomasD Says:

    How can I store attachments into a database blob field e.g. via memorystream?

  7. Limilabs support Says:

    @ThomasD

    You can get direct access to attachment’s data as MemoryStream using MimeData.GetMemoryStream() method.

  8. ThomasD Says:

    Perfect! Thank you.

  9. Chris B Says:

    Is it possible to first retrieve the message by its message ID, rather than using a combination of the long uid and setting the correct folder?

  10. Limilabs support Says:

    @Chris B,

    You can search by message-id (Expression.MessageId), but you still need to select a folder to search in. There is no server-wide search in IMAP protocol.

    If you are using Gmail however, all emails are stored in “All Mail” folder – you can search there (consider also using Expression.GmailMessageId as it is set by server and is valid in all folders).

Questions?

Consider using our Q&A forum for asking any questions.