The Most Advanced Guide on Sending Emails From Azure

Let’s say you’ve picked Microsoft Azure as a cloud-computing platform for your environment. You may need it for hosting your app, or whatever. At some point, you will need to implement email sending, and this might be troublesome. You can’t send emails directly from any service in Azure. Why? You’ll find the answer below, as well as the details about how to send emails from Azure.

Azure SMTP restrictions

Since November, 15, 2017, Microsoft has banned outbound SMTP communication from Azure computing resources in trial subscriptions.

The restriction applies to unauthenticated email delivery (without SPF, DKIM and DMARC records) via SMTP port 25 through direct DNS MX lookups. The idea is to protect Azure data center IP addresses from reputation abuse. A free account offers $200 credits for 30 days. You can use those to experiment with any service within the Azure platform. With that in mind, users take advantage of this offer for hosting and testing their apps or servers. Isn’t that for what a trial subscription is meant? In practice, those apps/servers send emails without proper sender authentication records. As a result, the reputation of Azure data center public IP addresses drops and they get blacklisted.

The Azure SMTP restriction does not affect enterprise users. Pay-As-You-Go subscribers can unblock the restriction. They need to send a respective support request, which has to be approved by Microsoft.

If you’re a trial subscriber, hold off on switching to AWS or another Azure alternative. You can send emails from Azure but via an SMTP relay service.

What do I need to send emails from Azure?

To send emails from Azure VMs or Apps, use an authenticated SMTP relay service, also known as a Smart Host, with TLS support.

This is an official recommendation by Microsoft for Azure customers. SMTP relay services provide an intermediary SMTP server between the mail servers of the sender and recipient. The TCP connection is established via the secure ports 587 or 443. However, other SMTP ports may be supported as well.

SendGrid is the most common SMTP relay service to integrate with Microsoft Azure. It allows you to use SendGrid SMTP API (not to be confused with Web or HTTP API) for sending emails. This SMTP relay service is a front-line player in this blog post. We’ll also take a look at such options as Mailjet and Office 365. However, you’re free to pick any authenticated smart host on the market like Elastic Email, SocketLabs, and so on. You can use any of these services without any restriction regardless of your Azure subscription.

Send emails with SendGrid

SendGrid is a recommended method for sending emails from the Azure function, web job, or any app. SendGrid offers 25K of free emails per month and all sorts of APIs including SMTP, Web, Event, and others. To start using the SMTP relay, you need to create an account and get your SendGrid SMTP credentials. With SMTP API, you’ll need to make a few more manipulations. So, let’s start with the basics.

SendGrid integration into your Azure environment

  • Sign in to Azure Portal and click Create a resource.
  • Find SendGrid in the search field and select. After that, click Create.

You’ll need to:

  • fill out a few fields: Name, Password, and Confirm Password. These parameters will be used to create a new SendGrid account.
  • select a Subscription
  • create a new Resource group or use an existing one
  • select a Pricing tier
  • provide contact information
  • and accept the Terms of Use

Click Create once you’re ready.

send-emails-azure-3.png

  • In the end, you’ll see a Deployment Succeeded pop-up, and your account will be listed in SendGrid Accounts.
  • Enter your brand-new account and click the Manage button. This is required to initiate the email verification process. SendGrid will send you a confirmation email to your address.
  • If you’d like to opt for SendGrid SMTP API, you need to generate an API Key. Click Manage=> Settings=> API Keys.
  • After you click Create API Key, provide a name for the key, and select a permission. Click Create & View once ready.
  • When you see your API Key, copy it and save. Keep in mind that you won’t be able to see it again.

Sending emails from Azure via SendGrid

Now, you have a functioning SMTP relay service, so you can send emails from Azure. And there are a few ways to do this.

Using PowerShell via SMTP

Use your SendGrid SMTP server credentials to send emails via PowerShell. Here is a script for a simple text email:

$From = "<user@sender.com>"
$To = "<user@recipient.com>"
$SMTPServer = "smtp.sendgrid.net"
$SMTPPort = "587"
$Username = "<your-SendGrid-username>"
$Password = "<your-SendGrid-password>"
$subject = "Test Email"
$body = "Test email using SendGrid Email Delivery"
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort)
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)
$smtp.Send($From, $To, $subject, $body

Using .NET’s Built-in SMTP Library

Here is the code sample for building a MIME email and sending it through SendGrid:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Net.Mime;

namespace SmtpMail
{
  class Program
  {
    static void Main()
    {
      try
      {
        MailMessage mailMsg = new MailMessage();

        mailMsg.To.Add(new MailAddress("user@recipient.com", "The Recipient"));

        mailMsg.From = new MailAddress("user@sender.com", "The Sender");

        mailMsg.Subject = "Test Email";
        string text = "Test Email with SendGrid using .NET's Built-in SMTP Library";
        string html = @"<strong>HTML text for the Test Email</strong>";
        mailMsg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Plain));
        mailMsg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));

        SmtpClient smtpClient = new SmtpClient("smtp.sendgrid.net", Convert.ToInt32(587));
        System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("<SendGrid-username>", "<SendGrid-password>");
        smtpClient.Credentials = credentials;

        smtpClient.Send(mailMsg);
      }
        catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }

    }
  }
}

Using the SendGrid C# Library via SMTP API

Install the SendGrid NuGet package in your app. It is a C# client library that will let you use SendGrid APIs to send emails. You can install it right from Visual Studio via Tools => NuGet Package Manager => Manage NuGet Packages for Solution. Browse for SendGrid and install the latest stable version.

send-emails-azure-10.png

Now, check out the following code sample for sending a simple email:


using SendGrid;
using SendGrid.Helpers.Mail;
using System;
using System.Threading.Tasks;

namespace Example
{
    internal class Example
    {
        private static void Main()
        {
            Execute().Wait();
        }

        static async Task Execute()
        {
            var apiKey = Environment.GetEnvironmentVariable("******"); //insert your Sendgrid API Key
            var client = new SendGridClient(apiKey);
            var from = new EmailAddress("user@sender.com", "The Sender");
            var subject = "Test Email with SendGrid";
            var to = new EmailAddress("user@recipient.com", "The Recipient");
            var plainTextContent = "Test Email with SendGrid C# Library";
            var htmlContent = "<strong>HTML text for the Test Email</strong>";
            var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
            var response = await client.SendEmailAsync(msg);
        }
    }
}

Using MailHelper class from ASP .NET Core API

You can also send emails from ASP .NET Core. For this, use the MailHelper class of SendGrid.Helpers.Mail namespace. The API key needs to be stored in the appsettings.json file (you can tweak it from the Azure Portal as well). Here is how it should look:

{
   "Logging": {
   "IncludeScopes": false,
   "LogLevel": {
   "Default": "Debug",
   "System": "Information",
   "Microsoft": "Information"
     }
   },
 "SENDGRID_API_KEY": "*********"
}

To access the API Key from appsettings.json, create the Startup.cs file. Inject the IConfiguration interface at the constructor of the controller after adding it in the ConfigureServices method below:

public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSingleton<IConfiguration>(Configuration);
    }

And here is the sample code for the controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using SendGrid;
using SendGrid.Helpers.Mail;
using Microsoft.Extensions.Configuration;

namespace SendgridMailApp.Controllers
{
    [Route("api/[controller]")]
    public class NotificationController : Controller
    {
       private readonly IConfiguration _configuration;

       public NotificationController(IConfiguration configuration)
       {
         _configuration = configuration;
       }

       [Route("SendNotification")]
       public async Task PostMessage()
       {
          var apiKey = _configuration.GetSection("SENDGRID_API_KEY").Value;
          var client = new SendGridClient(apiKey);
          var from = new EmailAddress("user@sender.com", "The Sender");
          List<EmailAddress> tos = new List<EmailAddress>
          {
              new EmailAddress("user1@recipient.com", "The Recipient 1"),
              new EmailAddress("user2@recipient.com", "The Recipient 2"),
              new EmailAddress("user3@recipient.com", "The Recipient 3")
          };

          var subject = "Test Email with SendGrid";
          var htmlContent = "<strong>HTML text for the Test Email</strong>";
          var displayRecipients = false; // set this to true if you want recipients to see each others mail id
          var msg = MailHelper.CreateSingleEmailToMultipleRecipients(from, tos, subject, "", htmlContent, false);
          await client.SendEmailAsync(msg);
      }
   }
}

If you want to add an attachment to your email, call the AddAttachment method and specify the file name and Base64 encoded content. For example:

var attachment = new Attachment()
{
    Content = Convert.ToBase64String(raw_content),
    Type = "image/png",
    Filename = "attachment.png",
    Disposition = "inline",
    ContentId = "attachment"
};
msg.AddAttachment(attachment);

Sending emails from Azure Automation runbook via SendGrid

This requires two steps:

  • Create an Azure KeyVault and store the SendGrid API key in it
  • Create a runbook that retrieves the API key and sends an email

Creating an Azure KeyVault

Use the following script to create an Azure KeyVault. Insert your variables and run the code in Azure PowerShell. You can also run the code locally if you have the Azure PowerShell Module installed.

$SubscriptionId  =  "<subscription ID>"

# Sign in to your Azure account and select your subscription
# If you omit the SubscriptionId parameter, the default subscription is selected.
Connect-AzAccount -SubscriptionId $SubscriptionId

# Use Get-AzLocation to see your available locations.
$region = "southcentralus"
$KeyVaultResourceGroupName  = "mykeyvaultgroup"
$VaultName = "<Enter a universally unique vault name>"
$SendGridAPIKey = "<SendGrid API key>"
$AutomationAccountName = "testaa"

# Create new Resource Group, or omit this step if you already have a resource group.
New-AzResourceGroup -Name $KeyVaultResourceGroupName -Location $region

# Create the new key vault
$newKeyVault = New-AzKeyVault -VaultName $VaultName -ResourceGroupName $KeyVaultResourceGroupName -Location $region
$resourceId = $newKeyVault.ResourceId

# Convert the SendGrid API key into a SecureString
$Secret = ConvertTo-SecureString -String $SendGridAPIKey -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName $VaultName -Name 'SendGridAPIKey' -SecretValue $Secret

# Grant access to the KeyVault to the Automation RunAs account.
$connection = Get-AzAutomationConnection -ResourceGroupName $KeyVaultResourceGroupName -AutomationAccountName $AutomationAccountName -Name AzureRunAsConnection
$appID = $connection.FieldDefinitionValues.ApplicationId
Set-AzKeyVaultAccessPolicy -VaultName $VaultName -ServicePrincipalName $appID -PermissionsToSecrets Set, Get

There are other ways to create an Azure KeyVault. Here is one using Portal.

Click Create a Resource and browse “Key Vault”. Click Create.

send-emails-azure-11.png

Fill out the required fields and click Review + Create.

send-emails-azure-12.png

To use Azure KeyVault within a runbook, you need to import Az.Profile and Az.KeyVault modules to your Automation Account. You can do this via PowerShell:

Install-Module -Name Az.Profile
Install-Module -Name Az.KeyVault -RequiredVersion 1.3.1

Or deploy these packages directly to Azure Automation.

Create a runbook to send an email

Do the following:

  • Select Runbooks under Process Automation in your Azure Automation account.
  • Select + Create a runbook.
  • Enter Send-GridMailMessage for the runbook name. Select PowerShell for the runbook type and click Create Runbook.
  • Copy the following PowerShell example in the opened Edit PowerShell Runbook page.
Param(
  [Parameter(Mandatory=$True)]
  [String] $destEmailAddress,
  [Parameter(Mandatory=$True)]
  [String] $fromEmailAddress,
  [Parameter(Mandatory=$True)]
  [String] $subject,
  [Parameter(Mandatory=$True)]
  [String] $content
)

$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Connect-AzAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint | Out-Null
$VaultName = "<Enter your vault name>"
$SENDGRID_API_KEY = (Get-AzKeyVaultSecret -VaultName $VaultName -Name "SendGridAPIKey").SecretValueText
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer " + $SENDGRID_API_KEY)
$headers.Add("Content-Type", "application/json")

$body = @{
personalizations = @(
    @{
        to = @(
                @{
                    email = $destEmailAddress
                }
        )
    }
)
from = @{
    email = $fromEmailAddress
}
subject = $subject
content = @(
    @{
        type = "text/plain"
        value = $content
    }
)
}

$bodyJson = $body | ConvertTo-Json -Depth 4

$response = Invoke-RestMethod -Uri https://api.sendgrid.com/v3/mail/send -Method Post -Headers $headers -Body $bodyJson

Here we go! I hope our Azure ASP.NET send email guide was helpful for you! It was initially writed for the Mailtrap blog by Dmitriy Shcherbakan. Head there to learn more about sending emails with Mailjet, sending email from Azure using Office 365 and sending emails with Gmail.