# MTA-STS & TLS-RPT Auditor (`phoenix2810/mta-sts-auditor`) Actor

Audit a domain's SMTP MTA-STS transport security policy and TLS-RPT reporting record. Checks DNS, HTTPS policy file, MX matching, and returns a readiness score.

- **URL**: https://apify.com/phoenix2810/mta-sts-auditor.md
- **Developed by:** [Sanskar Jaiswal](https://apify.com/phoenix2810) (community)
- **Categories:** Developer tools, SEO tools, Open source
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## MTA-STS & TLS-RPT Auditor

Audits a public domain's SMTP MTA Strict Transport Security (MTA-STS) policy (RFC 8461) and SMTP TLS Reporting (TLS-RPT) record (RFC 8460) in one API call. Checks the `_mta-sts` DNS TXT record, fetches and parses the HTTPS policy file, resolves MX records and matches them against policy patterns, and checks the `_smtp._tls` TLS-RPT TXT record. Returns a readiness score, grade, issues, and actionable recommendations.

### Use cases

- Email deliverability and transport security checks before migrating email providers.
- Security audits for MTA-STS policy enforcement and TLS-RPT reporting across client domains.
- Compliance checks for SMTP transport encryption downgrade resistance.
- Onboarding checks when adding a new domain to email infrastructure.
- Scheduled monitoring for MTA-STS policy drift, expired policy files, or MX coverage gaps.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `startUrl` | string | Yes | Public domain or URL to audit. The actor extracts the hostname and checks MTA-STS DNS and HTTPS policy, MX records, and TLS-RPT DNS. HTTP and HTTPS only. Private IP ranges are blocked. |
| `timeoutSeconds` | integer | No | Timeout for DNS queries and HTTP fetch from 3 to 30 seconds. Default: `10`. |

### Output

Each run pushes one dataset item.

| Field | Type | Description |
| --- | --- | --- |
| `inputUrl` | string | Original input URL or domain. |
| `domain` | string | Extracted domain name used for DNS and HTTP lookups. |
| `checkedAt` | string | ISO timestamp for the audit. |
| `mtaSts` | object | MTA-STS audit results (see below). |
| `tlsRpt` | object | TLS-RPT audit results (see below). |
| `score` | integer | Transport security readiness score from 0 to 100. |
| `grade` | string | Letter grade from A to F. |
| `issues` | array | Human-readable issues found. |
| `recommendations` | array | Recommended fixes. |
| `error` | string or null | Error message, if any. |

#### MTA-STS object

| Field | Type | Description |
| --- | --- | --- |
| `dnsRecord` | string or null | Raw `_mta-sts.<domain>` TXT record. |
| `recordFound` | boolean | Whether an MTA-STS DNS record exists. |
| `recordId` | string or null | Policy id from the DNS record. |
| `policyFileUrl` | string or null | Policy file URL that was fetched. |
| `policyFileFetched` | boolean | Whether the policy file was fetched successfully. |
| `policyFileStatus` | integer or null | Policy file HTTP status code. |
| `policyFileHttps` | boolean | Whether the policy file was served over HTTPS. |
| `policyContentType` | string or null | Policy file Content-Type header. |
| `rawPolicy` | string or null | Raw policy file text. |
| `version` | string or null | Policy version (expected STSv1). |
| `mode` | string or null | Policy mode: enforce, testing, or none. |
| `mxPatterns` | array | MX patterns from the policy file. |
| `maxAge` | integer or null | Policy max\_age in seconds. |
| `mxRecords` | array | Resolved MX hostnames sorted by priority. |
| `mxMatch` | object | MX matching results (matched, unmatched, allMatch, issues). |
| `issues` | array | MTA-STS-specific issues. |

#### TLS-RPT object

| Field | Type | Description |
| --- | --- | --- |
| `dnsRecord` | string or null | Raw `_smtp._tls.<domain>` TXT record. |
| `recordFound` | boolean | Whether a TLS-RPT record exists. |
| `version` | string or null | TLS-RPT version tag (expected TLSRPTv1). |
| `rua` | string or null | Report destination (rua). |
| `ruaSchemes` | array | Schemes used in rua destinations (mailto, https). |
| `issues` | array | TLS-RPT-specific issues. |

### Example input

```json
{
  "startUrl": "https://example.com",
  "timeoutSeconds": 10
}
```

### Example output

```json
{
  "inputUrl": "https://example.com",
  "domain": "example.com",
  "checkedAt": "2026-08-17T00:00:00.000Z",
  "mtaSts": {
    "dnsRecord": "v=STSv1; id=20260101A1",
    "recordFound": true,
    "recordId": "20260101A1",
    "policyFileUrl": "https://mta-sts.example.com/.well-known/mta-sts.txt",
    "policyFileFetched": true,
    "policyFileStatus": 200,
    "policyFileHttps": true,
    "policyContentType": "text/plain",
    "rawPolicy": "version: STSv1\nmode: enforce\nmx: mail.example.com\nmax_age: 604800\n",
    "version": "STSv1",
    "mode": "enforce",
    "mxPatterns": ["mail.example.com"],
    "maxAge": 604800,
    "mxRecords": ["mail.example.com"],
    "mxMatch": {
      "matched": ["mail.example.com"],
      "unmatched": [],
      "allMatch": true,
      "issues": []
    },
    "issues": []
  },
  "tlsRpt": {
    "dnsRecord": "v=TLSRPTv1; rua=mailto:tls-reports@example.com",
    "recordFound": true,
    "version": "TLSRPTv1",
    "rua": "mailto:tls-reports@example.com",
    "ruaSchemes": ["mailto"],
    "issues": []
  },
  "score": 100,
  "grade": "A",
  "issues": [],
  "recommendations": [],
  "error": null
}
```

### Security

- Accepts only public HTTP and HTTPS URLs or domains.
- Rejects URL credentials (user:pass@host).
- Rejects localhost, private IPv4, private IPv6, link-local, and private DNS resolutions.
- Fetches only the MTA-STS policy file at `https://mta-sts.<domain>/.well-known/mta-sts.txt` over HTTPS with SSRF-safe redirect revalidation.
- Performs DNS TXT and MX lookups only for `_mta-sts.<domain>`, `_smtp._tls.<domain>`, and `<domain>` MX.
- Does not collect credentials or private data.
- Does not fetch URLs referenced inside the policy file or TLS-RPT record.

### Pricing

Suggested pay-per-event pricing:

| Event | Price |
| --- | ---: |
| Actor start | `$0.005` |
| Domain audited | `$0.01` |

Typical one-domain run cost: about `$0.015` before Apify platform charges. Apify keeps its standard commission and the actor owner receives the remainder.

### FAQ

#### What is MTA-STS?

MTA-STS (SMTP MTA Strict Transport Security, RFC 8461) is a standard that lets a domain declare that inbound SMTP connections must use TLS with a valid certificate and a specific set of MX servers. It prevents TLS downgrade and STARTTLS stripping attacks. It uses a DNS TXT record at `_mta-sts.<domain>` to signal policy existence, and an HTTPS policy file at `https://mta-sts.<domain>/.well-known/mta-sts.txt` to define the policy.

#### What is TLS-RPT?

TLS-RPT (SMTP TLS Reporting, RFC 8460) is a companion standard that lets a domain request reports about TLS delivery failures from sending MTAs. It uses a DNS TXT record at `_smtp._tls.<domain>` with a `rua=` destination (mailto or HTTPS endpoint).

#### Does this actor check DANE TLSA records?

No. DANE TLSA (RFC 7672) is a separate transport security mechanism that requires DNSSEC. This actor focuses on MTA-STS and TLS-RPT. Use the DNSSEC Validator actor for DNSSEC chain-of-trust checks.

#### Does this actor send test emails?

No. It only performs DNS lookups and fetches the MTA-STS policy file over HTTPS. It does not send SMTP traffic or test mail delivery.

#### What is the scoring based on?

The score starts at 100 and is reduced for: missing MTA-STS DNS record (-40), missing or unfetchable policy file (-25), policy mode none (-15) or testing (-5), missing required policy keys, MX records not covered by policy patterns (-15), no MX records (-10), missing TLS-RPT record (-15), and missing or invalid TLS-RPT rua (-5).

#### Kill or keep metric

Keep this actor if it gets organic Store impressions, runs, revenue, or inbound questions within 60 to 90 days. Improve the listing or pricing if impressions arrive without runs. Archive it if there is no discovery or usage.

# Actor input Schema

## `startUrl` (type: `string`):

Public domain or URL to audit. The actor extracts the hostname and checks MTA-STS DNS and HTTPS policy, MX records, and TLS-RPT DNS. HTTP and HTTPS only. Private IP ranges are blocked.

## `timeoutSeconds` (type: `integer`):

DNS query and HTTP fetch timeout from 3 to 30 seconds.

## Actor input object example

```json
{
  "startUrl": "https://example.com",
  "timeoutSeconds": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrl": "https://example.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("phoenix2810/mta-sts-auditor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrl": "https://example.com" }

# Run the Actor and wait for it to finish
run = client.actor("phoenix2810/mta-sts-auditor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrl": "https://example.com"
}' |
apify call phoenix2810/mta-sts-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,phoenix2810/mta-sts-auditor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HZryxZB2bxiq1Yzzd/builds/CJlEW0ImFouK2oVYz/openapi.json
