majorwiki/05-troubleshooting/python-smtplib-missing-rfc-headers.md
majorlinux 1524ca66d5 Add 3 articles; update nav and index (2026-04-29)
New articles:
- Python smtplib: Missing Date/Message-ID Headers Break Mail Clients
- Fantastical MCP: Permission Denied (macOS Quarantine)
- Ubuntu dist-upgrade Repo Quarantine

Updated: troubleshooting index, SUMMARY.md nav, WOL article edits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 22:45:17 -04:00

60 lines
2.3 KiB
Markdown

---
title: "Python smtplib: Missing Date/Message-ID Headers Break Mail Clients"
domain: troubleshooting
category: general
tags: [email, python, smtplib, spam, rfc, spark]
status: published
created: 2026-04-29
updated: 2026-04-29
---
# Python smtplib: Missing Date/Message-ID Headers Break Mail Clients
## Problem
Emails sent via Python's `smtplib` and `EmailMessage` appear on some mail clients but not others. The emails are delivered to the server and visible in Maildir, but specific clients silently suppress them.
## Root Cause
Python's `EmailMessage` does **not** automatically add `Date:` or `Message-ID:` headers. These are required by RFC 5322. Without them:
- **SpamAssassin** flags `MISSING_DATE` and `MISSING_MID`, and may set `X-Spam-Flag: YES` even if the overall score is below the spam threshold
- **Mail clients** (e.g., Spark) may filter on the spam flag header and silently hide the message — no Junk folder, just invisible
- **Other clients** (e.g., iPhone Mail, some Spark builds) may be more lenient and display the message anyway
This creates a confusing situation where the same email appears on one device but not another, despite both using the same IMAP account.
## Fix
Always include `Date` and `Message-ID` headers when constructing emails with `EmailMessage`:
```python
import smtplib
from email.message import EmailMessage
from email.utils import formatdate, make_msgid
msg = EmailMessage()
msg['Subject'] = 'Your subject here'
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
msg['Date'] = formatdate(localtime=True)
msg['Message-ID'] = make_msgid(domain='example.com')
msg.set_content('Email body here')
with smtplib.SMTP('mail.example.com', 25) as s:
s.send_message(msg)
```
## Verification
After applying the fix, check that SpamAssassin no longer flags the headers:
```bash
# Check email headers on the mail server
grep -E 'MISSING_DATE|MISSING_MID|X-Spam' /var/vmail/domain/user/cur/<message-file>
```
A clean message should show `X-Spam-Status: No` with no `MISSING_DATE` or `MISSING_MID` in the test list.
## Key Takeaway
Python's `EmailMessage` is a low-level builder — it trusts you to set all required headers. Unlike higher-level mail libraries or webmail interfaces, it will happily send a message with no date or message ID. Always add both explicitly in any script that sends email via `smtplib`.