Why are my Gmail emails bouncing with a 'missing Message-ID' error?

Updated on 17 Oct 2026: We clarified Gmail's Message-ID requirements and added a Python example for generating a valid header.
Gmail is bouncing the message because the final email it received either has no Message-ID header or the header is syntactically invalid under RFC 5322. The error text can say missing even when the header exists, because Gmail is treating an invalid Message-ID as missing a valid header.
One cause is a generator that puts illegal characters in the identifier. An unquoted colon in the id-left is an example. A Message-ID is not a DMARC identifier, and its domain does not need to match the sender domain, return-path domain, DKIM signing domain, or visible From domain. The domain side mainly helps the generator guarantee global uniqueness.
What the Gmail error means
The bounce usually appears at the end of the SMTP DATA command, after Gmail has read the message and parsed its headers. Google's sender guidelines require every message to include a valid Message-ID and follow RFC 5322 formatting. RFC 5322 section 3.6.4 recommends this field with SHOULD; Gmail requires it for acceptance.
Typical Gmail bouncetext
550-5.7.1 Messages missing a valid Message-ID: header are not accepted. 550-5.7.1 Review RFC 5322 specifications. 550 5.7.1 gsmtp
Classify this as a message construction defect. Do not suppress the Gmail recipient as invalid just because the bounce is a hard 550 5.7.1. The mailbox can be real, and the same recipient can accept a corrected message later.
- Header failure: Gmail is objecting to the message headers, not necessarily SPF, DKIM, content, or list reputation.
- End of DATA: The rejection happens after Gmail has enough of the message to evaluate the RFC 5322 structure.
- Bounce handling: Classify it as a send-side fix, then retry only after the generator has produced a compliant header.
- Read the full bounce-back message: 550 5.7.1 also covers other policy errors. Use Gmail SMTP codes to distinguish this header failure from 550 5.1.1 unknown-recipient errors or 552 5.2.2 storage errors.
Do not chase domain matching first
The Message-ID domain does not need to match your From domain. If the identifier is malformed, matching the domain will not fix the bounce. If the identifier is valid, a different domain on the right side is not a Gmail rejection reason by itself.
What a valid Message-ID needs
A valid Message-ID field contains one unique identifier inside angle brackets. It looks similar to an email address, but RFC 5322 gives it tighter generation rules. The left side is the id-left, the right side is the id-right, and the whole value must be globally unique. For new identifiers, the right side allows dot-atom text or a square-bracketed literal. A controlled domain is recommended for uniqueness, rather than required to match the From domain. See the RFC 5322 identification rules.
|
|
|
|---|---|---|
Header field | Exactly one | Missing, blank, or duplicate |
Brackets | One matching pair | Missing or extra |
Left side | Dot-atom text with no leading, trailing, or consecutive dots | Unquoted colon, internal space, or empty dot component |
Right side | Valid id-right; controlled domain recommended | Malformed right-hand value |
Uniqueness | Each new message | Reusing an identifier for different messages |
Message-ID syntax rules and generator recommendations.
Invalid and valid examplestext
Invalid: Message-ID: <app.EMAIL:22f945a8:059d606f@mta.example.net> Valid: Message-ID: <app.EMAIL.22f945a8.059d606f@mta.example.net>
The invalid example fails because the left side contains unquoted colons. Replacing those colons with dots or another allowed separator fixes the syntax without forcing the right side to use the customer sending domain. A blank value, more than one identifier in the field, or duplicate Message-ID fields also fail the one-field, one-identifier requirement.
Safe generator pattern
- Unique data: Use a UUID, or combine time with a random or sequential value that prevents collisions across hosts and restarts. A queue id alone is not guaranteed unique.
- Allowed separator: Use dots or hyphens instead of colons, spaces, or angle brackets inside the value.
- Owned domain: Use a domain controlled by the system that creates the identifier.
- Final check: Validate the exact header after templating, MTA processing, and gateway handling.
Risky generator pattern
- User input: Letting a customer system pass through arbitrary text creates syntax risk.
- Colon chains: Values copied from internal routing ids often include characters Gmail rejects.
- Internal folding: Whitespace inserted inside the angle brackets changes the identifier Gmail parses.
- Log only: Keeping only bounce logs makes it hard to prove what Gmail received.
Check for duplicate and rewritten Message-ID headers
Gmail also rejects duplicate Message-ID fields as an RFC 5322 compliance failure. An application can create a valid identifier before a relay, gateway, forwarding rule, or custom header routine adds a second field. Inspect the final outbound copy, not only the source template. Google explicitly includes Message-ID in its duplicate-header checks; a duplicate can produce a different RFC compliance error from the missing-header wording.
Duplicate and single-header examplestext
Invalid duplicate fields: Message-ID: <20260809.101500.78123@app.example.net> Message-ID: <relay.99812@mta.example.net> Valid single field: Message-ID: <20260809.101500.78123@app.example.net>
- Find the first writer: Record whether the application, library, or MTA creates the original field.
- Trace every handoff: Compare the raw header before and after relays, gateways, and forwarding rules.
- Stop the second writer: Configure downstream systems to preserve an existing valid field instead of adding another.
- Validate the final copy: Confirm that exactly one non-empty, syntactically valid field reaches the outbound SMTP connection.
How to inspect the final email headers
Inspect the message after every system that can change headers. Capture the generated message and the final outbound .eml or MTA queue copy before transmission to Gmail; a rejected message will not be available in the recipient's inbox. The Sent folder or an application log alone does not prove what Gmail received.

Troubleshooting a Gmail missing Message-ID bounce by checking the final email headers.
A single later test that reaches Gmail does not clear the original campaign. A generator can work for some templates and fail for others, or a platform can deploy a fix between the failed send and the test. Capture the exact raw message from the failing window and compare it with an accepted sample. For an accepted Gmail sample in a browser, open the message, click More next to Reply, then select Show original to view its full headers.
- Preserve raw headers: Store the full header block for a sampled set of accepted and rejected messages.
- Log both stages: Compare the Message-ID supplied by the application with the field emitted by the MTA. Keep the MTA queue id as a separate diagnostic value; a queue id in a log does not replace the header.
- Check header placement: Message-ID must appear before the first blank line, which starts the message body. Leading whitespace before the field name makes it a continuation of the preceding header. See the RFC 5322 header rules.
- Group bounces: Cluster by template, client integration, MTA node, Gmail MX host, and exact error string.
- Send a probe: Send a real copy to an email tester and inspect the final headers.
Email tester
Send a real email to this address. Suped shows a results button when the test is ready.
?/43tests passed
Suped's email tester lets you inspect a submitted message's headers. Suped's domain health check and DMARC monitoring help investigate separate authentication failures; use the raw outbound message and SMTP logs to diagnose the Message-ID rejection.

Email tester sample report showing total score, email preview, issue summary, and per-section results
Why only some Gmail messages bounce
When only part of a campaign bounces, do not assume Gmail received byte-identical messages. Different templates, application paths, MTA nodes, gateways, or forwarding routes can create different final headers. Each new message needs its own unique identifier, so compare structure and syntax rather than expecting the values to match.
Compare accepted and rejected raw messages first, then group the results by template, generator version, MTA node, gateway, and Gmail receiving host. A pattern tied to one receiving host can guide the investigation, but it does not prove Gmail changed enforcement. The final message source is the evidence that identifies the exact header defect.
Separate RFC failures from authentication failures
A missing or invalid From header prevents reliable DMARC evaluation because DMARC depends on the visible From domain. Message-ID is outside that identity check, but Gmail can still reject a missing or malformed field as non-compliant mail. For broader RFC cases, use the RFC compliance guide for triage.
How to fix the generator
Fix the system that creates or rewrites the header. If the customer application supplies the Message-ID, give that application a strict contract. If your sending platform accepts customer-supplied headers, validate them at the boundary and either reject the submission or replace only the defective field with a compliant value you generate. Make the repair before DKIM signing, since changing a signed Message-ID value invalidates that signature. See the DKIM signing rules.
Simple safe formattext
Message-ID: <20260529.102030.queue-78123@mta.example.net> Message-ID: <a7f2d4c1-8c91-4c39-b62a-642792ea11c8@mta.example.net>
Each line above is a separate valid pattern, not two fields to place in one message. The right side should use a domain that helps the generator guarantee uniqueness. It can be the MTA host domain, a platform mail domain, or another controlled domain. Preserve a valid identifier on routine SMTP retries of the same message; each new message needs a new value.
- Reject bad input: Do not accept an id with unquoted colons in id-left, internal whitespace, extra brackets, or an empty value.
- Generate when absent: If the application omits the field, create one at the platform or MTA boundary.
- Prevent duplicates: Make each downstream system preserve an existing valid field instead of adding another.
- Avoid rewriting valid ids: Do not change a compliant id just to use the same domain as the sender.
- Keep evidence: Store sampled raw headers long enough to investigate receiver rejections.
- Retest Gmail: Send the same template after the fix and compare the accepted header with the old bounce sample.
Practical fix
Replace colon-separated internal ids with dot-separated or hyphen-separated values, keep the value inside one pair of angle brackets, emit exactly one Message-ID field, and use a domain controlled by the generator. That fixes the common Gmail rejection without changing SPF, DKIM, or DMARC records.
Add a missing Message-ID in Python
For Python applications, use the standard library's make_msgid helper to create a bracketed identifier instead of building one from user input. Set the field when constructing a new message, before submission to your signing MTA.
Generate one Message-ID when constructing a new messagepython
from email.message import EmailMessage from email.policy import SMTP from email.utils import formatdate, make_msgid message = EmailMessage(policy=SMTP) message["From"] = "sender@example.com" message["To"] = "recipient@example.net" message["Subject"] = "Message-ID test" message["Date"] = formatdate(usegmt=True) message["Message-ID"] = make_msgid(domain="mail.example.com") message.set_content("Test message with a valid Message-ID header.") raw_message = message.as_bytes()
Replace mail.example.com with a domain your generator controls, and submit raw_message through your existing authenticated sending path. Do not wrap make_msgid() in extra angle brackets; it already adds them. For an existing message, validate and preserve its valid field rather than appending another.
Views from the trenches
Best practices
Capture final raw headers for failed samples before rotating logs or retrying sends.
Validate customer-supplied Message-ID values at the SMTP or API boundary before accepting mail.
Use a controlled generator domain and unique left-side values for every new message.
Cluster Gmail bounces by error, template, MTA node, receiver host, and generator version.
Common pitfalls
Assuming a visible Message-ID is valid when it contains illegal separator characters.
Blaming sender-domain differences when the real defect is malformed header syntax inside the id.
Keeping only bounce logs and losing the raw message Gmail evaluated during the failed send.
Treating a 550 header rejection as proof the recipient mailbox is invalid for suppression.
Expert tips
Replace unquoted colons with dots or hyphens before the message reaches the outbound MTA.
Retest the same template after the fix, not a different later campaign or clean sample.
Do not rewrite valid identifiers only to make domains look cleaner in downstream headers.
Watch for related RFC 5322 errors, especially missing or malformed From headers.
Marketer view
Marketer from Email Geeks says Gmail can return the missing Message-ID wording even when the header is present but invalid.
2025-08-12 - Email Geeks
Expert view
Expert from Email Geeks says an unquoted colon inside the Message-ID local part is invalid and explains the rejection.
2025-08-12 - Email Geeks

