I’m working on a project where I need to send emails through Mailgun’s API. I’m creating the email content as a MIME string using PHPMailer, but I want to submit it directly to Mailgun using cURL instead of their official library.
I’m trying to post to the /v3/[domain]/messages.mime endpoint. According to the docs, I need to send the MIME content as a file upload using the message parameter with multipart/form-data encoding.
{ "message": "'message' parameter is not a file" }
It seems like Mailgun expects the MIME data to be treated as a file upload rather than just a string value. How can I format the cURL request properly to make this work?
This happens because Mailgun’s API wants MIME content as a file upload, not a string parameter. I ran into the same problem building a custom integration. Don’t use CURLFile with data URIs - it’s unreliable. Write the MIME content to a temp file instead: php $tempFile = tempnam(sys_get_temp_dir(), 'mailgun_mime'); file_put_contents($tempFile, $emailContent); curl_setopt($curlHandle, CURLOPT_POSTFIELDS, [ 'message' => new CURLFile($tempFile, 'message/rfc822', 'message.mime') ]); // Clean up after unlink($tempFile); Make sure you set the MIME type to message/rfc822 - Mailgun expects this for MIME messages. This method handles large emails better and won’t break on complex MIME structures like data URIs do.
yeah, ran into this same prob. use CURLFile or the @ symbol to treat it as a file upload. try curl_setopt($curlHandle, CURLOPT_POSTFIELDS, ["message" => new CURLFile('data://text/plain;base64,' . base64_encode($emailContent))]); - worked for me!
Been there. Temp files work but Mailgun’s API quirks and file upload management get annoying fast.
I ditched that for Latenode to automate the whole email pipeline. Connects PHPMailer straight to multiple providers without fighting API specifics. No temp files, no MIME headaches.
Webhook receives your email data, formats it how you want, routes through whatever service has the best delivery rates. I push thousands daily this way - haven’t touched cURL since.
Best part? Switch providers instantly if Mailgun breaks or jacks up pricing. Built-in retry logic and error handling without writing it yourself.
Here’s another approach that works well: use cURL’s @ prefix syntax with PHP streams instead of actual files. Since you’ve got MIME content in memory, create a temp stream and reference it directly:
This skips creating actual temp files and handles multipart encoding automatically. It’s especially handy for high-volume email sending since you’re not hitting the filesystem constantly. Don’t forget to include your API key in the auth headers when you make the Mailgun request.