SendGrid on Heroku in 2021

In the end of 2020 SendGrid required customers to enable two-factor authentication, which means they stopped accepting SMTP requests made with username and password via Basic Authentication. This is better for security since providing account username and password for authenticating against the SendGrid SMTP API gives full access to your SendGrid account, and therefore it is a security risk if these credentials get compromised. Using API Keys adds an additional layer of security, and is the recommended way to securely talk to SendGrid APIs.

This means that by default the behaviour of the Twilio SendGrid addon may be somewhat unexpected. It still automatically adds a SENDGRID_USERNAME and SENDGRID_PASSWORD to your app's environment variables, but sending emails straight out of the box will no longer work.

There's a simple workaround. You will need to log into your Twilio SendGrid account and:

  1. Generate an API key under "Settings" > "API Keys". Give it a name, and select "Restricted Access". Restricted Access is recommended as it customises levels of access for all parts of your account.
  2. To send email only, your API key will require "Mail Send" > "Full Access permissions".
  3. To use your API key with the SMTP integration, set your username to be "apikey". Your password will be the API key you generated in the previous step.

In my Environment variables I use the following values:

SMTP_USERNAME: "apikey"
SMTP_PASSWORD: <Generated API Key starts with SG.>
SMTP_AUTHENTICATION: "plain"
SMTP_ADDRESS: smtp.sendgrid.net
SMTP_PORT: 587

Then in my Rails app, I have the following setup:

# config/smtp.rb
SMTP_SETTINGS = {
  address: ENV.fetch("SMTP_ADDRESS"),
  authentication: ENV.fetch("SMTP_AUTHENTICATION", "plain"),
  domain: ENV.fetch("SMTP_DOMAIN"),
  enable_starttls_auto: true,
  password: ENV.fetch("SMTP_PASSWORD"),
  port: ENV.fetch("SMTP_PORT", "587"),
  user_name: ENV.fetch("SMTP_USERNAME"),
}.freeze

# config/environments/production.rb
require Rails.root.join("config/smtp")

Rails.application.configure do
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = SMTP_SETTINGS
end

# app.json
{
  # ..
  "env": {
    "SMTP_ADDRESS": {
      "required": true
    },
    "SMTP_DOMAIN": {
      "required": true
    },
    "SMTP_PASSWORD": {
      "required": true
    },
    "SMTP_USERNAME": {
      "required": true
    }
  },
}

Working all this out required a number of conversations with both Twilio and Heroku support. Considering that this change is required for new and old SendGrid clients, I would expected Heroku support to be on top of this, and that the documentation would be more upfront. In any case, here are a few more references:

Posted on February 17, 2021 by Elle Meredith

Interested in reading more?

Introducing new services

We have been working on a few new offerings, which we would like to introduce today. Mainly, we have been working on technical leadership coaching, culture and technical workshops, an Associate Developer onboarding program, and codebase reviews.

Receive our monthly newsletter

Talk to us, we're listening

Would you like to improve team effectiveness and productivity? Got a project you think we can help with? Interested in leadership coaching or engineering training? Basically, want to work with us? Get in touch: gday@blackmill.co and we will be in touch in a jiffy.

We live on, and benefit from, the colonised lands of the Arakwal and the Minjungbal peoples of the Bundjalung nation, and those of the Wurundjeri people of the Kulin nation. We acknowledge the Traditional Owners of these lands and recognise their enduring connection to land, waters, and culture. We pay our respects to their elders, past and present.