C#, msoControlComboBox, Programming, SharePoint, Software, Technology, VB.NET, VSTO

VSTO Add a Menu Item to Outlook and Save an Email into SharePoint

SharePoint Documents List
SharePoint Documents List

Some really cool functionality that you can put together is to automate saving emails from your Outlook email application to be stored in a SharePoint document list. This lets your users keep using the tools they are comfortable working with (such as Outlook), but helps make sure that important emails are backed up to a reliable storage and reporting medium like SharePoint with as little effort on the user’s part as possible.  

All it takes to create an Outlook Add-in to save emails to SharePoint is a bit of custom code.

For starters, you’ll need to create a new VSTO project in Visual Studio. For this example, I’m using Visual Studio 2017 Community Edition. You’ll also need to have a SharePoint site with a Document list that you can save the emails to (I am using on-premises SharePoint 2016).

So how does the connection between Outlook and SharePoint happen?

Happily, SharePoint exposes a whole lot of functionality to developers for connecting their tailor-made apps that are not physically present on the SharePoint server. Microsoft calls this the SharePoint client object model. This is really cool, because often you’ll want to have your users using applications that are not physically present on the SharePoint server itself.

I’m actually surprised that there aren’t more examples of doing a simple email save into SharePoint. In this article I’ll show a super-simple, but fully functional VSTO Visual Studio Project for saving one or more emails into a SharePoint document library.

The save script in this example is the simplest way to upload a file. Note that this method does impose a 2 MB size limit on files being uploaded. If this is good enough for your purposes, then it’s best to go with this way of uploading your messages. Alternately, in a later article I will show the code you need to allow you to upload unlimited sized files (but watch out, because your users could inadvertently quickly eat up a lot of space on your server by uploading large files)

VB.NET Example to Add an Outlook Add-in Button to Import a Selection of EMails into SharePoint

Below is the code to create a VSTO plugin in Visual Studio to save one or more highlighted emails at the click of a button. The button is contained in a drop-down list that appears in the custom Add-ins tab in Outlook. If you are first putting together this code, you’ll want to create a new VSTO project in Visual Studio and copy in the code. I’m giving samples below in C# as well as VB.NET, although the C# version comes from a code converter (since I wrote the actual code in VB)

Imports Microsoft.SharePoint.Client
Imports System.IO
Imports System.ComponentModel
Imports System.Text.RegularExpressions

Public Class ThisAddIn
    Private menuBar As Office.CommandBar
    Private newMenuBar As Office.CommandBarPopup
    Private buttonOne As Office.CommandBarButton

    Private Sub ThisAddIn_Startup() Handles Me.Startup
        ' Add a Menu Item to Outlook and Save an Email into SharePoint
        AddMenuBar()
    End Sub
    Private Sub AddMenuBar()
        Try
            menuBar = Me.Application.ActiveExplorer().CommandBars.ActiveMenuBar
            newMenuBar = menuBar.Controls.Add(
            Office.MsoControlType.msoControlPopup,
            Temporary:=True)
            If newMenuBar IsNot Nothing Then
                newMenuBar.Caption = "New Menu"
                buttonOne = newMenuBar.Controls.Add(
                Office.MsoControlType.msoControlButton,
                Before:=1, Temporary:=True)

                With buttonOne
                    .Style = Office.MsoButtonStyle.msoButtonIconAndCaption
                    .Caption = "Button One"
                    .FaceId = 65
                    .Tag = "c123"
                End With

                AddHandler buttonOne.Click, AddressOf ButtonOne_Click
                newMenuBar.Visible = True
            End If
        Catch Ex As Exception
            MsgBox(Ex.Message)
        End Try
    End Sub

    Public Sub ButtonOne_Click(ByVal buttonControl As Office.CommandBarButton, ByRef Cancel As Boolean)
        Dim context As New ClientContext("http://testURL/sites/testing")
        Dim testList As List = context.Web.Lists.GetByTitle("Documents")

        Dim mySelection As Outlook.Selection = Me.Application.ActiveExplorer().Selection
        Dim mailitem As Outlook.MailItem = Nothing

        For Each obj As [Object] In mySelection
            If TypeOf obj Is Outlook.MailItem Then
                mailitem = DirectCast(obj, Outlook.MailItem)

                ' Remove special characters from the file name and make sure it is not longer than 100 characters
                Dim strFileName As String = Left(Regex.Replace(mailitem.Subject, "[\/\\\:\?\*\<\>\|]", ""), 100) & ".msg"

                ' The full path will place the email in the user's temporary folder
                Dim strTmpPath As String = System.IO.Path.GetTempPath() & strFileName

                ' Save the email to the user's temp folder and convert it to a .MSG
                mailitem.SaveAs(strTmpPath, Outlook.OlSaveAsType.olMSG)

                ' Open the email file and read it into a byte array
                Dim tmpFile As New FileStream(strTmpPath, FileMode.Open, FileAccess.Read)
                Dim btSaveFile(tmpFile.Length) As Byte
                tmpFile.Read(btSaveFile, 0, tmpFile.Length)
                tmpFile.Close()

                If (mailitem IsNot Nothing) Then
                    UploadDocument("http://testURL/sites/testing", "Documents", strFileName, btSaveFile)
                End If
                ' Clean up the temporary .MSG file from the user's temporary folder
                System.IO.File.Delete(strTmpPath)
            End If
        Next
    End Sub


    Public Sub UploadDocument(siteURL As String, documentListName As String, documentName As String, documentStream As Byte())
        ' set this up using the URL to your SharePoint Web site
        Using clientContext As New ClientContext(siteURL)

            ' This is the name of your document list in SharePoint
            Dim testList As List = clientContext.Web.Lists.GetByTitle("Documents")

            ' Here we get teh file ready to be uploaded by streaming it into a FileCreationInformation object. Note that the URL is the subject of the email
            Dim zTmpFile As New FileCreationInformation()
            zTmpFile.Content = documentStream
            zTmpFile.Url = documentName
            ' This will overwrite an existing file with the same name! Otherwise trying to add a file will throw an error.
            zTmpFile.Overwrite = True
            ' We have to specify the file as belonging to SharePoint since otherwise it is ambiguous
            Dim uploadFile As Microsoft.SharePoint.Client.File = testList.RootFolder.Files.Add(zTmpFile)
            ' uploadFile.ListItemAllFields("INSDATE") = "11/2/2017"
            uploadFile.ListItemAllFields("FromUser") = "Justin Cooney"
            ' Save the values to the custom columns
            uploadFile.ListItemAllFields.Update()

            ' Finally now the document can be uploaded along with any meta-information you might like to add
            clientContext.Load(uploadFile)
            clientContext.ExecuteQuery()

        End Using
    End Sub

    Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown

    End Sub

End Class

C# Version of the Code Above: Using VSTO to add a button to Outlook that imports Highlighted EMails

Ok, so for reference I ran the VB version of the code above into a converter to get the C# version below.

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Microsoft.SharePoint.Client;
using System.IO;
using System.ComponentModel;
using System.Text.RegularExpressions;

public class ThisAddIn
{
	private Office.CommandBar menuBar;
	private Office.CommandBarPopup newMenuBar;

	private Office.CommandBarButton buttonOne;
	private void ThisAddIn_Startup()
	{
		// Add a Menu Item to Outlook and Save an Email into SharePoint
		AddMenuBar();
	}
	private void AddMenuBar()
	{
		try {
			menuBar = this.Application.ActiveExplorer().CommandBars.ActiveMenuBar;
			newMenuBar = menuBar.Controls.Add(Office.MsoControlType.msoControlPopup, Temporary: true);
			if (newMenuBar != null) {
				newMenuBar.Caption = "New Menu";
				buttonOne = newMenuBar.Controls.Add(Office.MsoControlType.msoControlButton, Before: 1, Temporary: true);

				var _with1 = buttonOne;
				_with1.Style = Office.MsoButtonStyle.msoButtonIconAndCaption;
				_with1.Caption = "Button One";
				_with1.FaceId = 65;
				_with1.Tag = "c123";

				buttonOne.Click += ButtonOne_Click;
				newMenuBar.Visible = true;
			}
		} catch (Exception Ex) {
			Interaction.MsgBox(Ex.Message);
		}
	}

	public void ButtonOne_Click(Office.CommandBarButton buttonControl, ref bool Cancel)
	{
		ClientContext context = new ClientContext("http://testURL/sites/testing");
		List testList = context.Web.Lists.GetByTitle("Documents");

		Outlook.Selection mySelection = this.Application.ActiveExplorer().Selection;
		Outlook.MailItem mailitem = null;

		foreach (Object obj in mySelection) {
			if (obj is Outlook.MailItem) {
				mailitem = (Outlook.MailItem)obj;

				// Remove special characters from the file name and make sure it is not longer than 100 characters
				string strFileName = Strings.Left(Regex.Replace(mailitem.Subject, "[\\/\\\\\\:\\?\\*\\<\\>\\|]", ""), 100) + ".msg";

				// The full path will place the email in the user's temporary folder
				string strTmpPath = System.IO.Path.GetTempPath() + strFileName;

				// Save the email to the user's temp folder and convert it to a .MSG
				mailitem.SaveAs(strTmpPath, Outlook.OlSaveAsType.olMSG);

				// Open the email file and read it into a byte array
				FileStream tmpFile = new FileStream(strTmpPath, FileMode.Open, FileAccess.Read);
				byte[] btSaveFile = new byte[tmpFile.Length + 1];
				tmpFile.Read(btSaveFile, 0, tmpFile.Length);
				tmpFile.Close();

				if ((mailitem != null)) {
					UploadDocument("http://testURL/sites/testing", "Documents", strFileName, btSaveFile);
				}
				// Clean up the temporary .MSG file from the user's temporary folder
				System.IO.File.Delete(strTmpPath);
			}
		}
	}


	public void UploadDocument(string siteURL, string documentListName, string documentName, byte[] documentStream)
	{
		// set this up using the URL to your SharePoint Web site
		using (ClientContext clientContext = new ClientContext(siteURL)) {

			// This is the name of your document list in SharePoint
			List testList = clientContext.Web.Lists.GetByTitle("Documents");

			// Here we get teh file ready to be uploaded by streaming it into a FileCreationInformation object. Note that the URL is the subject of the email
			FileCreationInformation zTmpFile = new FileCreationInformation();
			zTmpFile.Content = documentStream;
			zTmpFile.Url = documentName;
			// This will overwrite an existing file with the same name! Otherwise trying to add a file will throw an error.
			zTmpFile.Overwrite = true;
			// We have to specify the file as belonging to SharePoint since otherwise it is ambiguous
			Microsoft.SharePoint.Client.File uploadFile = testList.RootFolder.Files.Add(zTmpFile);
			// uploadFile.ListItemAllFields("INSDATE") = "11/2/2017"
			uploadFile.ListItemAllFields("FromUser") = "Justin Cooney";
			// Save the values to the custom columns
			uploadFile.ListItemAllFields.Update();

			// Finally now the document can be uploaded along with any meta-information you might like to add
			clientContext.Load(uploadFile);
			clientContext.ExecuteQuery();

		}
	}


	private void ThisAddIn_Shutdown()
	{
	}
	public ThisAddIn()
	{
		Shutdown += ThisAddIn_Shutdown;
		Startup += ThisAddIn_Startup;
	}

}

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s