Introduction
During development, everyone comes to the point where he/she has to send email with the application. It is very easy but sometimes there are tasks that can make you crazy. For example, setting a signature in an Outlook email. It's truly a tricky one. ;)
Background
After lots of time searching how to do things with Outlook mailing, I would like to share my final class for sending emails. Besides that, there are also lots of other cool things you can do with Outlook but that should have a separate article on its own.
The class uses an email validation method that validates email addresses. I found this part here. Just modified it to fit in a static
class:
private static bool invalid = false;
public static bool IsValidEmailString(string strIn)
{
invalid = false;
if (String.IsNullOrEmpty(strIn))
return false;
try
{
strIn = Regex.Replace(strIn, @"(@)(.+)$", DomainMapper,
RegexOptions.None, TimeSpan.FromMilliseconds(200));
}
catch (RegexMatchTimeoutException)
{
return false;
}
if (invalid)
return false;
try
{
return Regex.IsMatch(strIn,
@"^(?("")(""[^""]+?""@)|
(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])quot; +
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,24}))$",
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
For this part, I won't write any explanation because it is explained in the above link.
And there we are. Already at the main method that sends the email. ;)
public static void SendEmail(string[] to, string subject, string body, string[] attachments, bool display = true, bool useSignature = true)
{
Outlook.Application outlookApp = new Outlook.Application();
Outlook.NameSpace nameSpace = outlookApp.GetNamespace("MAPI");
Outlook.MAPIFolder mapiFolder = nameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail);
Outlook.MailItem mailItem = mapiFolder.Items.Add(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
Outlook.Recipients recipients = mailItem.Recipients as Outlook.Recipients;
mailItem.Subject = subject;
foreach (string tempTO in to)
{
if (tempTO != string.Empty && IsValidEmailString(tempTO))
recipients.Add(tempTO);
}
recipients.ResolveAll();
foreach (string attachment in attachments)
{
if (File.Exists(attachment))
mailItem.Attachments.Add(attachment);
}
mailItem.GetInspector.Activate();
var signature = mailItem.HTMLBody;
mailItem.HTMLBody = body;
if (useSignature)
mailItem.HTMLBody += signature;
if (mailItem.Recipients.Count == 0 || display)
{
mailItem.Display();
}
else
{
mailItem.Send();
}
}
Every line of code is commented. The tricky part is to get the signature of the default user and add it to the email body. With GetInspector.Active()
, we set the default signature to the mailItem
HTML body. After that, we just save the HTML body to a var
. After that, we can add the signature to the body with our text in it.
Besides this method, we can make 2 others that we can use for simple email actions like sending just an email without attachments or with just one recipient and one attachment:
public static void SendEmail(string to, string subject, string body, string attachment, bool display = true, bool useSignature = true)
{
SendEmail(new string[] { to }, subject, body, new string[] { attachment }, display, useSignature);
}
public static void SendEmail(string to, string subject, string body, bool display = true, bool useSignature = true)
{
SendEmail(to, subject, body, null, display, useSignature);
}
Let's now take a look at the whole class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Net;
using System.Net.Mail;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Diagnostics;
using System.IO;
namespace ICS.EnterpriseResourcePlaning
{
public static class Email
{
private static bool invalid = false;
public static bool IsValidEmailString(string strIn)
{
invalid = false;
if (String.IsNullOrEmpty(strIn))
return false;
try
{
strIn = Regex.Replace(strIn, @"(@)(.+)$", DomainMapper,
RegexOptions.None, TimeSpan.FromMilliseconds(200));
}
catch (RegexMatchTimeoutException)
{
return false;
}
if (invalid)
return false;
try
{
return Regex.IsMatch(strIn,
@"^(?("")(""[^""]+?""@)|
(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,24}))$",
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
private static string DomainMapper(Match match)
{
IdnMapping idn = new IdnMapping();
string domainName = match.Groups[2].Value;
try
{
domainName = idn.GetAscii(domainName);
}
catch (ArgumentException)
{
invalid = true;
}
return match.Groups[1].Value + domainName;
}
public static void SendEmail(string[] to, string subject,
string body, string[] attachments, bool display = true, bool useSignature = true)
{
Outlook.Application outlookApp = new Outlook.Application();
Outlook.NameSpace nameSpace = outlookApp.GetNamespace("MAPI");
Outlook.MAPIFolder mapiFolder = nameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail);
Outlook.MailItem mailItem = mapiFolder.Items.Add(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
Outlook.Recipients recipients = mailItem.Recipients as Outlook.Recipients;
mailItem.Subject = subject;
foreach (string tempTO in to)
{
if (tempTO != string.Empty && IsValidEmailString(tempTO))
recipients.Add(tempTO);
}
recipients.ResolveAll();
foreach (string attachment in attachments)
{
if (File.Exists(attachment))
mailItem.Attachments.Add(attachment);
}
mailItem.GetInspector.Activate();
var signature = mailItem.HTMLBody;
mailItem.HTMLBody = body;
if (useSignature)
mailItem.HTMLBody += signature;
if (mailItem.Recipients.Count == 0 || display)
{
mailItem.Display();
}
else
{
mailItem.Send();
}
}
public static void SendEmail(string to, string subject, string body,
string attachment, bool display = true, bool useSignature = true)
{
SendEmail(new string[] { to }, subject, body, new string[] { attachment }, display, useSignature);
}
public static void SendEmail(string to, string subject,
string body, bool display = true, bool useSignature = true)
{
SendEmail(to, subject, body, null, display, useSignature);
}
}
}
IMPORTANT: Don't forget to add the Office/Outlook Library to your project.
Using the Code
Now we can see what we can do using this static
class.
Send an email to one recipient, without attachments and without signature:
Email.SendEmail(txtEmail.Text, "Subject", "TEST MESSAGE",true,false);
In this example, the email address is saved in a TextBox
. We don't know if it is valid or not. Also the other arguments could be in TextBox
es or other controls.
Send an email with multiple recipients, multiple attachments and with the signature:
Email.SendEmail(new string [] {recipient1,recipient2,recipient3},
"Subject", "TEST MESSAGE",new string[] {attacment1,attachment2,attachment3});
Points of Interest
The only thing that bothers me in this code is that even if I set the display bool to false
, the email is shown for a second. I found out that it is the "GetInspector.Active()
" line causing this. Besides that, the code works like it should. :D
History