Original Photo by Joanna Kosinska on Unsplash

How to send emails in .NET with the Microsoft Graph

Sending emails using the SmtpClient isn’t recommended in .NET and Exchange Online deprecated basic authentication so there is need for a new approach for sending emails through Office 365.

Philipp Bauknecht
Published in
6 min readSep 30, 2022

--

In the past the easiest way to send an email in .NET was using the smtp protocol through the SmtpClient class. This also worked fine when using Exchange Online (Office 365) mailboxes with basic authentication.

For some years now using SmtpClient is no longer recommended. The Microsoft docs state:

… The SmtpClient type is obsolete on some platforms and not recommended on others; for more information, see the Remarks section.

Read more on why here: https://learn.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient?view=net-6.0#remarks

Effective October 1st 2022 Microsoft will also disable basic authentication for security reasons in Exchange Online which typically was used together with the SmtpClient. Read more on the details of this change here: https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online

So what now?

Microsoft Graph to the rescue! Microsoft Graph is a set of restful http APIs to interact with Microsoft 365. This API also allows to send emails on behalf of users.

Note: Exchange Online limits to sending to more than 10,000 mails per day. Learn more about limits here: https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits#sending-limits-1

If you need to send more mails than Exchange Online supports, check out Azure Communication Service

To access the Microsoft Graph a program needs to authenticate itself with a OAuth access token that also provides the right permissions. When building a software where a signed in user is present this is relatively easy as this user can request permission to send mails through the Graph and therefore the program can use this as a delegated permission to do the same.

More interesting though is how to do this when no user is present, e.g. as part of a workflow or other background service process. In this case there are application permissions that can be assigned to an app registration in Azure AD and the service authenticates using the app registration’s clientId and clientSecret as credentials through the client credential flow against Azure AD.

So let’s walk through the steps required for this backgroud service like setup.

#1 Setup app registration in Azure AD

First we need a new app registration that will service as a service principal aka “machine user” to authenticate our background service against AAD. So let’s go to the Azure Portal > AAD > App Registration and create a new one:

Just enter the name of your service and leave everything else here to defaults as we’re not using this features anyway.

After registering the new app registration take note of the ClientId and the TenantId. We’ll need both later in our .NET code:

Next we need a secret as our “password”. Click on “Certificates & secrets” and create a new client secret. Also take note of the secret right away as it will only show once:

Finally this app registration needs to have the right API permission. Under “API permissions” select “Add permission” and then select “Microsoft Graph”. Since we’re building a background service with no user present, choose “Application permissions”, search for “Mail.Send” and select it:

Important: After adding a permission a admin needs to grant this permission for the entire organization:

After granting there should be a green checkmark on the permissions:

#2 Restrict access to a specific mailbox

With the newly created app permission our service would have the permission to send emails on behalf of every mailbox/user in our organization. This doesn’t sound like the perfect plan from a security perspective. So let’s see how we can further lock this down so the service can just send from one specific mailbox.

To restrict our app registration to only specific mailboxes we need to use application access policies and configure them with the Exchange Online Powershell module.

The first step is to install the PowerShell module:

After installation we can import the module to use it:

If you’re doing this on a Windows machine you may need to also set the execution policy:

Now we can connect to Exchange Online we a admin account:

Since a application access policy is applied on a mail enabled security group we first need to create one for our app:

With the group in place we can create application access policy that restricts the app registration’s access through the graph to members of that group. Therefore we again need the clientId that in this script is called appId:

Finally we need to add the mailbox we want to sent from as a member to the group:

Now we have successfully limited access for our app registration.

#3 Send an email through the Graph in .NET

An easy way to try this out is creating as new ASP.NET Core 6 app in Visual Studio. First we need to store our credentials somewhere for development. The recommended way is using user secrets, so let’s add them to secrets.json (Right-click on the project and choose “Manage User Secrets”):

  • To authenticate with AAD there is a SDK for dotnet: Azure.Identity
  • To use the Microsoft Graph from dotnet there is a SDK: Microsoft.Graph

Make sure to install both through NuGet.

Now on to the actual sending of mails through the graph. Let’s create a new service class to host the send mail functionality and add a send method:

To test this all let’s register our service and create an endpoint that sends a sample email:

If we start the app now and open it in the browser, it should send us a nice email right away.

Note: This sample is missing error handling so don’t use it straight away in your production code.

Note: You can also use a Managed Identity instead of the App Registration to authenticate the service. This is recommended wherever possible as it’s more secure (automatic key/secret rotation) and more resilient!

The full example is available here: https://github.com/GrillPhil/GraphEmailSample

Conclusion

With very little effort you can send emails through the Microsoft Graph using modern authentication with Azure AD while the available SDKs handle most of the logistics. Make sure to migrate your code away from SmtpClient and basic authentication to avoid broken features as soon as Microsoft disabled basic authentication in your tenant.

--

--

Philipp Bauknecht
medialesson

CEO @ medialesson. Microsoft Regional Director & MVP Windows Development. Father of identical twins. Passionate about great User Interfaces, NYC & Steaks