C# and Microsoft 365 – Automatically download your attachments

In this guide I would like to show how you can use C# and Microsoft 365 to automatically download email attachments to your local computer on a schedule.

Many companies are taking advantage of Microsoft 365 and their very business friendly toolset of applications. From managing business emails, to connecting on Teams, or utilizing their more advanced network related applications in the cloud.

I recently had a project that involved collecting data through email. It was the only way that data transmission was allowed. Although the complete application was synchronizing the process of automatically placing this emailed data into a database, this article will exclusively explain the fairly easy process of automating the process of downloading email attachments and placing them in a folder on your computer.

Setting everything up

Set up your email

C# and Microsoft 365 Subfolders

For this example A subfolder was created. You can use Outlook rules to ensure your emails with the attachments are directed here. Additionally an archive folder was created to move the email here once the attachment download is complete.

To accomplish this Right click on your inbox folder and create these two folders.

Setup your Local folder path

Create a folder named test on your C drive or in a location of your choosing.

The Extractor

Create a new C# Console application. Add the following dependencies

Microsoft.Office.Interop.Outlook

Interop.Microsoft.Office.Interop.Outlook

Microsoft.Exchange.WebServices.NETStandard

From there we have the dependencies to build our extractor.

What it does

The following code will locate and download any attachments in the provided inbox subfolder. It then moves the email to an archive folder. Please review abbreviated notes for further clarification.

using System;
using System.IO;
using Microsoft.Exchange.WebServices.Data;
using System.Net;
using System.Text;

namespace M365.AttachmentExtractor
{
    class Microsoft365Extractor
    {

        public static async System.Threading.Tasks.Task<int> Extract(string email, string pass, string domain,
            string extractfoldername, string extracttofolder)
        {
            //Start Service
            ExchangeService service = new ExchangeService();
            service.Credentials = new NetworkCredential(email, pass, domain);
            service.AutodiscoverUrl(email, (a) => { return true; });
            //Get Folders
            Folder rootfolder = await Folder.Bind(service, WellKnownFolderName.MsgFolderRoot);            
            await rootfolder.Load();

            FindFoldersResults findResults = await service.FindFolders(
                WellKnownFolderName.Inbox,
                new FolderView(int.MaxValue)
                {
                    Traversal = FolderTraversal.Deep
                });

            //Find the correct folder to extract attachments
            Folder attachmentFolder = null;
            Folder attachmentFolderArchive = null;
            foreach (Folder folder in findResults.Folders)
            {

                if (folder.DisplayName == extractfoldername)
                {
                    attachmentFolder = folder;                   
                }
                if (folder.DisplayName == extractfoldername + "Archive")
                {
                    attachmentFolderArchive = folder;
                }

            }
            FindItemsResults<Item> attachmentResults = null;
            //if the folder is found, get the emails, load them. and extract the attachment
            if (attachmentFolder != null)
            {
                attachmentResults = await service.FindItems(attachmentFolder.Id, new ItemView(1000));
                Console.WriteLine("# of Reports for " + extractfoldername + ": " + attachmentResults.TotalCount);
                int count = 0;
                foreach (Item item in attachmentResults.Items)
                {
                    await item.Load();

                    if (item.HasAttachments && item.Attachments[0] is FileAttachment)
                    {
                        FileAttachment fileAttachment = item.Attachments[0] as FileAttachment;
                        await fileAttachment.Load();
                        string converted = Encoding.Unicode.GetString(fileAttachment.Content, 0, fileAttachment.Content.Length);
                        Console.WriteLine(converted);
                        string path = extracttofolder + fileAttachment.Name;

                        if (File.Exists(path))
                        {
                            path = extracttofolder + (count++) +  fileAttachment.Name;
                            //File.Delete(path);
                        }

                        File.AppendAllText(path, converted);  // File Operation 2

                        string readtext = File.ReadAllText(path); // File Operation 3

                        //Console.WriteLine(readtext);
                    }

                    //Move item to a new folder
                   
                    await item.Move(attachmentFolderArchive.Id);
                    

                }
            }
            if (attachmentResults != null)
            {
                return attachmentResults.TotalCount;
            }
            else {
                return -1;
            }
        }
    }
}

How to Execute Extract Function

Finally, to get this operation to function you will need to call it with an asynchronous Main Method.

    class Program
    {
        //Set the path where you would like your attachments to go
        static readonly string baseFolder = "C:\\path\\to\\the\\folder\\where\\attachments\\are\\downloaded\\";
        static readonly string yourEmail = "[email protected]";
        static readonly string yourPassword = "password";
        static readonly string inboxFolderName = "subinboxfolder";
        static readonly string localComputerFolder = "localsubfolder";

        //Asynchronous Main Method
        static async System.Threading.Tasks.Task Main(string[] args)
        {

                Console.WriteLine("Moving File to Attachments Folder");
               await MoveMatrixAttachToFolder();

        }

        //Asychronous function that calls our service
        static async System.Threading.Tasks.Task<int> MoveMatrixAttachToFolder()
        {

            return await Microsoft365Extractor.Extract(
                      yourEmail
                    , yourPassword                    
                    , inboxFolderName
                    , localComputerFolder
                );

        }
    }

If you know that your build is good, and that your login credentials are correct, then you should have a working application. You could then do a number of things with this. The simplest way to make this process automatic, would be to run the executable using Task Scheduler.

I hope this guide has provided the means for you to use C# and Microsoft 365 to start working with your emails in a programmatic way.

Leave a Reply