---
title: "Email Attachment Size Limits and Base64 Overhead"
description: "Why a 25 MB limit fits about 18 MB of attachments, the limits Gmail, Microsoft 365, SES, SendGrid, Mailgun, and Postmark publish, and how to test the boundary."
canonical_url: "https://smtp.dev/docs/guides/email-size-limits/"
---

> Index of every page on this site: [llms.txt](https://smtp.dev/llms.txt)

Most email size limits count the message as it travels, not the files you attached. Attachments are base64-encoded on the way, which makes them about 37% bigger.

## The Encoding Overhead

SMTP carries text, so a binary attachment is base64-encoded: every 3 bytes become 4 characters, a third more. MIME then wraps the encoded text at 76 characters per line, and every line break adds 2 bytes:

```text
encoded size ≈ file size × 4/3 × 78/76 ≈ file size × 1.37
```

The largest attachment that fits is about 73% of the limit, a little less once you count headers and the body:

<table>
<thead>
  <tr>
    <th>
      Message limit
    </th>
    
    <th>
      Largest attachment, roughly
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      10 MB
    </td>
    
    <td>
      7.3 MB
    </td>
  </tr>
  
  <tr>
    <td>
      20 MB
    </td>
    
    <td>
      14.6 MB
    </td>
  </tr>
  
  <tr>
    <td>
      25 MB
    </td>
    
    <td>
      18.3 MB
    </td>
  </tr>
  
  <tr>
    <td>
      30 MB
    </td>
    
    <td>
      21.9 MB
    </td>
  </tr>
  
  <tr>
    <td>
      35 MB
    </td>
    
    <td>
      25.6 MB
    </td>
  </tr>
  
  <tr>
    <td>
      40 MB
    </td>
    
    <td>
      29.2 MB
    </td>
  </tr>
</tbody>
</table>

Attachments share one limit. Two 10 MB files make a message of about 27 MB.

## Published Limits

<table>
<thead>
  <tr>
    <th>
      Service
    </th>
    
    <th>
      Limit
    </th>
    
    <th>
      Counts
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Gmail, personal accounts
    </td>
    
    <td>
      25 MB
    </td>
    
    <td>
      Attachments on a sent message. Over the limit, Gmail swaps them for a Google Drive link
    </td>
  </tr>
  
  <tr>
    <td>
      Yahoo Mail
    </td>
    
    <td>
      25 MB
    </td>
    
    <td>
      All attachments in one message, sent or received
    </td>
  </tr>
  
  <tr>
    <td>
      Microsoft 365, Exchange Online
    </td>
    
    <td>
      35 MB to send, 36 MB to receive
    </td>
    
    <td>
      The whole message, by default. Admins can set anything from 1 to 150 MB
    </td>
  </tr>
  
  <tr>
    <td>
      Amazon SES
    </td>
    
    <td>
      40 MB
    </td>
    
    <td>
      The whole message after base64 encoding, over SMTP or the v2 API. The v1 API allows 10 MB
    </td>
  </tr>
  
  <tr>
    <td>
      SendGrid
    </td>
    
    <td>
      Under 30 MB
    </td>
    
    <td>
      The whole message, through the v3 Mail Send API
    </td>
  </tr>
  
  <tr>
    <td>
      Mailgun
    </td>
    
    <td>
      25 MB
    </td>
    
    <td>
      The whole message
    </td>
  </tr>
  
  <tr>
    <td>
      Postmark
    </td>
    
    <td>
      10 MB
    </td>
    
    <td>
      The whole message. The text and HTML bodies can be up to 5 MB each
    </td>
  </tr>
</tbody>
</table>

<note>

From each provider's own help pages and documentation, checked November 2026. Google Workspace and Microsoft 365 admins can set different limits for their organization.

</note>

A message passes at least two of these limits: your provider's on the way out, and the recipient's on the way in. The smaller one wins. A 38 MB message that SES accepts still bounces at a Microsoft 365 mailbox on the default 36 MB receive limit.

Every SMTP server also states its own limit. Connect, send `EHLO`, and the `SIZE` line in the reply is the maximum in bytes ([how](https://smtp.dev/docs/guides/send-test-email/#by-hand-with-openssl)). `send.smtp.dev` replies `SIZE 20971520`, which is 20 MB.

## Testing the Boundary

Size bugs show up in two places: the message that's too big, and what your app does when a server refuses it. Both are easy to reproduce in the sandbox.

Make one file that fits and one that doesn't:

```bash
head -c 12000000 /dev/urandom > fits.bin
head -c 18000000 /dev/urandom > too-big.bin
```

Encoded, `fits.bin` is about 16 MB and goes through `send.smtp.dev`. `too-big.bin` is about 25 MB, so the server refuses it with `552`:

```bash
swaks --server send.smtp.dev --port 587 --tls \
  --auth-user sender@test.example.com --auth-password "$SMTP_PASSWORD" \
  --from sender@test.example.com --to qa@test.example.com \
  --attach @too-big.bin
```

For the message that arrived, the [API](https://smtp.dev/docs/api/#get-a-message) reports the size of the message and of each attachment. Compare them with what your app attached:

```bash
curl "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}" \
  -H "X-API-KEY: $SMTP_DEV_API_KEY" | jq '{size, attachments: [.attachments[] | {filename, size}]}'
```

Then send the oversized message through your app and check what happens next:

- **Check before sending.** Estimate the encoded size from the file sizes, and send a download link instead of an attachment past your provider's limit. That's what Gmail does with Drive.
- **Treat 552 as permanent.** Retrying a message that's too big fails the same way every time.
- **Tell someone.** The person who triggered the email should learn it didn't go out.

## Sitemap

See the full [sitemap](https://smtp.dev/sitemap.md) for all pages.
