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

2.3 KiB

title domain category tags status created updated
Python smtplib: Missing Date/Message-ID Headers Break Mail Clients troubleshooting general
email
python
smtplib
spam
rfc
spark
published 2026-04-29 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:

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:

# 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.