Save images embedded in HTML email to disk using POP3
This article shows how to save all images embedded in HTML email message to disk. The messages are downloaded using Mail.dll .NET POP3 component and POP3 protocol.
In most cases HTML body of the message references such images using special “cid:” protocol, that specifies Content-ID of the image that should be used:
This is our <strong>brand new</strong> logo: <br /> <img src="cid:logo@example.com" />
In such case actual image is embedded inside an email, as part of the mime tree, as an element related to HTML body and with content-disposition header set to inline. This means that invoking GetMessageByUID method is going to download entire email message, including all images. This makes message bigger, but images don’t need to be stored on your web server (and remember that emails tend to be archived for years).
Mail.dll exposes 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.
As you can see the most interesting from this article’s point of view is IMail.Visuals collection. As with regular attachments, visual elements are represented by MimeData objects.
using Limilabs.Mail; using Limilabs.Mail.MIME; using Limilabs.Client.POP3; class Program { static void Main(string[] args) { Pop3 pop3 = new Pop3(); pop3.Connect("server.company.com"); pop3.Login("user", "password"); // Receive all messages foreach (string uid in pop3.GetAll()) { var eml = pop3.GetMessageByUID(uid); IMail email = new MailBuilder() .CreateFromEml(eml); Console.WriteLine(email.Subject); foreach (MimeData mime in email.Visuals) { mime.Save(@"c:\" + mime.SafeFileName); } } pop3.Close(); } };
' VB.NET Imports Limilabs.Mail Imports Limilabs.Mail.MIME Imports Limilabs.Client.POP3 Public Module Module1 Public Sub Main(ByVal args As String()) Using pop3 As New Pop3() pop3.Connect("server.example.com") pop3.Login("user", "password") Dim uids As List(Of Long) = pop3.GetAll() For Each uid As Long In uids Dim eml = pop3.GetMessageByUID(uid) Dim email As IMail = New MailBuilder() _ .CreateFromEml(eml) Console.WriteLine(email.Subject) For Each mime As MimeData In email.Visuals mime.Save("c:\" + mime.SafeFileName) Next Next pop3.Close() End Using End Sub End Module
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.
You can also use SaveHtmlAs method to save entire message as regular HTML page with all required images and styles to a single folder:
// C# IMail email = ... email.SaveHtmlAs(@"c:\tmp\email.html");
' VB.NET Dim email As IMail = ... email.SaveHtmlAs("c:\tmp\email.html")
What is also worth mentioning is the fact that you can use Content-Id to search through IMail.Visuals collection:
// C# IMail email = ...; MimeData logo = email.Visuals["logo@example.com"];
// VB.NET Dim email As IMail = ... Dim logo As MimeData = email.Visuals("logo@example.com")