MIME (Multipurpose Internet Mail Extensions) is the header-and-boundary system that tells a mail client what is in the body of a message - plain text, HTML, an attachment, or some combination. When it is malformed, the most common symptom is not a bounce. It is a message that renders wrong, shows raw headers as body text, or drops an attachment silently, and in some cases a message that a spam filter scores more aggressively because its structure does not match what a legitimate mail client produces.
What a correct MIME structure looks like
A simple HTML email with a plain-text fallback uses multipart/alternative:
Content-Type: multipart/alternative; boundary="b1_9f2e4a" --b1_9f2e4a Content-Type: text/plain; charset="UTF-8" Plain text version here. --b1_9f2e4a Content-Type: text/html; charset="UTF-8" <html><body>HTML version here.</body></html> --b1_9f2e4a--
Every part after the preamble starts with --boundary, and the final part ends with --boundary-- (note the trailing double dash). The boundary string itself must not appear anywhere inside the actual part content, or the parser will treat that line as a new section break.
Where this actually breaks
- Missing or mismatched boundary. If the
boundary=value in the header does not exactly match the--boundarylines in the body (including case and trailing whitespace), most clients fail closed and show the raw MIME source as the message body. - Attachment declared with the wrong Content-Type. A PDF sent as
Content-Type: text/plaininstead ofapplication/pdfwill often render as a block of unreadable binary text rather than downloading as a file. - Missing `Content-Transfer-Encoding`. Binary attachments need
base64encoding declared explicitly. Without it, non-ASCII bytes in the raw SMTP stream can corrupt the message or, on stricter servers, get rejected mid-transfer. - Charset mismatch. Declaring
charset="UTF-8"while actually sending Windows-1252 bytes (common with copy-pasted text from certain editors) turns curly quotes and em dashes into mojibake, which some content filters read as evidence of a hastily assembled bulk sender. - Nested multipart done wrong. A message with both an HTML/text alternative and an attachment needs
multipart/mixedwrapping amultipart/alternativepart, each with its own distinct boundary. Reusing the same boundary string for both levels is a common copy-paste mistake that breaks parsing for some clients even though others render it by accident.
Why it affects deliverability, not just rendering
Spam filters do inspect message structure, not just content. A message with a boundary mismatch, an empty or missing MIME-Version header, or a Content-Type that doesn't match the actual byte content is a structural signal that something assembled the message incorrectly - and a lot of actual spam is assembled by scripts that get this wrong. A well-formed message is not a guarantee of inbox placement, but a malformed one is one more data point pushing a borderline message toward spam, on top of whatever reputation and content signals are already in play.
How to find the actual error
Pull the raw source rather than trusting how your own client renders it - some clients repair bad MIME silently.
openssl s_client -starttls smtp -connect smtp.yourprovider.com:587 -crlf EHLO test.local AUTH LOGIN <base64 username> <base64 password> MAIL FROM:<you@yourdomain.com> RCPT TO:<test@yourdomain.com> DATA Subject: MIME test MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="b1_test" --b1_test Content-Type: text/plain; charset="UTF-8" Plain text body. --b1_test-- . QUIT
Send it to an address you control, then open the message in Gmail's "Show original" or Outlook's message source view and check that the boundary lines match the header exactly and that every part closes correctly.
Fixing it in your sending stack
- Generate boundary strings programmatically with enough entropy that they can never collide with body content - most mail libraries (PHP's PHPMailer, Python's
email.mime, Node'snodemailer) do this correctly by default, so a hand-built MIME body is the usual source of these bugs. - Always set
MIME-Version: 1.0even on simple single-part messages that technically don't require it - some filters flag its absence as unusual. - Match
Content-Typeto the actual file:application/pdf,image/jpeg,application/vnd.openxmlformats-officedocument.wordprocessingml.documentfor .docx, not a genericapplication/octet-streamunless the type is genuinely unknown. - Declare
Content-Transfer-Encoding: base64for any binary part and actually base64-encode the bytes - don't declare it and then send raw binary. - Validate with a second, independent mail client before rolling out a template change, since one client silently correcting an error will hide it from you.
What not to do
Do not hand-edit a MIME boundary once a template is built on a library that generates it automatically - a manual edit is the single most common way these bugs get introduced. Do not reuse one boundary string across nested multipart sections. And do not assume a message that looks fine in your own inbox is proof the MIME is valid - test in at least two different client renderers, since forgiving clients mask boundary errors that stricter filters do not forgive.
MailPilot's seed-inbox network checks real inbox placement per provider, which catches the downstream effect of a MIME problem - a message rendering badly or landing in spam - even when the root cause is a header you would not normally think to inspect.
Ready to reach the inbox every time?
Automated email warmup across real peer mailboxes. Live inbox placement monitoring. Free 7-day trial - no credit card required.
Start free trial