EWS: How to send signed email using the EWS Managed API


A question that keeps popping up is how to send signed or encrypted email using EWS.  A colleague (thank-you Vladimir!) has recently put together some sample code showing how to do exactly that using the EWS Managed API.  Based on his sample code, I’ve been able to partially complete my Windows Forms application that shows how this can be done.  The basic idea is to create the Mime content, then sign that content and write it to the MimeContent property.  Vladimir’s code (below) shows how to do this from scratch building your own message.  My adaptation, in the attached Visual Studio 2015 solution, creates an EWS message as normal, then uses EWS to create the actual Mime (by saving the message as a draft then reading it back) – this is then read, signed, and written back to the message.  The advantage of this is that you can easily add attachments and anything else needed without having to learn how this works at an email level (i.e. you can just let EWS do this for you).

So, to the code:

var cert = new X509Certificate2(@"..\..\..\UserA_cert_for_email.pfx", "1234");

var mail = new EmailMessage(exchService);
mail.ItemClass = "IPM.Note.SMIME";
var msgId = Guid.NewGuid().ToString("N");
var boundary = "----=_NextPart_" + msgId + "." + (new Random(100)).Next(999999);
var sb = new StringBuilder();
sb.AppendLine("From: UserA@vd-test.local");
sb.AppendLine("To: UserA@vd-test.local");
sb.AppendLine("Subject: SMIME test subject " + (new Random(100)).Next(999));
sb.AppendLine("Message-ID:\n <" + msgId + "@vd-srv08r2-dc.vd-test.local>");
sb.AppendLine("Content-Language: en-US");
sb.AppendLine("Content-Type: application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\"");
sb.AppendLine("Content-Disposition: attachment; filename=\"smime.p7m\"");
sb.AppendLine("Content-Transfer-Encoding: base64");
sb.AppendLine("MIME-Version: 1.0");
sb.AppendLine("");

var mimeHeader = sb.ToString();

sb.Clear();

sb.AppendLine("Content-Type: multipart/alternative;");
sb.AppendLine("\tboundary=\"" + boundary + "\"");
sb.AppendLine("");
sb.AppendLine("This is a multipart message in MIME format.");
sb.AppendLine("");
sb.AppendLine("--" + boundary);
sb.AppendLine("Content-Type: text/plain;");
sb.AppendLine("\tcharset=\"us-ascii\"");
sb.AppendLine("Content-Transfer-Encoding: 7bit");
sb.AppendLine("");
sb.AppendLine("Hello!");
sb.AppendLine("I am manually generated signed message.");
sb.AppendLine("");
sb.AppendLine("");
sb.AppendLine("--" + boundary);
sb.AppendLine("Content-Type: text/html;");
sb.AppendLine("\tcharset=\"us-ascii\"");
sb.AppendLine("Content-Transfer-Encoding: quoted-printable");
sb.AppendLine("");
sb.AppendLine("<html><head/><body><p>Hello!</p><p>I am manually generated signed message.</p></body></html>");
sb.AppendLine("");
sb.AppendLine("--" + boundary);

var bodyBytes = Encoding.ASCII.GetBytes(sb.ToString());
var content = new ContentInfo(bodyBytes);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert);
signedCms.ComputeSignature(signer);
var bodySignedBytes = signedCms.Encode();

mimeHeader += Convert.ToBase64String(bodySignedBytes);
mail.MimeContent = new MimeContent(Encoding.ASCII.HeaderName, Encoding.ASCII.GetBytes(mimeHeader));
mail.Send();

The sample application can be downloaded below.  Note that while the application states it can encrypt and sign email, I haven’t yet completed the encryption part.  When I get a chance I’ll add that and update.  The application looks like this:

EWSEmailEncryption.zip

Comments (1)

  1. AlexS says:

    What about OpenPGP signed messages? How does this work?

Skip to main content