Working with .eml Files in MS Outlook

Similar to the .msg file, which represents an individual MailItem in MS Outlook, the .eml format is employed by Outlook Express and Thunderbird to store messages. An EML file comprises the e-mail text, along with any attachments or files attached to it.

Because EML is not the default format of MS Outlook, it can pose a challenge to developers who want to work with .eml files via Outlook automation. Luckily, there are some very workable solutions to match your specific goals. In the “Saving an Email as an EML File in C#” tutorial, we learned how to programmatically create and save an EML-formatted e-mail by using the SmtpClient class. In today’s follow-up, we’ll write a C# console program to load and send .eml files by using the Microsoft.Office.Interop.Outlook library.

Installing the Microsoft.Office.Interop.Outlook Package

The NuGet Package Manager Console is built into Visual Studio on Windows, in versions 2012 and later. (It is not included with Visual Studio for Mac or Visual Studio Code.)

The console lets you use NuGet PowerShell commands to find, install, uninstall, and update NuGet packages. Using the console is necessary in cases where the Package Manager UI does not provide a way to perform an operation.

Here are the steps for adding the Microsoft.Office.Interop.Outlook package:

  1. In Visual Studio, open the console by using the Tools > NuGet Package Manager > Package Manager Console command.

    The NuGet Package Manager
    Figure 1: The NuGet Package Manager

    The NuGet prompt will launch:

    Each package is licensed to you by its owner. NuGet
       is not responsible for, nor does it grant any licenses
       to, third-party packages. Some packages may include
       dependencies which are governed by additional
       licenses. Follow the package source (feed) URL to
       determine any dependencies.
    
    Package Manager Console Host Version 4.5.0.4685
    
    Type 'get-help NuGet' to see all available NuGet
       commands.
    
    PM>
    
  2. Enter “Install-Package Microsoft.Office.Interop.Outlook” at the prompt. You should see something like the following:

    Attempting to gather dependency information for package
       'Microsoft.Office.Interop.Outlook.15.0.4797.1003' with
       respect to project 'MailReadTests', targeting
       '.NETFramework,Version=v4.6.1'
    Gathering dependency information took 15.2 ms
    Attempting to resolve dependencies for package
       'Microsoft.Office.Interop.Outlook.15.0.4797.1003'
       with DependencyBehavior 'Lowest'
    Resolving dependency information took 0 ms
    Resolving actions to install package 'Microsoft.Office
       .Interop.Outlook.15.0.4797.1003'
    Resolved actions to install package 'Microsoft.Office
       .Interop.Outlook.15.0.4797.1003'
    Retrieving package 'Microsoft.Office.Interop.Outlook
          15.0.4797.1003' from 'nuget.org'.
       GET https://api.nuget.org/v3-flatcontainer/microsoft
          .office.interop.outlook/15.0.4797.1003/microsoft
          .office.interop.outlook.15.0.4797.1003.nupkg
       OK https://api.nuget.org/v3-flatcontainer/microsoft
          .office.interop.outlook/15.0.4797.1003/microsoft
          .office.interop.outlook.15.0.4797.1003.nupkg 741ms
    Installing Microsoft.Office.Interop.Outlook 15.0.4797.1003.
    Adding package 'Microsoft.Office.Interop.Outlook
       .15.0.4797.1003' to folder 'C:\Users\blackjacques
       \source\repos\MailReadTests\packages'
    Added package 'Microsoft.Office.Interop.Outlook.15.0
       .4797.1003' to folder 'C:\Users\blackjacques\source
       \repos\MailReadTests\packages'
    Added package 'Microsoft.Office.Interop.Outlook
       .15.0.4797.1003' to 'packages.config'
    Successfully installed 'Microsoft.Office.Interop.Outlook
       15.0.4797.1003' to MailReadTests
    Executing nuget actions took 5.56 sec
    Time Elapsed: 00:00:11.0316538
    PM>
    

The Program Code

Our program will now be able to reference the Microsoft.Office.Interop.Outlook library to import an .eml file and send it.

Here are the using statements at the top of the Program.cs file for our C# .net console application. You can see the Microsoft.Office.Interop.Outlook library reference on the fourth line:

using System;
using System.Linq;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Diagnostics;
using System.Threading;

Referencing the Outlook Application

Using Outlook as our default e-mail program, we can start a new process via the ProcessStartInfo class. We then have to obtain a reference to the Outlook process to use it:

namespace MailReadTests
{
   class Program
   {
      static void Main(string[] args)
      {
         Outlook.Application oOutlook = null;
         Outlook.NameSpace oNS = null;
         Object objsel = null;
         Outlook.MailItem oMail = null;
         string sendTo = @"guitargodofottawa@gmail.com";
         string fl = @"I:\My Documents\articles\codeguru\C#\Saving
            an E-mail\SavedMail\test_sample_message.eml";
         ProcessStartInfo psi = new ProcessStartInfo(fl);
         psi.UseShellExecute = true;
         Process.Start(psi);
         var process = Process.GetProcessesByName("OUTLOOK")
            .First();
         Thread.Sleep(10);
         while (!process.HasExited)
         {
            try
            {
               oOutlook = (Outlook.Application)Marshal
                  .GetActiveObject("Outlook.Application");
               oNS = oOutlook.Session;
               break;
            }
            catch
            {
               oOutlook = null;
            }
            Thread.Sleep(10);
         }
         // Code to send e-mail will go here...

         oOutlook.Quit();
         oOutlook = null;
      }
   }
}

Sending the Email

We then can select the current item in the active inspector and send it just as we would with any Outlook MailItem:

Outlook.Inspectors inps = oOutlook.Inspectors;
objsel = oOutlook.ActiveInspector().CurrentItem;
if (objsel is Outlook.MailItem)
{
   oMail = (Outlook.MailItem)objsel;
   oMail.To = sendTo;
   oMail.Send();
   Console.WriteLine("email sent.");
}

The Finished Product

Here is the complete code for the MailReadTests program:

using System;
using System.Linq;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Diagnostics;
using System.Threading;

namespace MailReadTests
{
   class Program
   {
      static void Main(string[] args)
      {
         Outlook.Application oOutlook = null;
         Outlook.NameSpace oNS = null;
         Object objsel = null;
         Outlook.MailItem oMail = null;
         string sendTo = @"guitargodofottawa@gmail.com";
         string fl = @"I:\My Documents\articles\codeguru\C#\Saving
            an E-mail\SavedMail\test_sample_message.eml";
         ProcessStartInfo psi = new ProcessStartInfo(fl);
         psi.UseShellExecute = true;
         Process.Start(psi);
         var process = Process.GetProcessesByName("OUTLOOK")
            .First();
         Thread.Sleep(10);
         while (!process.HasExited)
         {
            try
            {
               oOutlook = (Outlook.Application)Marshal
                  .GetActiveObject("Outlook.Application");
               oNS = oOutlook.Session;
               break;
            }
            catch
            {
               oOutlook = null;
            }
            Thread.Sleep(10);
         }
         Outlook.Inspectors inps = oOutlook.Inspectors;
         objsel = oOutlook.ActiveInspector().CurrentItem;
         if (objsel is Outlook.MailItem)
         {
            oMail = (Outlook.MailItem)objsel;
            oMail.To = sendTo;
            oMail.Send();
            Console.WriteLine("email sent.");
         }
         oOutlook.Quit();
         oOutlook = null;
      }
   }
}

Conclusion

In today’s article, we loaded an .eml file from the file system and sent it by using the Microsoft.Office.Interop.Outlook library. In addition to the objects that we worked with, there are also some third-party libraries worth exploring. One of these is Outlook redemption. I have used it in the past and have found it to be very useful. Another, which I have not used, but looks promising, is called MimeReader. Between them, you should be able to accomplish whatever you need to do.

Robert Gravelle
Robert Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read