AhaSend
Back to Blog

Need inline images in your transactional emails? Switch to AhaSend

Mark Kraakman
Mark Kraakman
Insights

Some transactional email providers can't embed images directly in the message. Their transactional API only lets you link to a hosted image, not attach one and reference it inline. Brevo is a common example: its transactional API has no support for inline (CID) images, so logos, receipts, and signatures that should render inside the email end up as broken links or get stripped.

AhaSend supports inline images natively, over both the API and SMTP. If that gap is why you're looking to move, switching is quick.

Inline vs linked images

There are two ways to put an image in an email:

  • Linked: an <img src="https://..."> pointing at a hosted file. Simple, but it depends on the recipient's client loading remote images, which many block by default.
  • Inline (embedded): the image travels inside the message as an attachment and is referenced with a cid: URL. It renders even when remote images are blocked, which is why it's the right choice for logos, QR codes, tickets, and invoices.

AhaSend does inline images the standard MIME way, so it works across mail clients.

How inline images work on AhaSend

Attach the image, mark it inline, give it a Content-ID, and reference that ID from your HTML with cid:.

{
  "from": { "email": "[email protected]", "name": "Your Company" },
  "recipients": [ { "email": "[email protected]" } ],
  "subject": "Your receipt",
  "html_content": "<p>Thanks for your order!</p><img src=\"cid:[email protected]\" alt=\"logo\">",
  "attachments": [
    {
      "base64": true,
      "data": "iVBORw0KGgoAAAANSUhEUgAA...",
      "content_type": "image/png",
      "file_name": "logo.png",
      "content_disposition": "inline",
      "content_id": "<[email protected]>"
    }
  ]
}

One detail that trips people up: the content_id value must be wrapped in angle brackets (<[email protected]>), exactly as it appears in the MIME Content-ID header. The cid: reference in your HTML stays without the brackets (cid:[email protected]). Set content_disposition to inline so clients render it in place rather than as a download.

Full field reference: Create Message, attachments.

Switching from your current provider

If you call the API directly: map your existing payload to AhaSend's Create Message endpoint and move each embedded image into the attachments array with content_disposition: "inline" and a bracketed content_id. The rest of the request (from, recipients, subject, html_content) maps over directly.

If you use Symfony: AhaSend is a drop-in replacement. There's an official Symfony Mailer bridge (symfony/aha-send-mailer), so you keep your existing Email code, including ->embed() for inline images, and only change the transport.

composer require symfony/aha-send-mailer
# .env  (API transport)
MAILER_DSN=ahasend+api://API_KEY@default

# or SMTP
MAILER_DSN=ahasend+smtp://USERNAME:PASSWORD@default

Your existing Symfony code keeps working unchanged:

$email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Your receipt')
    ->html('<p>Thanks!</p><img src="cid:logo">')
    ->embed(fopen('/path/to/logo.png', 'r'), 'logo');

Symfony's embed() handles the Content-ID for you, so inline images just work once the DSN points at AhaSend.

Where to find things

Set up a domain, add your API key, and your inline images will render the way you intended.

Start for free on AhaSend →