Message Transfer Agent – Strict Transport Security (MTA-STS) is an email security protocol to make incoming messages safer by requiring encryption for mail sent to a domain. It is typically used to ensure that incoming mail is encrypted via TLS 1.2 or higher. However, as we will demonstrate throughout this article, MTA-STS can be used for much more. It’s easily implemented via a policy file, which you can deploy by uploading it to your domain at /.well-known/mta-sts.txt. We’ll introduce the syntax of this command to you shortly.

In addition to the aforementioned security benefits, MTA-STS can also be combined with TLS Reporting (TLSRPT), allowing you to receive reports of any incoming mail that was rejected for violating your MTA-STS policy. This is crucial for debugging a policy. We’ll also cover setting up TLS Reporting in this article.

Before we dive in, let’s begin with a brief overview of the key terms and syntactic elements relevant to MTA-STS. The following table will serve as a reference you can refer to throughout the article.

versionWhich version of the MTA-STS specification is being used.
modeSpecifies whether an MTA-STS policy should be enforced, ignored, or only generate violation reports.
mxSpecifies which mail servers are authorized to handle mail for your domain.
max_ageThe maximum lifetime of the MTA-STS policy, in seconds.
TLSRPTA protocol for reporting messages that fail MTA-STS policy.

Creating an MTA-STS policy 

The following assumes that you have access to both inbound mail servers and web servers that support connections encrypted using TLS/SSL (the latter because the policy file is retrieved by HTTPS). The steps to make that happen are outside the scope of this post.


Let’s examine a real MTA-STS policy. After making it, we can go through the parts and examine why the policy writers did things a certain way as well as what configurations you may want to change depending on your needs. 

Writing the Policy File

With the prerequisite DNS and file system obstacles overcome, we can finally begin focusing on the content of the policy file itself. A policy consists of four kinds of directives: version, mode, mx, and max_age. Let’s go through them one by one so you can more easily figure out what values would work for your setup.

version

This one’s easy: STSv1 is the only version of the MTA-STS protocol in existence, so you’ll have to use that.

mode

What should happen to mail that fails to comply with your MTA-STS policy? If we set this to enforce, then sending servers that support MTA-STS will fail to deliver mail to your domain if your MX hosts don’t match those in your policy file, or the MX hosts fail certificate validation, or they do not support STARTTLS. Additionally, if the sending server supports sending reports, a TLS Report will be sent if you have TLSRPT set up (we’ll cover that soon). If set to testing, then mail will still be delivered even if encryption fails, but a TLSRPT will still be sent if possible, and if set to none, the sending server will act as though no policy were in place.

mx

For each MX host associated with your domain, you must have a separate mx directive pointing to that MX host. It’s paramount that each MX server has a valid TLS certificate for the sender to encrypt the content with. 

max_age

The max_age directive defines how long servers should cache your policy before checking for a new one.  Google will only process policies with a max_age higher than 86400 seconds (equal to one day). Because of this, 86400 is the most popular value, and it’s what we recommend as well.

Setting up DNS

For this example, we will use Google, along with Unix command-line tools instead of screenshots, because their results are easier to reproduce, independently verify, and adapt to your needs.

$ curl https://mta-sts.google.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: smtp.google.com
mx: aspmx.l.google.com
mx: *.aspmx.l.google.com
max_age: 86400

First, we see that the policy file is accessed via the mta-sts.google.com subdomain. Second, we see that the policy file itself is hosted at the path /.well-known/mta-sts.txt. Neither of these facts is arbitrary—rather, that subdomain and path are the required locations for an MTA-STS policy file. Therefore, to create your own policy, you will need to create this file at that same location on your own domain. 

One final point before we begin picking apart the actual contents of the policy file: To officially enable MTA-STS and thus communicate to SMTP servers that incoming mail should comply with the policy, you must add a special DNS record at the subdomain _mts-sta (note the leading underscore). Let’s see what this looks like in practice, using Google as a model once again:

$ dig -t txt +noall +answer _mta-sts.google.com
_mta-sts.google.com.  213  IN  TXT  "v=STSv1;id=20210803T010101;"

It’s mandatory for there to be a TXT record, which is the kind of record we see above. The v=STSv1 part means we are using version one of the MTA-STS protocol, which to date is the only version. The ID is an arbitrary combination of 1-32 alphanumeric characters. You can set it to whatever you want within that limit. If you ever change your policy, you can change this ID string to let other servers know that your policy has been updated. So how do you decide what to set it to? Google’s Workspace Admin Support offers some solid advice:

Update the id to a new, unique value every time you change your MTA-STS policy. […] We recommend using the current date and time for the id value so you know when your policy last changed.

Source: https://support.google.com/a/answer/9276512, “Add DNS TXT records“

This tactic is similar to that of creating the serial number in the SOA record for a zone, as experienced DNS administrators may recognize.


Armed with an understanding of the directives that make up an MTA-STS Policy, you can leverage your new knowledge to combine these elements into a real policy file. Let’s say you want to deploy an enforced policy with a max_age of 86400 seconds and your domain has three MX servers: mx1.domain.com, mx2.domain.com, and mx3.domain.com. The policy file would look like this:

version: STSv1
mode: enforce
mx: mx1.domain.com
mx: mx2.domain.com
mx: mx3.domain.com
max_age: 86400

That’s it! Not so intimidating, once you understand the various parts. 

Adding Reporting with TLSRPT

Because MTA-STS leads to the rejection of certain noncompliant mail, there’s a possibility that a misconfigured policy could lead to legitimate mail not being properly delivered. To mitigate this risk and aid in debugging mail problems caused by MTA-STS, admins have the option of setting up reporting that lets SMTP servers send a report on successful and rejected TLS connections to a predetermined email address, where these reports can be consumed and monitored for signs of issues.

To enable such reports, we apply a standard known as SMTP TLS Reporting (commonly abbreviated as TLSRPT). Implementing TLSRPT is as simple as adding another TXT record to your DNS zone file, this time to the _smtp._tls subdomain. To demonstrate, we will again use Google as our exemplar:

$ dig -t txt +short _smtp._tls.google.com
"v=TLSRPTv1;rua=mailto:sts-reports@google.com"

Just like with the MTA-STS TXT record, we start with a version number. As before, only one version has been promulgated, so v=TLSRPTv1 is the only value you’ll find this set to (but it’s still important to set it this way to clarify what version you’re using, in case a new version with incompatible features comes out in the future). The second part, rua (Aggregate Reporting URI), dictates how you can be contacted with aggregate reports of TLS connection successes (or failures!).

Reports can be delivered by one of two methods – SMTP or HTTP POST – and the rua tag in your MTA-STS record will include the appropriate URI to reflect your preference – e.g., rua=mailto:reports@example.com or rua=https://reporting.example.com/v1/tlsrpt

Note that reports send to this address must be DKIM-signed, per RFC 8460 Section 3.

What a report looks like

Now that you know how to set up reporting, let’s get a closer look at what these reports actually consist of. The sending server will usually provide a daily, aggregate report containing data about messages they’ve sent you in the form of a GZIP compressed JSON file. The file itself will contain data formatted similarly to the following:

{
     "organization-name": "Some other company",
     "date-range": {
       "start-datetime": "2022-01-01T00:00:00Z",
       "end-datetime": "2022-01-22T23:59:59Z"
     },
     "contact-info": "sts-reporting@some_other_company.test",
     "report-id": "5034327c-44d3-47da-b6a0-946ea4e8c4be",
     "policies": [{
       "policy": {
         "policy-type": "sts",
         "policy-string": ["version: STSv1","mode: testing",
               "mx: *.mail.yourdomain.example","max_age: 86400"],
         "policy-domain": "yourdomain.example",
         "mx-host": "*.mail.yourdomain.example"
       },
       "summary": {
         "total-successful-session-count": 2323,
         "total-failure-session-count": 203
       },
       "failure-details": [{
         "result-type": "certificate-expired",
         "sending-mta-ip": "2001:db8:abdd:0015::5",
         "receiving-mx-hostname": "mx1.mail.yourdomain.example",
         "failed-session-count": 34
       }, {
         "result-type": "starttls-not-supported",
         "sending-mta-ip": "2001:db8:abcd:0013::1",
         "receiving-mx-hostname": "mx2.mail.yourdomain.example",
         "receiving-ip": "203.0.113.57",
         "failed-session-count": 200,
         "additional-information": "https://reports.yourdomain.example/
           report_info ? id = 5065427 c - 23 d3# StarttlsNotSupported "
       }]
     }]
}

The core of the summary resides in the policies section, where we see a breakdown of the MTA-STS policy as the reporting server interprets it, a summary of basic statistics on delivered emails and failures, and finally an array of specific failures with statistics and details.

The precise schema for this JSON file is defined in RFC 8460 Section 4.4, although the report itself does a decent job of explaining itself. When unsure, look at two fields, “result-type” and “additional-information”, as these fields serve to explain the nature of a failure. Detailed explanations of the meaning of different values that can appear in the Result Types can be found in RFC 8460 Section 4.3.


That’s all there is to it! However, sometimes a theoretical understanding isn’t sufficient. Let’s take it to the next level by implementing a real MTA-STS policy on a live domain, with reporting. 

MTA-STS with Google Workspace

 

Workspace makes creating an MTA-STS policy trivially easy. First, browse to your Google Admin console. Then open Apps -> G Suite -> Gmail -> Advanced settings. Navigate down to the compliance section and look for MTA-STS.

Figure 1: How to turn on end-to-end encryption in Gmail (source)

Click on it to be presented with the exact recommended MTA-STS configuration for your setup:

Figure 2: MTA-STS configuration diagnostics (source)

Voila, Workspace has just created and configured the policy you need, which you can deploy using the steps above.

Avoiding Common Pitfalls

Before you begin implementing your own MTA-STS policy, it’s best to apply some best practices that have developed based on the experiences of the email administration community. Here are some quick tips that will save you headaches down the road:

  1. Set mode to testing and verify before setting to enforce.
  2. Don’t set max_age too large or changes will delay propagation.
  3. If you already enforce TLS with DANE, you still can and should use MTA-STS.

That last point requires some explanation. MTA-STS is an alternative to DANE that is easier to implement because DANE requires DNSSEC.

Conclusion

MTA-STS policy file syntax is simple, but there are many areas of the implementation that sysadmins can get wrong. DNS, file hosting, and mail server administration are all murky technical fields mired in complicated technical stacks. Left to figure everything out by trial and error, adding new features like MTA-STS is no walk in the park, and debugging can be even harder.

The guidance in this article was thoroughly tested for correctness at every step, so your MTA-STS implementation experience will be easy and smooth. By astutely avoiding the pitfalls, adhering to best practices, and following the advice that we laid out above, you should be able to create a secure, robust MTA-STS policy and thereby make your organization a little more secure.