How to send email with file attachment using Mailgun API

I’m trying to send emails with file attachments through the Mailgun service but running into problems. The emails are being delivered successfully but the attachments are not included. When I try to use a file path, it just shows the path as text instead of attaching the actual file.

Here’s the code I’m currently using:

<?php
$api_key = 'key-8bx9ynkp52hd8fds6gc484tgvkxueol1';
$api_version = 'api.mailgun.net/v3/';
$domain_name = "example.mailgun.org";
$sender_email = "[email protected]";
$reply_address = "[email protected]";

$message_endpoint = "https://".$api_version.$domain_name."/messages";

$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_MAXREDIRS, 5);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_VERBOSE, 0);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);

curl_setopt($curl, CURLOPT_USERPWD, 'api:' . $api_key);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_URL, $message_endpoint);

$post_data = array(
    'from' => 'System <' . $sender_email . '>',
    'to' => '[email protected]',
    'h:Reply-To' => $reply_address,
    'subject' => 'Document Package ' . date('Y-m-d'),
    'html' => '<p>Please find attached document</p>',
    'attachment[0]' => 'document.zip'
);

curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
$response = curl_exec($curl);
curl_close($curl);

$decoded_response = json_decode($response, true);
var_dump($decoded_response);
?>

I’m using my actual Mailgun credentials in the real code. Has anyone successfully implemented file attachments with Mailgun? What am I doing wrong here?

The issue arises from passing just a string filename instead of the actual file data. Mailgun requires the file content; therefore, you should utilize CURLFile or the @ syntax for attaching files correctly. Replace your attachment line with: ‘attachment[0]’ => new CURLFile(‘/full/path/to/document.zip’, ‘application/zip’, ‘document.zip’). If you’re on an older PHP version, use ‘attachment[0]’ => ‘@/full/path/to/document.zip’. Ensure the file path is absolute and that the file exists on your server. I encountered a similar problem initially, and this solution worked perfectly for me.

yeah your missing the actual file content there. try using curl_file_create() instead - thats the newer way to do it. something like 'attachment[0]' => curl_file_create('/path/to/document.zip') should work better than just passing the filename as string.

Your code is treating the attachment as a simple string parameter when it needs to be a proper file object. The main problem is in your $post_data array where you have ‘attachment[0]’ => ‘document.zip’ - this just sends the filename as text rather than the actual file contents. I had this exact same issue when I started working with Mailgun attachments. You need to modify your CURL options to handle multipart form data properly. Before setting your post fields, add curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true); and then change your attachment line to use the full file path with new CURLFile(). Also make sure the file permissions are readable by your web server process, as I spent hours debugging what turned out to be a simple permission issue.