当前位置: 首页 > news >正文

Mailjet Setup Pitfall Guide: SPF, DKIM, DMARC Deliverability

Here’s the full English version of this article, keeping the same structure and “real-pitfalls + step-by-step” tone.


This is a step-by-step guide that collects all the real issues I ran into when integrating Mailjet.

Goal: send transactional emails only, deliver reliably to the inbox, and avoid sending limits / suspensions.


0. Pre-Launch Checklist (Quick View)

  • Account has passed manual review / is unsuspended (Business Verification submitted and clearly states “transactional emails only”)
  • You only use your own domain for From addresses (e.g. noreply@yourdomain.com), never gmail.com / outlook.com etc.
  • SPF is a single record only, and includes include:spf.mailjet.com
  • DKIM is active (mailjet._domainkey as a TXT record, value is a single-line public key)
  • DMARC is enabled (_dmarc TXT record, even if policy is just p=none at first)
  • SMTP or Send API is working with a minimal sending example
  • Webhook is configured (you can see bounces, blocks, soft bounces, opens, clicks, etc.)
  • Real-world test with Gmail/Outlook shows: SPF=Pass / DKIM=Pass / DMARC=Pass in headers

1. Account Review & Unblocking (Business Verification)

1.1 Create the account first, then provide extra info

New accounts often see “Sending activity is suspended”.
This is usually not a config error; it means they need more business information and manual review.

1.2 What to tell support (key points)

  • We send transactional emails only (e.g. task assignment notifications, system alerts, status change notifications). No marketing, no bulk campaigns, no purchased lists.
  • Estimate of monthly sending volume (be conservative, e.g. 500–1,000 / month).
  • Recipient sources: internal staff or existing users from our own system, all are work-related notifications.
  • Attach a few sample emails (subject, recipient type, business trigger).
  • Link to your website / product.

This type of description usually speeds up the manual review.
It’s normal if the case gets passed to another team; just wait it out.


2. Only Use Your Own Domain as Sender (Avoid Free Mailboxes)

On the Sender domains & addresses page you’ll see:

  • Domains like gmail.com cannot have SPF/DKIM configured by you. Mailjet explicitly does not recommend or allow them as sending domains. This severely hurts deliverability.
  • Correct approach: add and authenticate your own domain (e.g. yourdomain.com), then use addresses such as noreply@yourdomain.com, alerts@yourdomain.com as From.

3. DNS Authentication (Cloudflare Hands-On)

Tool: Cloudflare dashboard → DNS
Goal: exactly ONE SPF record, ONE DKIM record, ONE DMARC record.

3.1 SPF (must be a single TXT record)

Pitfall #1: Duplicate SPF records → SPF is considered invalid.

You may already have SPF for Google/M365 or Cloudflare Email Routing. Adding Mailjet on top easily leads to multiple records.

Merge rule: put all necessary include: mechanisms into one single SPF record, and keep only one ~all (or -all) at the end.
Example: you need Mailjet + Cloudflare Email Routing + Google:

Name: @
Type: TXT
Value: v=spf1 include:spf.mailjet.com include:_spf.mx.cloudflare.net include:_spf.google.com ~all

Notes:

  • Order does not matter, but there must be only one SPF record.
  • Avoid duplicate include: entries, and only one ~all at the end.
  • Once active, Mailjet’s SPF check should show OK.

3.2 DKIM (TXT, pay attention to “single line”)

In Mailjet’s Domain Authentication Setup you will see:

  • Hostname: mailjet._domainkey (it becomes mailjet._domainkey.yourdomain.com)
  • Type: TXT
  • Value: a long public key starting with k=rsa; p=MIIBI...

Pitfall #2: Pasting multi-line values or adding quotes incorrectly in Cloudflare → looks correct in UI, but actually invalid.

  • Fix: remove line breaks and ensure the value is one single line.
  • Cloudflare will display quotes for you; you do not need to add extra quotes manually.

Example (do not break this line):

Name: mailjet._domainkey
Type: TXT
Value: k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...QIDAQAB

3.3 DMARC (start with p=none)

Even if you don’t enforce anything at first, it’s worth collecting reports to see if anyone is abusing your domain:

Name: _dmarc
Type: TXT
Value: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; sp=none; adkim=s; aspf=s

Later you can move p=nonequarantinereject.

3.4 Other Cloudflare Gotchas

  • Root CNAME: Cloudflare supports CNAME flattening at the root for web; it does not interfere with email TXT/MX records.
  • Orange cloud proxy: TXT records for SPF/DKIM/DMARC are always DNS only, not proxied.
  • TTL: Auto or 5 minutes is fine. After editing, wait a couple of minutes and then hit Refresh in Mailjet.

4. Sending Channel: SMTP vs Send API (Either or Both)

4.1 SMTP (fastest way to start)

  • Dashboard path: Account → SMTP and SEND API settings
  • Credentials: Host: in-v3.mailjet.com, Port: 587 (STARTTLS) or 465 (SSL)
  • Auth: use Mailjet API Key as username, Secret Key as password

Example (Node.js + nodemailer):

import nodemailer from "nodemailer";const transporter = nodemailer.createTransport({host: "in-v3.mailjet.com",port: 587,secure: false, // 587 with STARTTLSauth: {user: process.env.MJ_APIKEY_PUBLIC,pass: process.env.MJ_APIKEY_PRIVATE}
});await transporter.sendMail({from: "noreply@yourdomain.com",to: "employee@yourdomain.com",subject: "Task Assigned #12345",text: "A new work package has been assigned to you.",html: "<p>A new work package has been assigned to you.</p>"
});

4.2 Send API (more flexible, better for structured templates)

Use HTTP POST to https://api.mailjet.com/v3.1/send with Basic Auth (API Key / Secret):

curl -X POST \-u "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \-H "Content-Type: application/json" \https://api.mailjet.com/v3.1/send \-d '{"Messages": [{"From": {"Email": "noreply@yourdomain.com", "Name": "Your App"},"To":   [{"Email": "employee@yourdomain.com", "Name": "John"}],"Subject": "Task Completed - #67890","TextPart": "A meter reading task has been completed.","HTMLPart": "<strong>Reading #67890</strong> completed."}]}'

Best practices

  • For transactional email, send one recipient per message; don’t stuff many employees into the same To/CC/BCC.
  • Maintain templates in Mailjet Transactional templates and treat them like versioned artifacts.
  • Use only the domain you have authenticated for all From addresses.

5. Event Webhooks & Observability

Path: Account → Event notifications (webhooks)

Common events: sent, delivered, open, click, bounce, blocked, spam, unsub (for pure transactional flows you usually won’t see unsub).

Recommendations:

  • Point to a backend endpoint like /mailjet/events, validate the source, and log the raw payload.
  • Build a small “delivery timeline” view: for each message, show send/deliver/open/click/bounce events. This makes debugging much easier.
  • For soft bounces (temporary failures), implement exponential backoff retries (e.g. 5m → 15m → 1h → 6h).

6. Verification & Troubleshooting

6.1 Quick self-test

  1. Send an email to your own Gmail/Outlook address.

  2. View original headers (Gmail → three dots → “Show original”):

    • SPF: PASS
    • DKIM: PASS (d= should be yourdomain.com or the Mailjet DKIM domain)
    • DMARC: PASS (based on the previous two)
  3. If SPF=softfail or DKIM=neutral, go back to Step 3 and double-check DNS.

6.2 Common problems list

  • Multiple SPF records → merge into a single record; keep only one ~all/-all.
  • DKIM value with line breaks / wrong quoting → store as a single line of plain text.
  • Using a free mailbox as From → switch to your own domain.
  • Sending before domain verification is done → leads to throttling or blocking.
  • Transactional email looks like marketing → keep it simple: mostly plain text + light HTML, like a system notification.
  • Aggressive retry behaviour → temporary rejections get worse if you hammer the recipient; use exponential backoff.
  • SMTP auth uses wrong credentials → make sure user/pass are API Key / Secret, not your login email password.

7. “Gray Release” Before Full Production

  • Start with a small internal group for a week: monitor delivery, open rate, bounce rate, and blocked events.
  • Throttling: even with low volumes, keep a reasonable per-minute / per-hour rate, avoid traffic spikes that might look suspicious to ISPs.
  • If the account is limited again: reuse the Section 1 template, explain transactional use, examples, recipient source, and actual sending frequency.

8. Advanced: Sub-Accounts & Environment Separation

  • Use Subaccounts or separate API Keys to isolate production vs test and different product lines. Webhooks can point to different endpoints per key.
  • Subject naming convention: [ENV] Task Assigned #12345 (clearly labeled for non-production).
  • Template variables such as {{name}}, {{task_id}}, {{date}} should be supplied by the backend. Template publishing should go through code review.

9. Minimal Working Configuration (Checklist)

Cloudflare DNS

@                  TXT  v=spf1 include:spf.mailjet.com include:_spf.mx.cloudflare.net include:_spf.google.com ~all
mailjet._domainkey TXT  k=rsa; p=MIIBIjANBgkq...QIDAQAB   // single line
_dmarc             TXT  v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s

Sender

From: noreply@yourdomain.com

Sending

  • SMTP: in-v3.mailjet.com:587 (STARTTLS)
  • Or Send API: POST /v3.1/send (Basic Auth)

Webhook

/mailjet/events  ← subscribe to sent, delivered, open, click, bounce, blocked, spam

10. FAQ

Q: SPF says “multiple SPF records, invalid”, but I need Google + Cloudflare + Mailjet. What now?
A: Combine all include: entries into one SPF record, e.g.:
v=spf1 include:spf.mailjet.com include:_spf.mx.cloudflare.net include:_spf.google.com ~all


Q: DKIM page says “DomainKey invalid”, but Cloudflare shows it saved correctly.
A: 90% of the time the value got split into multiple lines or segments. Change it to a single line value, save, then hit Refresh in Mailjet a few minutes later.


Q: Do transactional emails need an unsubscribe link?
A: True transactional notifications (strongly tied to work / system operations) do not require an unsubscribe link, but you must ensure you only send to recipients with an existing business relationship.


Q: Gmail still puts messages into Promotions or Spam?
A: For transactional messages, try:

  • Mostly plain text with light HTML
  • Minimal external links / images / tracking elements
  • Honest, non-marketing subject lines
  • From and Reply-To using the same or consistent domain
  • All three: SPF / DKIM / DMARC must PASS

Closing

If you follow these steps, you can flatten most of the tricky parts of Mailjet integration in one go:

  • Explain account usage clearly (transactional only)
  • DNS trio set up correctly (single SPF, single-line DKIM, DMARC enabled)
  • Get a minimal SMTP / Send API example working first, then add templates and webhooks
  • Run a small-scale gray release + metrics dashboard so you can quickly trace any problems

Happy sending!

http://www.dtcms.com/a/605048.html

相关文章:

  • 最好的企业网站电子商务网站建设考试重点
  • 大学新校区建设网站北京seo方法
  • SPI学习(QA)
  • 怎么用数据仓库来进行数据治理?
  • Linux_6:FTP云盘项目
  • Spring Boot spring.factories文件详细说明
  • 网站seo文章免费asp地方门户网站系统
  • 《信息存储与管理》逻辑串讲
  • dify TTS部署 GPT-SoVITS
  • kotlin中SharedFlow的简单使用
  • Kotlin 中的 inline 和 reified 关键字
  • 开封府景点网站及移动端建设情况精品资源共享课网站建设 碧辉腾乐
  • 战场目标检测:Faster R-CNN与RegNetX-800MF融合实现建筑物人员坦克车辆识别_2
  • 易语言黑月编译器:提升编程效率与性能优化 | 深入解析易语言开发中的工具应用与技巧
  • Vibe Coding - 从Vibe Coding到Spec Coding_AI编码范式的进化之路
  • 宣化网站建设青岛网站制作推广平台
  • 【多模态大模型面经】 BERT 专题面经
  • Node.js 开发实战:从入门到精通
  • 草莓病害智能识别与分类_Cascade-RCNN_HRNetV2p-W18-20e_COCO实现
  • 改造多模块!!无法使用三方依赖的异常处理
  • JMeter 自动化实战:自动生成文件并传参接口的完整方案
  • AutoSAR实战:RTA-OS Counters操作系统计数器详解
  • FCAF3D: Fully Convolutional Anchor-Free 3D Object Detection论文精读
  • 北京市轨道交通建设管理有限公司网站企业网站建设合同书模板
  • 做图表的网站大连关键词
  • Vue 3中集成GIS(地理信息系统)
  • 进程基本概念
  • Java模拟算法题目练习
  • Mac远程控制新篇章:UU远程被控端深度测评
  • WordPress插件--菜单登录后可见的插件