How to properly handle inline image attachments with Mailgun PHP SDK?

I’m building an email forwarding system using the Mailgun PHP library. My users can send emails with inline images, but when I forward them through Mailgun, the images show up as broken links instead of displaying properly in the email body.

The issue is that I can’t figure out how to correctly handle inline attachments versus regular attachments. When I use the attachment parameter, images get added to the bottom of the email as downloadable files. When I use the inline parameter, I still get broken image links.

Here’s my webhook data structure:

$_POST = [
    'attachment-count' => 2,
    'content-id-map' => '{
        "<[email protected]>": "attachment-1",
        "<[email protected]>": "attachment-2"
    }'
];

$_FILES = [
    'attachment-1' => [
        'name' => 'screenshot.jpg',
        'type' => 'image/jpeg',
        'tmp_name' => '/tmp/phpABC123',
        'error' => 0,
        'size' => 95000
    ],
    'attachment-2' => [
        'name' => 'chart.png',
        'type' => 'image/png', 
        'tmp_name' => '/tmp/phpDEF456',
        'error' => 0,
        'size' => 45000
    ]
];

My processing code:

$attachments = [];
foreach($content_id_map as $content_id => $file_key) {
    $uploaded_file = $_FILES[$file_key];
    
    $attachment_data = [];
    $attachment_data["filePath"] = $uploaded_file["tmp_name"];
    $attachment_data["filename"] = $uploaded_file["name"];
    $attachments[] = $attachment_data;
}

// Send email
$response = $this->mailgun->messages()->send($my_domain, [
    'from' => $sender_email,
    'to' => $recipient_email,
    'subject' => $email_subject,
    'html' => $html_content,
    'h:Reply-To' => $sender_email,
    'inline' => $attachments // or 'attachment' => $attachments
]);

The HTML contains image tags like:

<img src="cid:[email protected]" alt="screenshot" width="300" height="200">

How can I properly detect which images should be inline vs regular attachments, and make sure the inline ones display correctly in the email body?

Your problem lies with how the Content-ID header is set up for inline images; the CID references need to match exactly. You can resolve this by correcting the format when using Mailgun’s inline parameter. Consider using the following PHP code:

$inline_attachments = [];
foreach($content_id_map as $content_id => $file_key) {
    $uploaded_file = $_FILES[$file_key];
    $inline_attachments[] = [
        'filePath' => $uploaded_file['tmp_name'],
        'filename' => $uploaded_file['name'],
        'contentId' => trim($content_id, '<>')
    ];
}

The key is to strip the angle brackets from the Content-ID when configuring it for Mailgun, while keeping them in your HTML cid references. I faced the same challenge with my email system a year ago, and this solution resolved all the broken image links.

check your HTML body’s cid format - Mailgun sometimes wants the content-id without angle brackets in the attachment config but keeps them in the HTML. also make sure you’re using the ‘inline’ parameter right, don’t mix it with ‘attachment’. I had the same problem coz I set both parameters at once and it confused Mailgun’s processing.

Your content-id mapping is messed up during forwarding. When Mailgun forwards emails, it needs the original content IDs preserved or remapped properly. Right now your HTML still points to the original CIDs, but Mailgun creates new ones when sending.

I’ve dealt with this exact problem on a forwarding service. You’ve got to update your HTML content before sending so it matches the new content IDs you’re assigning. Parse the HTML and replace the cid references with what Mailgun will actually use.

Here’s what worked for me: strip the angle brackets from your content_id_map keys, then do a string replace in your HTML to update all cid references so they match what you’re passing to the inline parameter. The broken links happen because there’s a mismatch between original and forwarded content IDs.