# Inline Images

## What are inline images?

Inline images (also called embedded images) are images that appear directly within your email content, rather than as attachments. They're referenced using a special `cid:` (Content-ID) URL scheme in your HTML, making them ideal for:

- **Email signatures**: Company logos and branding
- **Transactional emails**: Product images, receipts, invoices
- **Branded templates**: Headers, footers, and design elements
- **Rich content**: Diagrams, charts, and visual elements

:::info
Inline images are embedded in the email itself, so recipients see them immediately without downloading attachments—even with images disabled in some email clients.
:::

## How inline images work

1. **Attach an image** with a unique Content-ID
2. **Reference the image** in your HTML using `cid:your-content-id`
3. **Email clients display** the image inline when rendering the email

The Content-ID acts as a unique identifier linking your HTML image references to the actual image data.

## Sending inline images via API

### Basic example

<CodeTabs>

```ts title="Node.js"
await lettermint.email
  .from('sender@yourdomain.com')
  .to('recipient@example.com')
  .subject('Welcome to our service')
  .html('<h1>Welcome!</h1><img src="cid:logo" alt="Company Logo">')
  .attach({
    filename: 'logo.png',
    content: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
    content_id: 'logo'
  })
  .send();
```

```php title="PHP"
$lettermint->email
  ->from('sender@yourdomain.com')
  ->to('recipient@example.com')
  ->subject('Welcome to our service')
  ->html('<h1>Welcome!</h1><img src="cid:logo" alt="Company Logo">')
  ->attach([
    'filename' => 'logo.png',
    'content' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
    'content_id' => 'logo'
  ])
  ->send();
```

```bash title="cURL"
curl -X POST https://api.lettermint.co/v1/send \
  -H "x-lettermint-token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "sender@yourdomain.com",
    "to": ["recipient@example.com"],
    "subject": "Welcome to our service",
    "html": "<h1>Welcome!</h1><img src=\"cid:logo\" alt=\"Company Logo\">",
    "attachments": [
      {
        "filename": "logo.png",
        "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
        "content_id": "logo"
      }
    ]
  }'
```

</CodeTabs>

:::info
The `content` field must be **base64-encoded** image data. Most programming languages provide built-in functions for base64 encoding files. Common image MIME types (PNG, JPG, GIF, WebP) are automatically detected from the file content.
:::

### Multiple inline images

You can embed multiple images by using different Content-IDs for each:

:::warning
The total email size—including all inline images, attachments, HTML, and headers—must not exceed **25MB**. See [Limitations](/platform/emails/limitations) for details.
:::

<CodeTabs>

```ts title="Node.js"
await lettermint.email
  .from('sender@yourdomain.com')
  .to('recipient@example.com')
  .subject('Your order receipt')
  .html('<div><img src="cid:header"><h1>Order Confirmation</h1><img src="cid:product-image"><p>Thank you for your order!</p><img src="cid:footer"></div>')
  .attach([
    {
      filename: 'header.png',
      content: '...',
      content_id: 'header'
    },
    {
      filename: 'product.jpg',
      content: '...',
      content_id: 'product-image'
    },
    {
      filename: 'footer.png',
      content: '...',
      content_id: 'footer'
    }
  ])
  .send();
```

```php title="PHP"
$lettermint->email
  ->from('sender@yourdomain.com')
  ->to('recipient@example.com')
  ->subject('Your order receipt')
  ->html('<div><img src="cid:header"><h1>Order Confirmation</h1><img src="cid:product-image"><p>Thank you for your order!</p><img src="cid:footer"></div>')
  ->attach([
    [
      'filename' => 'header.png',
      'content' => '...',
      'content_id' => 'header'
    ],
    [
      'filename' => 'product.jpg',
      'content' => '...',
      'content_id' => 'product-image'
    ],
    [
      'filename' => 'footer.png',
      'content' => '...',
      'content_id' => 'footer'
    ]
  ])
  ->send();
```

```bash title="cURL"
curl -X POST https://api.lettermint.co/v1/send \
  -H "x-lettermint-token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "sender@yourdomain.com",
    "to": ["recipient@example.com"],
    "subject": "Your order receipt",
    "html": "<div><img src=\"cid:header\"><h1>Order Confirmation</h1><img src=\"cid:product-image\"><p>Thank you for your order!</p><img src=\"cid:footer\"></div>",
    "attachments": [
      {
        "filename": "header.png",
        "content": "...",
        "content_id": "header"
      },
      {
        "filename": "product.jpg",
        "content": "...",
        "content_id": "product-image"
      },
      {
        "filename": "footer.png",
        "content": "...",
        "content_id": "footer"
      }
    ]
  }'
```

</CodeTabs>

## Sending inline images via SMTP

When using SMTP, the email library handles Content-ID headers automatically for inline attachments.

### Nodemailer (Node.js)

```javascript
const nodemailer = require('nodemailer');
const fs = require('fs');

const transporter = nodemailer.createTransporter({
  host: 'smtp.lettermint.co',
  port: 587,
  auth: {
    user: 'lettermint',
    pass: 'your-api-token'
  }
});

await transporter.sendMail({
  from: 'sender@yourdomain.com',
  to: 'recipient@example.com',
  subject: 'Email with inline image',
  html: '<h1>Hello!</h1><img src="cid:unique-image-id" alt="Embedded Image">',
  attachments: [
    {
      filename: 'image.png',
      path: './path/to/image.png',
      cid: 'unique-image-id' // Content-ID reference
    }
  ]
});
```

### PHPMailer (PHP)

```php
<?php
use PHPMailer\PHPMailer\PHPMailer;

$mail = new PHPMailer(true);

$mail->isSMTP();
$mail->Host = 'smtp.lettermint.co';
$mail->SMTPAuth = true;
$mail->Username = 'lettermint';
$mail->Password = 'your-api-token';
$mail->Port = 587;

$mail->setFrom('sender@yourdomain.com');
$mail->addAddress('recipient@example.com');
$mail->Subject = 'Email with inline image';
$mail->isHTML(true);
$mail->Body = '<h1>Hello!</h1><img src="cid:unique-image-id" alt="Embedded Image">';

// Add inline image
$mail->addEmbeddedImage('/path/to/image.png', 'unique-image-id', 'image.png');

$mail->send();
```

### Python (smtplib)

```python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

msg = MIMEMultipart('related')
msg['From'] = 'sender@yourdomain.com'
msg['To'] = 'recipient@example.com'
msg['Subject'] = 'Email with inline image'

# HTML content
html = '<h1>Hello!</h1><img src="cid:unique-image-id" alt="Embedded Image">'
msg.attach(MIMEText(html, 'html'))

# Inline image
with open('image.png', 'rb') as img:
    image = MIMEImage(img.read())
    image.add_header('Content-ID', '<unique-image-id>')
    msg.attach(image)

# Send email
with smtplib.SMTP('smtp.lettermint.co', 587) as server:
    server.starttls()
    server.login('lettermint', 'your-api-token')
    server.send_message(msg)
```

## Content-ID format requirements

Content-IDs must follow these rules:

- **Allowed characters**: Letters (a-z, A-Z), numbers (0-9), dots (.), underscores (_), hyphens (-), and at-signs (@)
- **Pattern**: Must match `^[a-zA-Z0-9._@-]+$`
- **Maximum length**: 255 characters
- **Automatic suffix**: If your Content-ID doesn't include `@`, Lettermint automatically appends `@lm` to ensure RFC compliance

### Valid Content-ID examples

- ✅ `logo`
- ✅ `company-logo`
- ✅ `header_image`
- ✅ `product.image.v2`
- ✅ `banner@example.com`
- ✅ `invoice-2024-01`

### Invalid Content-ID examples

- ❌ `logo image` (spaces not allowed)
- ❌ `product#123` (# symbol not allowed)
- ❌ `header!image` (! symbol not allowed)
- ❌ `logo/banner` (/ symbol not allowed)

:::tip
Use descriptive, semantic Content-IDs like `company-logo` or `product-image` instead of generic names like `image1` or `img`. This makes your email templates more maintainable.
:::

## Troubleshooting


<details>
<summary>Image not displaying</summary>

**Check your Content-ID reference**
- Ensure your HTML uses `cid:your-content-id` (note the `cid:` prefix)
- Verify the Content-ID in your attachment matches the HTML reference exactly (case-sensitive)
- Don't include angle brackets (`<>`) in your Content-ID when using the API

**Verify base64 encoding**
- The `content` field must contain valid base64-encoded image data
- Test your base64 string with an online decoder to ensure it's valid

**Check HTML syntax**
```html
<!-- Correct -->
<img src="cid:logo" alt="Logo">

<!-- Incorrect -->
<img src="logo" alt="Logo">
<img src="cid:<logo>" alt="Logo">
```

</details>

<details>
<summary>Image appears as attachment</summary>

If your inline image also appears as a downloadable attachment:
- Ensure you're setting `content_id` in your API request
- For SMTP, verify your email library supports inline attachments (check library-specific documentation)

</details>

<details>
<summary>Content-ID validation errors</summary>

If you receive validation errors:
- Remove special characters except dots, underscores, hyphens, and @
- Keep Content-IDs under 255 characters
- Use only alphanumeric characters if unsure

</details>


## Best practices

1. **Use descriptive Content-IDs**: Choose meaningful names that describe the image's purpose
2. **Optimize image sizes**: Keep images small to reduce email size and improve deliverability
3. **Provide alt text**: Always include `alt` attributes for accessibility and when images are blocked
4. **Test across email clients**: Different email clients handle inline images differently—test thoroughly
5. **Consider fallbacks**: Some email clients block images by default—design emails that work without them

## Related

- [Limitations](/platform/emails/limitations) — Email size limits (25MB) and blocked file types
- [Tags](/platform/emails/tags) — Organize and categorize your emails
- [Webhook events](/platform/webhooks/events) — Track delivery and engagement for emails with inline images
