Sending attachments over SMTP is not about “adding a file.” It is about building a valid MIME message that survives gateways, spam filters, antivirus scanners, and client rendering differences.

If your attachment workflow is flaky in production, the cause is often MIME structure, encoding overhead, or provider policy limits.

What actually happens when you attach a file

SMTP sends text. Attachments are encoded and wrapped in MIME parts so recipients can reconstruct files.

Typical structure:

  1. Top-level
  2. First part is message body ( or )
  3. Additional part(s) are attachments with:
    • (often )

Minimal raw MIME example

When this structure is wrong, clients may show corrupted files or drop attachments entirely.

Size limits you need to design for

Attachment delivery limits are enforced at multiple layers:

  • sender/provider outbound limit,
  • recipient mailbox provider inbound limit,
  • intermediate gateway/security appliances.

Also remember base64 expansion. Binary data encoded as base64 is larger (roughly one-third overhead), so a “20 MB file” may exceed a “25 MB message limit” once encoded and wrapped.

Correct content types and dispositions

Use the most accurate MIME type you can. Overusing can reduce client behavior quality and increase security scrutiny.

Examples:

  • PDF:
  • CSV:
  • PNG:

Use for downloadable files, and only when you intentionally want rendering in the email body.

Security and deliverability considerations

Attachment handling directly affects inbox placement and user trust.

Key controls:

  1. Restrict executable/high-risk file types.
  2. Virus-scan uploaded files before send.
  3. Validate filenames and strip dangerous characters.
  4. Prefer signed download links for large/sensitive files instead of giant attachments.
  5. Align SPF/DKIM/DMARC so attachment-heavy mail does not look suspicious.

Related references:

Node.js (Nodemailer) example

If you are using Node, this is the shortest reliable pattern.

For explicit file attachments in Nodemailer, add an array with , or , and .

Python SMTP attachment example

Why attachments fail in production

Most failures come from one of these buckets:

  • invalid MIME boundaries,
  • wrong or missing ,
  • file too large after encoding,
  • blocked file type by recipient policy,
  • SMTP auth/TLS mismatch,
  • provider throttling under burst load.

If you see intermittent failures, inspect raw message source and SMTP responses, not just app logs.

Testing strategy that catches real failures

Before release, validate attachment flows in isolated test inboxes.

Recommended assertions:

  1. Message delivered to expected recipient.
  2. Attachment count and filenames match expected values.
  3. MIME types are correct.
  4. File bytes can be downloaded and checksum-verified.
  5. Message still passes auth and spam checks.

You can automate those checks with MailSlurp email sandbox testing and API-based assertions.

Large attachment alternatives

For large assets, links are often safer than attachments:

  • upload file to secure object storage,
  • generate short-lived signed URL,
  • email a lightweight message with context + link,
  • log download activity for audit.

This pattern improves deliverability and reduces SMTP failure rates.

Final take

SMTP attachments are a MIME engineering problem plus an operations problem. If you treat them as both, with strict message construction and automated pre-release checks, attachment bugs become predictable instead of random production incidents.