如何为您的发件域设置 SPF、DKIM 和 DMARC
How to set up SPF, DKIM, and DMARC for your sending domain

原始链接: https://mailfully.com/blog/spf-dkim-dmarc-setup

电子邮件身份验证对于自动发送的邮件至关重要,包括密码重置、发票和交易邮件。SPF 根据信封发件人域或 Return-Path 域授权发送服务器。DKIM 使用 DNS 中发布的域名对邮件进行加密签名,以验证邮件的真实性和完整性。DMARC 要求 SPF 或 DKIM 与可见发件人域对齐,并向接收方说明如何处理验证失败的邮件以及将报告发送到哪里。 请为专用发送子域配置这些记录。添加邮件服务提供商的 DKIM CNAME 记录,为自定义 MAIL FROM 域配置 SPF 和 MX 记录,并在 `_dmarc` 位置发布 DMARC 策略。开始时设置为 `p=none`,监控汇总报告;待所有合法发件方验证通过后,再调整为 `quarantine` 或 `reject`。 由于 SPF、DKIM 和 DMARC 检查的域各不相同,因此即使 SPF 和 DKIM 都通过验证,DMARC 仍可能失败。请确认保存的 DNS 名称正确,关闭 DKIM 记录的 Cloudflare 代理,避免创建重复的 SPF 记录,并通过生产应用程序的发送流程进行测试。身份验证有助于提高邮件送达率,但不能保证邮件进入收件箱;发件信誉、邮件内容、投诉率和发送模式也会产生影响。

黑客新闻 最新 | 往期 | 评论 | 提问 | 展示 | 职位 | 提交 登录 如何为你的发件域设置 SPF、DKIM 和 DMARC ( mailfully.com ) 17 分 由 spy888 4 小时前提交 | 隐藏 | 往期 | 收藏 | 讨论 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请加入 YC | 联系我们 搜索:
相关文章

原文

It's way too common to overlook email authentication when you set up automated email. You connect your email provider, send a test message, and it lands in spam. Or Gmail bounces it with a 550 5.7.26 error about an unauthenticated sender. This guide explains how a sending domain is authenticated, which helps keep your messages out of spam.

The three key email security components are SPF, DKIM, and DMARC. They let receiving mail servers check whether a message is authorized to use your domain, and they work together: SPF authorizes the sending server's IP address, DKIM adds a cryptographic signature to prove message integrity, and DMARC uses both results to check alignment with the visible sender address and enforce your policy. [1, 2] Getting them right won't guarantee inbox placement, but a missing record can keep ordinary mail from arriving. Password resets and invoice sends need these checks just as much as newsletters do.

Gmail's sender guidelines require SPF or DKIM even for small senders, and all three for senders reaching roughly 5,000 messages a day to personal Gmail accounts. We suggest you set them up right away when you connect your domain.

We'll use Mailfully's domain setup here to show how everything works. If you use another provider, the record values will differ, but you'll make the same two checks: are the records published correctly, and does a message sent through your app actually pass?

What you're setting up

When your message arrives, the receiving mail server asks three questions. Each record answers one:

  • SPF (Sender Policy Framework): Was the server that delivered this message allowed to send for this domain?
  • DKIM (DomainKeys Identified Mail): Did this message really come from this domain, and did it arrive unchanged?
  • DMARC (Domain-based Message Authentication, Reporting, and Conformance): Do those answers apply to the address the recipient sees in the From line? If not, what should happen to the message?

All three are DNS records: short pieces of text published at your DNS host, such as Cloudflare, that any mail server can look up.

The diagram below follows one message from your email provider to the receiving server. It shows which part of the message each check reads, which DNS record the server looks up for it, and what happens when DMARC passes or fails.

Diagram: mail.example.com sends a signed email. The receiving server checks SPF against the Return-Path domain, DKIM against the signature's d= domain, and DMARC against the From domain, using public DNS records. A DMARC pass continues to normal delivery; a fail follows the domain's policy: none, quarantine, or reject.

Notice that each check reads a different domain from the same message. SPF uses the Return-Path, DKIM uses the signature's d= domain, and DMARC uses the From address. Most setup problems come from one of those domains not being the one you expected. The table puts the same information in one place:

Record What it checks Which domain it checks Where it's published
SPF The sending server is on the allowed list The Return-Path (envelope sender) A TXT record at the Return-Path domain
DKIM The message carries a valid signature The d= domain in the signature A record at <selector>._domainkey.<domain>
DMARC SPF or DKIM passed for a domain that matches the From The domain in the visible From address A TXT record at _dmarc.<domain>

SPF: which servers can send for you

SPF is a list of servers allowed to send mail for a domain, published as a DNS TXT record. When a message arrives, the receiving server compares the IP address that delivered it against that list. If the address is on the list, SPF passes. If it isn't, SPF fails or softfails, depending on how the record ends.

Example SPF for host example.com:

v=spf1 include:_spf.google.com ~all

The part that's easy to miss is which domain SPF checks. It doesn't look at the From address your recipient sees. It checks the envelope sender, also called the MAIL FROM or Return-Path. That's a separate address used behind the scenes, mostly so bounce messages have somewhere to go. Recipients don't see it unless they open the raw message, and email providers often set it to their own domain by default.

Think of a letter in an envelope. The postal service uses the return address on the envelope; the reader sees the letterhead inside. SPF checks the envelope, not the letterhead.

SPF is also tied to the server that hands over the message. When mail is forwarded, the forwarding server becomes the one delivering it, and it usually isn't on your list, so SPF often fails after forwarding.

DKIM: a signature that proves the message is yours

DKIM works like a tamper-evident seal. When your provider sends a message, it signs it with a private key that only the provider holds and adds the signature to the message as a header. The matching public key is published in your DNS, so any receiving server can look it up and check the signature.

DKIM example on host s1._domainkey.example.com:

v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3Xk...IDAQAB

If the signature checks out, the receiver knows two things. The message was signed by someone who controls the key for that domain, and the signed parts haven't changed along the way. The signed parts are the body and a set of headers that always includes From and usually includes Subject. If any of them were altered in transit, the check fails.

Each signature names the domain it signs for in its d= field. That's the domain the receiver looks up, and it's the domain DMARC later compares to your From address. A single message can carry several DKIM signatures, each for a different domain.

DMARC: tying it all to the From address

SPF and DKIM have a gap when used alone: neither one checks the From address your recipient sees. A spammer can send mail through their own server, with SPF passing for their own Return-Path domain and a DKIM signature for their own domain, and still put your domain in the From line. Both checks pass, just for the wrong domain.

DMARC closes that gap by connecting the checks to the domain in the visible From address. For a message to pass DMARC, at least one of SPF or DKIM must pass and use a domain that matches the From domain. That match is called alignment.

DMARC example on host _dmarc.example.com:

v=DMARC1; p=quarantine; rua=mailto:[email protected]; adkim=s; aspf=r; pct=100

Alignment doesn't have to mean identical. Under the default, relaxed rules, any two domains that share the same organizational domain align. The organizational domain is the part you'd buy from a registrar, such as example.com. So mail.example.com and send.mail.example.com align with each other, but neither aligns with example.net.

For example, a message from [email protected] can pass DMARC through SPF on send.mail.example.com. An SPF pass on your email provider's own domain won't do it. The same applies to DKIM: a valid signature from an unrelated provider domain doesn't authenticate your From address for DMARC.

This explains the otherwise confusing result where SPF and DKIM both say “pass,” but DMARC says “fail.” The checks can succeed for the wrong domains.

DMARC also tells receivers what to do with mail that fails (p=none, p=quarantine, or p=reject), and it can ask them to send you reports, which is how you find senders you forgot about. Step 3 covers both.

Before you open your DNS settings

Choose the domain you'll send from. For app mail, a subdomain such as mail.example.com is a good place to start. It gives you room to configure sending without mixing those records into the setup you use for staff email. We cover that choice in Send your transactional mail from a subdomain.

We'll use mail.example.com throughout this guide. Replace it with your own sending domain, and copy the actual record values from your provider. The DKIM selectors below are examples; publishing them won't verify your domain.

You'll need access to the service that hosts your DNS. That might be your registrar, but it could also be Cloudflare or another host. If you're unsure, this command shows your domain's nameservers:

dig NS example.com +short

In Mailfully, add your domain from the Domains page. You'll get a list of records, with a copy button and a status for each one. Keep that page open while you work through your DNS settings. If your DNS is on Cloudflare, Mailfully can add these records for you; see If your DNS is on Cloudflare at the end.

The Mailfully domain page listing the DKIM, MAIL FROM, and DMARC records for a sending domain, each with a copy button

Step 1: add the DKIM records

Mailfully gives you three DKIM CNAME records. Each points to a public key hosted by Mailfully, which means keys can rotate without another round of DNS edits on your side.

Type Name Value
CNAME k7qz2._domainkey.mail.example.com k7qz2.dkim.mailfully.com
CNAME m4tr9._domainkey.mail.example.com m4tr9.dkim.mailfully.com
CNAME p2xw8._domainkey.mail.example.com p2xw8.dkim.mailfully.com

Pay attention to the Name or Host field. Some DNS hosts expect the full name; others append your zone name for you. If you're editing the example.com zone and the form appends example.com, enter k7qz2._domainkey.mail. Entering the full name in that kind of form can produce this:

k7qz2._domainkey.mail.example.com.example.com

That's a valid place to publish a record, but no receiving server will look there for your DKIM key. Check the saved record's full name before waiting for verification.

If you use Cloudflare, set these CNAMEs to DNS only, shown by the grey cloud. The proxy is for web traffic and prevents the CNAME from resolving to the DKIM target as intended.

Check each saved record, using the selector from your dashboard:

dig CNAME k7qz2._domainkey.mail.example.com +short

The answer should match the target value. If it's empty, check the saved name and record type first. The change may also need time to become visible through your DNS provider.

Step 2: set up SPF on the return path

Many email providers use their own domain for the Return-Path unless you configure a custom one. SPF can pass in that setup, but it won't align with your From domain. Your mail can still pass DMARC through aligned DKIM; setting up a custom MAIL FROM gives it another way to pass.

For example, Mailfully uses send. by default. For our sending domain, that makes the MAIL FROM domain send.mail.example.com. You need an MX record and a TXT record at that name:

Type Name Value Priority
MX send.mail.example.com feedback-smtp.us-east-1.amazonses.com 10
TXT send.mail.example.com v=spf1 include:_spf.mailfully.com ~all

The MX record routes bounce messages back to the sending service. The TXT record authorizes the servers listed through _spf.mailfully.com to send for this domain. Use the values shown in your dashboard, including the region in the MX target.

These records belong at send.mail.example.com. You don't need to replace the SPF record that Google Workspace or Microsoft 365 uses at example.com. SPF records apply to the name where they're published; they aren't inherited by subdomains.

A domain name can have only one SPF record. If you publish two TXT records beginning with v=spf1 at the same name, receivers return permerror. When several services need to send for the same name, their authorizations must fit into one SPF record. There is also a limit of 10 DNS lookups during evaluation, including lookups caused by nested include: entries, so a long list of providers can cause trouble even in a single record.

Mailfully's record ends in ~all, which produces an SPF softfail for an unlisted sender. You may see other guides recommend -all, which produces a fail. Neither is an unconditional command to put a message in spam or reject it; the receiver also considers DMARC and its own filtering rules. Use the record your provider supplies unless you have a specific reason to change it.

Check both records:

dig TXT send.mail.example.com +short
dig MX send.mail.example.com +short

There should be exactly one SPF record in the TXT results. Other TXT records are fine. If you see two separate records starting with v=spf1, fix that before moving on.

Step 3: add DMARC and watch the reports

First, check whether your domain already has a DMARC policy. Don't replace an existing quarantine or reject policy with none just to follow this example. If you don't publish _dmarc.mail.example.com, receivers fall back to the policy at _dmarc.example.com, including its sp= subdomain policy if present. A separate record lets you manage the sending subdomain on its own, but check the inherited policy first so you don't accidentally weaken it.

For a new setup with no existing policy, start with:

Type Name Value
TXT _dmarc.mail.example.com v=DMARC1; p=none;

p=none asks receivers not to quarantine or reject mail because of your DMARC policy. They can still filter it for other reasons. This gives you a chance to find legitimate senders that aren't aligned before you ask receivers to block failing messages.

To see what's happening, add an address for aggregate reports:

v=DMARC1; p=none; rua=mailto:[email protected]

Create that mailbox or alias before publishing the record. Participating receivers typically send daily XML reports showing the sending IPs they observed and the authentication results. Those files aren't pleasant to read by hand, so a DMARC reporting service or parser is useful once they start arriving. Reports sent to a different organizational domain generally need an authorization record at the destination; reporting services should give you instructions for that.

Give the reports enough time to cover your normal sending activity. A couple of weeks may be enough for an app that sends every day. It won't tell you much about a billing system that sends once a month. Check password resets, invitations, receipts, support tools, and anything else using this From domain.

Once those senders pass, change the policy to p=quarantine and keep watching. This asks receivers to treat failing messages as suspicious, usually by putting them in spam. When you're confident that legitimate mail is covered, move to p=reject to ask receivers to refuse failing messages.

Expect to see some failures even with a correct setup. Unauthorized senders are part of what you're looking for. The question is whether any of the failures belong to a service you actually use. Fix those before tightening the policy.

Step 4: send a real message and check it

New records often become visible within minutes, though caching and the DNS host can make the wait longer. Mailfully checks the records against live DNS and flags common problems: Wrong name for a doubled domain name, Behind a proxy for a proxied CNAME, and Not found when it can't find the record.

The Mailfully DNS check showing each record as Published, while the DKIM and Mail From verification status is still Pending

Once the records verify, send a message through the same path your app will use in production. A test sent from your personal mailbox won't tell you whether your app's provider is signing mail correctly.

Send it to a Gmail account, for example, then open the message menu and choose Show original. You'll see an authentication summary near the top. Further down, look for the Authentication-Results header added by Gmail:

Authentication-Results: mx.google.com;
       dkim=pass [email protected] header.s=k7qz2;
       spf=pass smtp.mailfrom=0100019[email protected];
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=mail.example.com

Check the domains as well as the word “pass.” DKIM should use your sending domain, and smtp.mailfrom should use the custom MAIL FROM domain you set up. The result you ultimately want is dmarc=pass for your visible From domain. A second DKIM signature from the sending service's own domain is normal; it doesn't prevent your own signature from aligning.

It's worth getting both SPF and DKIM aligned even though DMARC only needs one. Forwarding often breaks SPF, but DKIM can survive that hop as long as the forwarder hasn't changed the signed content. Mailing lists that rewrite subjects or add footers can still break it.

If something still fails

What you see What to check
Domain stays pending Check the full saved DNS name and whether the CNAME is proxied.
spf=permerror Look for duplicate SPF records or a policy that exceeds the lookup limit.
spf=pass but dmarc=fail Check whether the Return-Path aligns with the From domain. An SPF pass on the provider's domain won't be enough.
dkim=pass but dmarc=fail Check the signature's d= domain against the From domain, including any strict alignment settings.
Everything passes, but mail goes to spam Check domain and IP reputation, complaints, message content, and sending patterns. Authentication alone doesn't decide placement.

If authentication passes, adding more DNS records won't fix a reputation problem. For a new domain, start with expected mail at a modest volume and build from there. Investigate complaints instead of treating them as an unavoidable cost of sending. Google recommends keeping reported spam rates below 0.1% and avoiding 0.3% or higher.

If your DNS is on Cloudflare

You can save the manual copying by choosing Set up with Cloudflare on the Mailfully domain page. It uses Domain Connect: you sign in to Cloudflare, review the proposed DNS changes, and approve them.

If Mailfully finds an existing DMARC record on the domain or its parent, this setup leaves that policy alone and adds only the DKIM and MAIL FROM records. An existing quarantine or reject policy stays in place.

The domain page lists the records and their statuses afterward. Once they verify, send the test message from Step 4. That's how you'll confirm the setup is working for the mail your app actually sends.

联系我们 contact @ memedata.com