I have been working a lot lately on existing and new application projects that require emails to be sent via Microsoft Office 365.

Traditionally this would be done using the System.Net.Mail class library over the SMTP protocol. Something like this…

MailMessage msg = new MailMessage();
msg.To.Add(new MailAddress("someone@somedomain.com", "SomeOne"));
msg.From = new MailAddress("you@yourdomain.com", "You");
msg.Subject = "This is a Test Mail";
msg.Body = "This is a test message using Exchange OnLine";
msg.IsBodyHtml = true;

SmtpClient client = new SmtpClient();
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("your user name", "your password");
client.Port = 587;
client.Host = "smtp.office365.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.EnableSsl = true;
try
{
  client.Send(msg);
  Console.WriteLine("Message Sent Succesfully");
}
catch (Exception ex)
{
  Console.WriteLine(ex.ToString());
}

I see an increasing amount of limitations with this approach. Here are some of those limitations:

  • SMTP ports closed my endpoint security products
  • SMTP ports blocked by border network equipment
  • Microsoft frequently changing encryption and authentication requirements
  • Public IP address, service account and credential issues

In short, a simpler approach was required and Microsoft have provided this approach via the Microsoft Graph API. Let me list some of the obvious benefits:

  • Ability to utilise existing web application filter / proxy technology
  • Authentication is performed via OAuth (including certificate based authentication)
  • All communication is performed via industry standard REST calls over secure HTTP

Lets get started. The first step is to register an application endpoint, define a secret and configure API permissions.

1. Go to your Azure Active Directory via Azure Active Directory Portal.

2. Select App registrations

3. Select new registration

4. Enter in your display name. For this tutorial I will use “Send Graph Email”.

5. Make a note of your Application Id and then select Certificates and Secrets

6. Create a new client secret. You will also note that this expires and will need to be rotated.

7. Copy the value of the secret. Once you leave the screen you will not be able to retrieve it again.

8. Select API Permissions. Then select add a permission.

9. Under Microsoft APIs. Under commonly used APIs. Select Microsoft Graph.

10.Select Application permissions. Then under Select Permissions. Choose Mail.Send. Select Add Permission.

11. Finally you need to grant consent. Select Grant admin consent for your organisation.


Now we can author and implement the replacement code necessary to move off System.net.mail.

The first thing you will need to do is retrieve a bearer token using the application id and secret you configured and captured above. For the examples below I will be using the RESTSharp and Newtonsoft dependencies.

var _client_id = "1575e70f-eb98-49f9-8f30-7df68cbfbd28";
var _client_secret = "WA0_WZ2uN9W.POL~wGIJtxtD.~a58WX47X";
var _tenant = "yourdomain.online";

var _uri = $"https://login.microsoftonline.com/{_tenant}/oauth2/v2.0/token";

var client = new RestClient(_uri);
client.Timeout = -1;

var request = new RestRequest(Method.POST);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("client_id", _client_id);
request.AddParameter("client_secret", _client_secret);
request.AddParameter("scope", "https://graph.microsoft.com/.default");

IRestResponse response = client.Execute(request);

var token = JObject.Parse(response.Content);
var access_token = token.GetValue("access_token");
Console.WriteLine(access_token);

Console.WriteLine("Press any key to exit...");
Console.ReadKey();

The token will look similar to this:-

Armed with your bearer token you can now start sending emails as per the sample below.

string _email = "noreply@yourdomain.online";
string htmlBody = "Sample Email";
string access_token = "Bearer Token String from previous sample";

var body = new
{
    message = new
    {
        subject = "Sample Subject",
        body = new
        {
            contentType = "HTML",
            content = htmlBody,
        },
        toRecipients = new[]
        {
            new {
                emailAddress = new { address = "to.user@domain.com" }
            }
        }
    }
};
string bodyJson = JsonConvert.SerializeObject(body);

var uri = $"https://graph.microsoft.com/v1.0/users/{_email}/sendMail";
var client = new RestClient(uri);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer " + access_token);
request.AddParameter("application/json", bodyJson, ParameterType.RequestBody);

var response = client.Execute(request);

if (response.StatusCode != HttpStatusCode.Accepted)
    Console.WriteLine("Email sent");
else
    Console.WriteLine("Email was not sent.");

As always. I hope this article was informative and useful.

Until next time.