Posts Tagged ‘Attachments’

Forward an email as an attachment

Tuesday, October 26th, 2010

If you want to share an email with other parties, forwarding it works like a charm in Mail.dll.

There are two ways of forwarding a message:

In this article we’ll describe the second option, in which you add forwarded an email as an attachment appended to your forward. This lets you forward multiple emails in one go too.

Why forward as an attachment?

Forwarding as an attachment is a way to share the email body in exactly the form you received it. This makes it easier for the recipient of your forward to reply to the original sender and it preserves some message details that can otherwise be lost — useful to help troubleshooting email problems, for example.

Forwarding an email

In our example we’ll use Mail.dll .NET IMAP component to download first message from an IMAP server. Then we’ll create new message and we’ll add previously received email as an attachment to it. Finally we’ll use Mail.dll SMTP client to send this message.

Please note that we are using MimeFactory class to create MIME object with content type set to mime-rfc822. This content type is specially designed for attaching email messages.

// C# version

byte[] eml = GetFirstMessage();

MailBuilder builder = new MailBuilder();
builder.From.Add(new MailBox("from@example.com"));
builder.To.Add(new MailBox("forward_address@example.com"));
builder.Subject = "Forwarded email is attached";

// attach the message
MimeRfc822 rfc822 = new MimeFactory().CreateMimeRfc822();
rfc822.Data = eml;

builder.AddAttachment(rfc822);

IMail forward = builder.Create();

using (Smtp smtp = new Smtp())
{
    smtp.Connect("smtp.example.com"); // or ConnectSSL if you want to use SSL
    smtp.UseBestLogin("user", "password");
    smtp.SendMessage(forward);
    smtp.Close();
}


static byte[] GetFirstMessage()
{
    byte[] eml;
    using (Imap imap = new Imap())
    {
        imap.Connect("imap.example.com"); // or ConnectSSL if you want to use SSL
        imap.UseBestLogin("user", "password");

        // Receive first message
        List<long> uids = imap.GetAll();
        if (uids.Count == 0)
            throw new Exception("There are no messages");
        eml = imap.GetMessageByUID(uids[0]);
        imap.Close();
    }
    return eml;
}
' VB.NET version

Dim eml As Byte()= GetFirstMessage()

Dim builder As New MailBuilder()
builder.From.Add(New MailBox("from@example.com"))
builder.[To].Add(New MailBox("forward_address@example.com"))
builder.Subject = "Forwarded email is attached"

' attach the message
Dim rfc822 As MimeRfc822 = New MimeFactory().CreateMimeRfc822()
rfc822.Data = eml

builder.AddAttachment(rfc822)

Dim forward As IMail = builder.Create()

Using smtp As New Smtp()
    smtp.Connect("smtp.example.com") ' or ConnectSSL if you want to use SSL
    smtp.UseBestLogin("user", "password")
    smtp.SendMessage(forward)
    smtp.Close()
End Using


Private Function GetFirstMessage() As Byte()
    Dim eml As Byte()
    Using imap As New Imap()
        imap.Connect("imap.example.com") ' or ConnectSSL if you want to use SSL
        imap.UseBestLogin("user", "password")

        ' Receive first message
        Dim uids As List(Of Long) = imap.GetAll()
        If uids.Count = 0 Then
            Throw New Exception("There are no messages")
        End If
        eml = imap.GetMessageByUID(uids(0))
        imap.Close()
    End Using
    Return eml
End Function

Forwarding an email saved to disk

If your original message is already saved on disk. You can use AddAttachment method. It will automatically choose correct content-type using the file’s extension (.eml).

// C#

MailBuilder builder = new MailBuilder();
builder.From.Add(new MailBox("bob@example.com", "Bob"));
builder.To.Add(new MailBox("alice@example.com", "Alice"));
builder.Subject = "Forwarded message";
builder.Text = "Forwarded message is attached.";

builder.AddAttachment("original.eml");

IMail forward = builder.Create();
' VB.NET

Dim builder As New MailBuilder()
builder.From.Add(New MailBox("bob@example.com", "Bob"))
builder.[To].Add(New MailBox("alice@example.com", "Alice"))
builder.Subject = "Forwarded message"
builder.Text = "Forwarded message is attached."

builder.AddAttachment("original.eml")

Dim forward As IMail = builder.Create()

Send email with attachment

Monday, October 25th, 2010

In this article we’ll create and send email with an attachment.

As a prerequisite you need to add reference to Mail.dll .NET email component to your project.

We’ll use MailBuilder class to create email message. This will be plain text message sent from Alice to Bob:

MailBuilder builder = new MailBuilder();
builder.From.Add(new MailBox("alice@mail.com", "Alice"));
builder.To.Add(new MailBox("bob@mail.com", "Bob"));
builder.Subject = "Test";
builder.Text = "This is plain text message.";

You use AddAttachment method to add new attachment to the email, it returns MimeData class instance, that can by used to change/set file name, data, content-id, or any other MIME header. This method has 3 overloads, that allow to create and add attachment from file, byte array or add existing MimeData object as email attachment. In our sample we’ll create attachment from file located on disk.

MimeData attachment = builder.AddAttachment(@"../image.jpg");

Mail.dll email component automatically recognizes content type using file extension. When you create attachment using byte array or MemoryStream, you can use ContentType property to set it manually:

attachment.ContentType = ContentType.ImageJpeg;

Finally we’ll use Smtp component to connect to SMTP server and send your message.

Following is the entire sample, that creates new email message, adds attachment from file located on disk. Than it connects to specified SMTP server and sends the message. Please note that some error handling is missing for simplicity and you should examine ISendMessageResultresult object returned by SendMessage to be sure that email sending was successful.

// C# version

using System;
using Limilabs.Mail;
using Limilabs.Mail.Headers;
using Limilabs.Client.SMTP;

class Program
{
    static void Main(string[] args)
    {
        // Use builder class to create new email message
        MailBuilder builder = new MailBuilder();
        builder.From.Add(new MailBox("alice@mail.com", "Alice"));
        builder.To.Add(new MailBox("bob@mail.com", "Bob"));
        builder.Subject = "Test";
        builder.Text = "This is plain text message.";

        // Read attachment from disk, add it to Attachments collection
        MimeData attachment = builder.AddAttachment(@"../image.jpg");

        IMail email = builder.Create();

        // Send the message
        using (Smtp smtp = new Smtp())
        {
            smtp.Connect("server.example.com");   // or ConnectSSL for SSL
            smtp.UseBestLogin("user", "password");   // remove if not needed

            smtp.SendMessage(email);

            smtp.Close();
        }

    }
};
' VB.NET version

Imports Limilabs.Client.SMTP
Imports Limilabs.Mail
Imports Limilabs.Mail.MIME
Imports Limilabs.Mail.Headers

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

        ' Use builder class to create new email message
        Dim builder As New MailBuilder()
        builder.From.Add(New MailBox("alice@mail.com", "Alice"))
        builder.[To].Add(New MailBox("bob@mail.com", "Bob"))
        builder.Subject = "Test"
        builder.Text = "This is plain text message."

        ' Read attachment from disk, add it to Attachments collection
        Dim attachment As MimeData = builder.AddAttachment("../image.jpg")

        Dim email As IMail = builder.Create()

        ' Send the message
        Using smtp As New Smtp()
            smtp.Connect("server.example.com")    ' or ConnectSSL for SSL
            smtp.UseBestLogin("user", "password")   ' remove if not needed

            smtp.SendMessage(email)

            smtp.Close()
        End Using
    End Sub
End Module

Save all attachments to disk using POP3

Monday, October 25th, 2010

This article describes how to save all email messages’ attachments to disk. The messages are downloaded using Mail.dll library and POP3 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.

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.

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

using Limilabs.Mail;
using Limilabs.Mail.MIME;
using Limilabs.Client.POP3;

class Program
{
    static void Main(string[] args)
    {
        Pop3 pop3 = new Pop3();
        pop3.Connect("pop3.example.com");
        pop3.Login("user", "password");

        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.Attachments)
            {
                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("pop3.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.Attachments
                    mime.Save("c:\" + mime.SafeFileName)
                Next
            Next
            pop3.Close()
        End Using

    End Sub
End Module

Accessing attachment’s data

You can also save attachment to stream: void MimeData.Save(Stream stream).
You can directly access attachment’s data as stream using MimeData.GetMemoryStream() method or as byte array using MimeData.Data property.

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.

Save images embedded in HTML email to disk using IMAP

Monday, October 25th, 2010

This article shows how to save all images embedded in HTML email message to disk. The messages are downloaded using Mail.dll .NET IMAP library and IMAP 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 (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.

// 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");
           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.Visuals)
               {
                   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")
            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

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")

Save all attachments to disk using IMAP

Monday, October 25th, 2010

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.