SPF for SendGrid (Twilio)
Add include:sendgrid.net to your domain's single SPF TXT record, never publish two SPF records. If you send only through SendGrid (Twilio), the whole record is:
v=spf1 include:sendgrid.net ~all
IMPORTANT: With SendGrid's default 'Automated Security' ON, you do NOT publish an SPF TXT record on your own domain at all. SPF is handled behind the CNAME'd return-path subdomain (e.g. em1234.example.com -> u12345.wl123.sendgrid.net); SendGrid auto-generates the SPF (v=spf1 include:sendgrid.net ~all) at the root of that delegated zone. SPF then authenticates/aligns on the em* subdomain (the envelope MAIL FROM / Return-Path), not on your organizational domain. The literal 'include:sendgrid.net' mechanism only applies if you turn Automated Security OFF and choose manual DNS (SendGrid then gives you an em* TXT 'v=spf1 include:sendgrid.net ~all' plus an em* MX to mx.sendgrid.net), OR if you also send from your root domain through other systems and want an org-level SPF record. include:sendgrid.net costs a single DNS lookup, so it rarely contributes to the RFC 7208 10-lookup limit on its own.
DKIM for SendGrid (Twilio)
In the SendGrid dashboard go to Settings > Sender Authentication > Authenticate Your Domain. Pick your DNS host, enter your domain, and keep 'Automated Security' set to Yes (default). SendGrid generates 3 CNAME records (one em* return-path/SPF record plus the two DKIM selectors s1._domainkey and s2._domainkey) and a _dmarc TXT record. Publish all of them at your DNS provider exactly as shown, wait for propagation, then return to SendGrid and click 'Verify'. DKIM is CNAME-based on purpose: because s1/s2 are CNAMEs pointing into sendgrid.net, SendGrid rotates the underlying DKIM keys for you without you ever touching DNS again. Two selectors exist for redundancy/rotation. If you turn Automated Security OFF, DKIM instead becomes a single TXT record (SendGrid's manual selector is m1._domainkey, with a k=rsa; p=... public key) that you must rotate manually, alongside an em* MX (mx.sendgrid.net) and em* SPF TXT. You can also request a custom selector name via SendGrid support/API if s1/s2 clash with an existing record.
Method: CNAME · Selector(s): s1._domainkey, s2._domainkey
s1._domainkey.example.com. CNAME s1.domainkey.u12345678.wl123.sendgrid.net. s2._domainkey.example.com. CNAME s2.domainkey.u12345678.wl123.sendgrid.net. em1234.example.com. CNAME u12345678.wl123.sendgrid.net. (return-path; carries SPF)
DMARC for SendGrid (Twilio)
SendGrid auto-adds a starter _dmarc TXT record (v=DMARC1; p=none;) during domain authentication, but you own the policy. DMARC passes primarily via DKIM alignment: signed emails carry d=example.com (your authenticated domain), which aligns with the From: header domain, this works in relaxed alignment even though the SPF/Return-Path is the em* subdomain. SPF alignment is only on the em* subdomain, so do not rely on SPF alone for DMARC; make sure DKIM is verified and passing. Start at p=none with aggregate reporting (rua), confirm your SendGrid traffic shows DKIM=pass and aligned, then move to p=quarantine and eventually p=reject. If you authenticate a subdomain in SendGrid, remember DMARC on the org domain applies to subdomains unless you set a separate sp= or subdomain _dmarc record.
v=DMARC1; p=none; rua=mailto:[email protected]; fo=1; adkim=r; aspf=r
Common SendGrid (Twilio) mistakes
- CNAME vs TXT confusion: with Automated Security ON (the default) ALL of SPF/DKIM are published as CNAMEs, not TXT. Do not also hand-add a 'v=spf1 include:sendgrid.net' TXT or a DKIM TXT for the same domain, the CNAME delegation already provides them and a duplicate can conflict.
- Underscore-hostname rejection: some DNS providers (and especially DNS that flattens/proxies, or older panels) refuse underscores in CNAME records, which breaks s1._domainkey / s2._domainkey. If yours does, you cannot use Automated Security, switch it OFF and use the TXT/MX-based manual records instead.
- Forgetting to click 'Verify': publishing the DNS is not enough, you must return to Settings > Sender Authentication and hit Verify so SendGrid marks the domain authenticated; until then mail still sends from sendgrid.net and fails alignment.
- CNAME proxying / Cloudflare orange-cloud: if the em*, s1, s2 CNAMEs are set to 'Proxied' in Cloudflare they resolve to Cloudflare IPs and verification/DKIM break. Set these records to DNS-only (grey cloud).
- Expecting SPF to align on the root domain: SPF/Return-Path is the em* subdomain, so a raw SPF check shows the sendgrid.net/em* domain, not example.com. That is expected, DMARC alignment for SendGrid comes from DKIM (d=example.com), so verify DKIM is passing rather than chasing SPF alignment.
- Not authenticating the domain at all and relying on Single Sender Verification: single-sender verified addresses still send DKIM-signed as sendgrid.net and will fail your DMARC, you must do full Domain Authentication for alignment.
- Manual-mode key rotation: if you disable Automated Security you take over the single DKIM TXT key (m1._domainkey) and must rotate it yourself; you lose SendGrid's automatic s1/s2 rotation.
Frequently asked questions
What SPF record do I need for SendGrid (Twilio)?
Add include:sendgrid.net to your domain's single SPF TXT record. A domain that sends only through SendGrid (Twilio) would use: v=spf1 include:sendgrid.net ~all. IMPORTANT: With SendGrid's default 'Automated Security' ON, you do NOT publish an SPF TXT record on your own domain at all. SPF is handled behind the CNAME'd return-path subdomain (e.g. em1234.example.com -> u12345.wl123.sendgrid.net); SendGrid auto-generates the SPF (v=spf1 include:sendgrid.net ~all) at the root of that delegated zone. SPF then authenticates/aligns on the em* subdomain (the envelope MAIL FROM / Return-Path), not on your organizational domain. The literal 'include:sendgrid.net' mechanism only applies if you turn Automated Security OFF and choose manual DNS (SendGrid then gives you an em* TXT 'v=spf1 include:sendgrid.net ~all' plus an em* MX to mx.sendgrid.net), OR if you also send from your root domain through other systems and want an org-level SPF record. include:sendgrid.net costs a single DNS lookup, so it rarely contributes to the RFC 7208 10-lookup limit on its own.
How do I set up DKIM for SendGrid (Twilio)?
In the SendGrid dashboard go to Settings > Sender Authentication > Authenticate Your Domain. Pick your DNS host, enter your domain, and keep 'Automated Security' set to Yes (default). SendGrid generates 3 CNAME records (one em* return-path/SPF record plus the two DKIM selectors s1._domainkey and s2._domainkey) and a _dmarc TXT record. Publish all of them at your DNS provider exactly as shown, wait for propagation, then return to SendGrid and click 'Verify'. DKIM is CNAME-based on purpose: because s1/s2 are CNAMEs pointing into sendgrid.net, SendGrid rotates the underlying DKIM keys for you without you ever touching DNS again. Two selectors exist for redundancy/rotation. If you turn Automated Security OFF, DKIM instead becomes a single TXT record (SendGrid's manual selector is m1._domainkey, with a k=rsa; p=... public key) that you must rotate manually, alongside an em* MX (mx.sendgrid.net) and em* SPF TXT. You can also request a custom selector name via SendGrid support/API if s1/s2 clash with an existing record.
Do I need DMARC when sending through SendGrid (Twilio)?
SendGrid auto-adds a starter _dmarc TXT record (v=DMARC1; p=none;) during domain authentication, but you own the policy. DMARC passes primarily via DKIM alignment: signed emails carry d=example.com (your authenticated domain), which aligns with the From: header domain, this works in relaxed alignment even though the SPF/Return-Path is the em* subdomain. SPF alignment is only on the em* subdomain, so do not rely on SPF alone for DMARC; make sure DKIM is verified and passing. Start at p=none with aggregate reporting (rua), confirm your SendGrid traffic shows DKIM=pass and aligned, then move to p=quarantine and eventually p=reject. If you authenticate a subdomain in SendGrid, remember DMARC on the org domain applies to subdomains unless you set a separate sp= or subdomain _dmarc record.