Get Started with DMARC and SendGrid

December 03, 2024
Written by
Alvin Lee
Contributor
Opinions expressed by Twilio contributors are their own

If you're communicating with customers by email– for transactional communications, marketing campaigns, or customer service follow-ups – then you know that deliverability is incredibly important. Deliverability is closely tied to your sender reputation. When your emails don’t reach customers because they’ve been flagged as spam or rejected as possibly fraudulent, it presents a challenge.

Email spoofing is used by attackers who try to disguise their emails as originating from a different address or domain. Imagine an attacker spoofing an address from your business’s domain to pitch a cryptocurrency scheme or discount pharmaceuticals. Your business reputation suffers, and your sender reputation will likely suffer too.

Enter Domain-based Message Authentication, Reporting, and Conformance , or DMARC. DMARC is a protocol that mail servers use to verify the authenticity of incoming email before they route it to the intended recipient’s inbox.

In this post, we’ll walk through how to get up and running with DMARC using SendGrid. We’ll provide suggestions and ways to implement them. As you follow along, you’ll learn how to protect your own domain from spoofing attempts while improving your sender reputation and email deliverability.

How DMARC Works

After this section, I’ll show you SendGrid can support your DMARC policy. But if you’d like some background on how DMARC works first, here’s a quick overview:

  • The DMARC protocol also relies on Sender Policy Framework (SPF) and DomainKeys Identified Mail (DKIM).
  • SPF is a domain owner’s specification of which SMTP servers are verified senders of email from that domain. The domain owner specifies this in a special TXT record among the domain’s DNS records. Receiving mail servers check incoming email (and the server that sent it) against the SPF record to make sure the mail is actually coming from who it says it comes from.
  • DKIM adds a digital signature to outgoing emails, which is then validated against a public key, which is published as CNAME records for the domain. Receiving mail servers use DKIM to verify that the contents of emails have not been tampered with.
  • DMARC specifies what a receiving mail server should do in the case of SPF or DKIM failing authentication. That action (or policy) can be to take no action, quarantine the email by sending it to spam, or reject the email altogether. Just like SPF and DKIM, DMARC is specified through a DNS record.

In this post, we’ll start with a policy of no action, then test quarantining or rejecting email. In general, SendGrid suggests you start with p=none as a policy, but move to p=quarantine or p=reject over time.

And you’ll want to move, eventually. Brand Indicators for Message Identification (oft-shortened to BIMI ), adds a verified brand logo next to the email in the recipient’s inbox. BIMI also requires a policy of p=quarantine or p=reject.

For a more detailed breakdown of what DMARC is and how it works, check out “ What is DMARC?

Prerequisites

Before you begin the tutorial, you’ll need a few things:

And with that, we can begin the tutorial.

Initial Setup

In this demo, we are owners of a domain, codingplus.coffee. We want to use the SendGrid SMTP server to send emails from this domain, but we also want to implement DMARC to protect our domain from email spoofing attempts.

Step 1: Add a SPF record

As mentioned above, the SPF record for your domain specifies the list of permitted mail servers from which your emails will come. When incoming servers receive an email, they can check the SPF record for the domain to verify that the email came from a permitted mail server.

Implement SPF by adding a TXT record to the DNS records (instructions vary by DNS provider, see here for more) for your domain. For our demo, since our emails are only allowed to be sent by sendgrid.net, our TXT record looks like this:

HostData
@ v=spf1 include:sendgrid.net -all

We navigate to the DNS settings for our domain provider, and we add this record.

You can use the MX Toolbox SuperTool to verify that your DNS record has been set up correctly. Here’s an example of how we use the tool to check our domain’s SPF information:

SPF record lookup result showing 'Pass' results for 'sendgrid.net' and other checks for codingplus.coffee.

Step 2: Authenticate domain and add DKIM records

To send emails through SendGrid’s SMTP server, we need to authenticate our codingplus.coffee domain. Authenticating our domain with SendGrid also improves our deliverability.

First, we sign into SendGrid. Then, we navigate to Settings > Sender Authentication.

A settings menu featuring options such as Account Details, Alert Settings, API Keys, and more.

We click Authenticate Your Domain.

Message recommending domain authentication to improve email deliverability with a button to authenticate.

We need to select our DNS host, or specify it if it’s not in the list. Then, we click Next.

Screenshot of a domain authentication setup screen with DNS host and branding link options.

Next, we provide the domain from which we’ll send emails. Click Next.

Form to authenticate domain for email sender with options for automated security, custom return path, and DKIM selector.

SendGrid provides us with several DNS records we need to add to our domain.

Screenshot showing DNS records for CNAME and TXT types related to codingplus.coffee.
  • The first CNAME record in the list associates our domain with our SendGrid account, and SendGrid uses it to help track email engagement (clicks and opens) for our account.
  • The next two CNAME records (with _domainkey in the HOST) are DKIM records.
  • The final TXT record is related to DMARC.

When authenticating your domain with SendGrid, you’re only required to add the three CNAME records. For now, we’ll set aside the TXT record for DMARC, since we’ll look at it in more detail below.

For some providers, when adding a CNAME or TXT record, you should leave off the domain name that is at the end of the HOST value. For example, if you need a CNAME record with HOST em5668.codingplus.coffee, you might just use em5668 as the HOST.

Below, you can see how we use MX Toolbox to verify the CNAME record for associating our SendGrid account:

Screenshot of SuperTool showing DNS CNAME lookup for em5668.codingplus.coffee with results.

After adding our three CNAME records, we check the box in SendGrid and click Verify.

Extract screen with a checkbox marked I've added these records and a blue Verify button below.

Our DNS records are properly updated, which completes the domain authentication process.

Success message verifying authenticated domain for codingplus.coffee
Screenshot showing the status of domain authentication with a verified domain.

You can read this page for more detailed information on domain authentication with SendGrid.

Step 3: Verify a sender

Next, we want to verify that we own the email address from which we’ll send our emails. Eventually, to test our DMARC settings, we’ll try to send spoofed emails with this email address. Back on the Sender Authentication page, we click Verify a Single Sender.

Button to verify ownership of a single email address with instructions

We complete the form with contact information for the email address that we want to verify. Then, we click Create.

Email Sender Information Form

After completing this step, SendGrid will run its verification process and add the email address to the list of verified senders.

Single Sender Verification status for the domain sender@codingplus.coffee

Step 4: Configure DMARC

With everything set up in SendGrid, let’s see how different DMARC settings affect our deliverability.

Most permissive, least secure policy: p=none

The data value for the DMARC TXT record must always begin with v=DMARC1. For our first go-around, we’ll set p=none, which means “take no action, even if DKIM or SPF fails.” Our TXT record will look like this:

HostData
_dmarc.codingplus.coffee v=DMARC1; p=none;

We add this record to our DNS settings. Checking our DMARC settings with MX Toolbox, we see this:

SuperTool Beta9 displaying DMARC lookup results for codingplus.coffee with a list of tests and results.

To test this, we send an email from sender@codingplus.coffee, but we use a different SMTP server. Since we are using the most permissive DMARC policy, our test recipient receives the email. When we inspect the raw headers for the email, we see some interesting things:

Authentication-Results: phl-mx-03.messagingengine.com;
    dkim=pass (2048-bit rsa key sha256)
      header.d=codingplus-coffee.20230601.gappssmtp.com
      header.i=@codingplus-coffee.20230601.gappssmtp.com header.b=KU+3RoAb
      header.a=rsa-sha256 header.s=20230601;
    dmarc=fail policy.published-domain-policy=none
      policy.applied-disposition=none policy.evaluated-disposition=none
      policy.arc-aware-result=fail
      (p=none,d=none,d.eval=none,arc_aware_result=fail) policy.policy-from=p
      header.from=codingplus.coffee;
    iprev=pass smtp.remote-ip=209.85.167.54 (mail-lf1-f54.google.com);
    spf=fail smtp.mailfrom=sender@codingplus.coffee
      smtp.helo=mail-lf1-f54.google.com

Our receiving email server performed authentication checks on the inbound email. We see dkim=pass, which means the outgoing server properly signed the email; the content hasn’t been tampered with. However, we see spf=fail because we are sending email from an SMTP server that is not in the list of permitted servers (which only includes sendgrid.net) in our SPF record.

Because SPF failed, we have dmarc=fail. However, the email was still delivered because our policy was to take no action on failures.

Add reporting emails

Let’s modify our settings to see DMARC reporting emails when failures occur. There are three segments we can add to our DMARC TXT record:

  • rua=mailto:recipient@example.com sets the email address that should receive aggregate reports of DMARC failures.
  • ruf=mailto:recipient@example.com sets the email address that should receive a forensic report on every DMARC failure.
  • Optional: ri=<integer> is the report interval (in seconds) for aggregate emails. When not specified, the report interval defaults to 86400, which is the equivalent of daily reporting. For example, adjusting this value to 259200 would result in aggregate reporting every 72 hours.

We’ve adjusted our TXT record to look like this:

HostData
_dmarc.codingplus.coffee v=DMARC1; p=none; rua=mailto:dmarc-reports@codingplus.coffee; ruf=mailto:dmarc-reports@codingplus.coffee;
DMARC record with policy none and reporting addresses to codingplus.coffee

If you plan to send DMARC report emails to an address for a different domain, you will need to set up external domain verification (EDV) for that domain, effectively permitting the sending of reports to that domain. This is done by adding a TXT record to that external domain’s DNS records.

Let’s assume we wanted to send DMARC reports from codingplus.coffee to dmarcfailures@myotherdomain.com. We would need to add the following TXT record to myotherdomain.com:

codingplus.coffee._report._dmarc.myotherdomain.com - v=DMARC1

We send another test email using our non-SendGrid SMTP server. Our policy (p=none) has not changed, so we still expect the email to be delivered despite the SPF failure. However, we would expect to receive a DMARC forensic report on the DMARC failure.

Many email service providers (including Gmail and Microsoft 365do not implement DMARC forensic reporting. However, aggregate reports are commonly supported across providers.

Aggregate reports are delivered as XML files archived to a ZIP file. An example report looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <email>noreply-dmarc-support@google.com</email>
    <extra_contact_info>https://support.google.com/a/answer/2466580</extra_contact_info>
    <report_id>15261463159764956713</report_id>
    <date_range>
      <begin>1724544000</begin>
      <end>1724630399</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>codingplus.coffee</domain>
    <adkim>r</adkim>
    <aspf>r</aspf>
    <p>quarantine</p>
    <sp>quarantine</sp>
    <pct>50</pct>
    <np>quarantine</np>
  </policy_published>
  <record>
    <row>
      <source_ip>209.85.220.41</source_ip>
      <count>1</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>fail</dkim>
        <spf>fail</spf>
        <reason>
          <type>sampled_out</type>
          <comment />
        </reason>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>codingplus.coffee</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>codingplus-coffee.20230601.gappssmtp.com</domain>
        <result>pass</result>
        <selector>20230601</selector>
      </dkim>
      <spf>
        <domain>codingplus.coffee</domain>
        <result>fail</result>
      </spf>
    </auth_results>
  </record>
  <record>
    <row>
      <source_ip>209.85.220.41</source_ip>
      <count>1</count>
      <policy_evaluated>
        <disposition>quarantine</disposition>
        <dkim>fail</dkim>
        <spf>fail</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>codingplus.coffee</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>codingplus-coffee.20230601.gappssmtp.com</domain>
        <result>pass</result>
        <selector>20230601</selector>
      </dkim>
      <spf>
        <domain>codingplus.coffee</domain>
        <result>fail</result>
      </spf>
    </auth_results>
  </record>
</feedback>

Quarantine on failures

Next, we’ll adjust our DMARC policy to quarantine emails that fail. To do this, we change p=none to p=quarantine. When using a policy other than p=none, it’s recommended to include the pct segment. This specifies what percentage of DMARC-failing emails should have the policy (in this case, quarantining) applied. When not specified, pct defaults to 100.

Let’s adjust our TXT record value. The data value now looks like this:

 

v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc-reports@codingplus.coffee; ruf=mailto:dmarc-reports@codingplus.coffee;

DMARC record updates may take up to 72 hours to propagate.

After setting the DMARC policy to quarantine, we send another test email. This time, because of the SPF failure, the incoming email server automatically routes the incoming email to the spam folder. A closer inspection of the raw email headers shows the following:

Authentication-Results: phl-mx-04.messagingengine.com;
    dkim=pass (2048-bit rsa key sha256)
      header.d=codingplus-coffee.20230601.gappssmtp.com
      header.i=@codingplus-coffee.20230601.gappssmtp.com header.b=X11d+q/J
      header.a=rsa-sha256 header.s=20230601;
    dmarc=fail policy.published-domain-policy=quarantine
      policy.applied-disposition=quarantine
      policy.evaluated-disposition=quarantine policy.arc-aware-result=fail
      (p=quarantine,d=quarantine,d.eval=quarantine,arc_aware_result=fail)
      policy.policy-from=p header.from=codingplus.coffee;
    iprev=pass smtp.remote-ip=209.85.218.50 (mail-ej1-f50.google.com);
    spf=fail smtp.mailfrom=sender@codingplus.coffee
      smtp.helo=mail-ej1-f50.google.com

Notice that the quarantine policy was applied.

What happens if we adjust pct to 50? We would expect that roughly half of the DMARC-failing emails would be quarantined. After adjusting our DMARC record, we sent two test emails. One of the emails went to the spam folder, while the other one was delivered to the inbox.

Reject on failures

Finally, let’s set the DMARC failure policy to p=reject. We’ll also set pct=100. Our updated TXT record looks like this:

v=DMARC1; p=rject; pct=100; rua=mailto:dmarc-reports@codingplus.coffee; ruf=mailto:dmarc-reports@codingplus.coffee;

Again, we try sending a test email via our non-SendGrid SMTP server. Our intended recipient never receives the email. Instead, the sender receives this bounce message:

Screenshot of a blocked email notification due to failed DMARC policy verification.

Our spoof email was rejected and blocked! It looks like our p=reject policy is in effect.

DMARC Monitoring

However you set your DMARC policy, monitoring those email reports is important—from today until you stop sending emails from your domain. That means checking those forensic reports for surprises: Are other members of your organization sending mail? Are bad actors trying to spoof your domain? Are valid emails failing SPF, DKIM, or DMARC checks?

Once you get the hang of DMARC on your domain, moving your policy from p=none to p=quarantine or p=reject is a worthy upgrade – and a mandatory prerequisite before you can add BIMI. But parsing through XML files to figure out everything going on with email sends from your domain can get old.

One way to streamline your DMARC monitoring is with a DMARC service that helps you implement, manage, enforce, and monitor your DMARC policies. SendGrid is partnered with Valimail for DMARC monitoring – their DMARC Monitor tool is free for Twilio SendGrid customers.

Dashboard displaying DMARC authentication status categorized into passing, partially passing, and failing.

You can learn more about DMARC monitoring in this post.

Conclusion

Protecting your domain’s sender reputation is essential to email deliverability. Implementing DMARC (alongside SPF and DKIM) improves your sender reputation, and it helps protect your domain from attackers who might try to spoof emails to look like they’re coming from your business. 

As we’ve seen, implementing DMARC is straightforward. You might start with a p=none policy to slowly get accustomed to DMARC and understand how reporting works. With time and careful monitoring, you can tighten things up by transitioning to p=quarantine or even p=reject, perhaps with a gradually increasing value for pct. And as I’ve mentioned, there’s a bonus waiting for you – to add BIMI and a verified brand logo next to email in your recipients’ inboxes, you will need a policy to quarantine or reject emails that fail validation.

But before tightening your policy too quickly, you need  to allow for the possibility of legitimate emails from your domain that don’t pass DKIM or SPF. For example, if a sender used a different SMTP server but you haven’t updated SPF to include that server. Eventually, you’ll arrive at a policy and an enforcement percentage that matches your business’s unique needs and quirks.

 

SendGrid helps organizations streamline their outgoing email campaigns. Send with confidence and simplicity. 

Sign up to start using SendGrid for free today, and get in touch with our team of experts.