File Attachment Issue with Mailgun API and Axios in React

I’m trying to send emails with file attachments using the Mailgun API in my React application. I’m using axios to make the HTTP requests.

The problem I’m facing is that while the email gets sent successfully and includes an attachment, the attachment has issues. The filename appears as just a dot (“.”) instead of the actual filename I specified. When I try to download and rename the attachment to open it, the content shows “[object Object]” instead of the actual file content.

Here’s my current implementation:

const formData = new FormData();
const fileSystem = require("fs");

formData.append("from", "[email protected]");
formData.append("to", "John Doe <[email protected]>");
formData.append("subject", "Email with Attachment");
formData.append("text", "Please find the attached document.");
formData.append("attachment", [{
    filename: "document.txt",
    data: fileSystem.readFileSync(__dirname + "/sample.txt", {
        encoding: "utf8",
        flag: "r"
    })
}]);

const mailgunEndpoint = "https://api.mailgun.net/v3/sandbox456.mailgun.org/messages";

await axios.post(mailgunEndpoint, formData, {
    auth: {
        username: "api",
        password: process.env.MAILGUN_KEY
    },
    headers: { "Content-Type": "multipart/form-data" }
});

Any suggestions on how to properly format the attachment so it maintains the correct filename and content?

I hit this exact FormData issue when working with file uploads and external APIs. You’re wrapping the file data in an object, but FormData can’t serialize that properly. The problem is you’re treating FormData like a regular JS object. When you append that object, it just becomes a string instead of actual binary file data. That’s why Mailgun gets malformed data with the dot filename and object content. For server-side code, read the file as a buffer and append it directly: formData.append('attachment', fileBuffer, 'document.txt'). The third parameter sets the filename. But here’s the thing - your code won’t work in browsers anyway since you’re mixing fs operations with React. Move this attachment handling to your backend where you can actually access the filesystem and keep your API credentials secure. Send the file data from React to your server endpoint, then let the server handle Mailgun with proper FormData formatting.

yeah, that fs require will definitely break react. but even moving it server-side won’t fix the real issue - you’re wrapping the file in a custom object when mailgun expects the raw buffer.

You can’t use require("fs") in React - that’s a Node.js thing and won’t work in browsers. That’s your main problem right there. You’ve got two options: move the email stuff to your backend server, or use a file input to let users pick files. If users are uploading files, grab them from an input element and stick the File object straight into FormData. I ran into this same mess last year building a document sharing feature. Ended up moving all the Mailgun stuff to our Express backend and just sending file data from React to the server. Plus it keeps your API keys safe since they’re not sitting in client code. If you really need to stay client-side, ditch the fs operations and handle files properly with File objects from input elements.

You’re mixing server-side Node.js code with client-side React. When you append that object structure to FormData, it just gets converted to a string - that’s why you’re seeing ‘[object Object]’. I ran into the same thing building an invoice system last year.

The fix depends on where this code actually runs. If it’s client-side React, you need to use the File API with input elements, then append the actual File object to FormData. If it’s running on your backend, ditch the object wrapper and append the file buffer directly with the filename as the third parameter.

Also - don’t expose your Mailgun API key in client-side code. Move this to a backend API route where you can safely use fs operations and keep your credentials secure.

Remove the array brackets and object wrapper. You’re passing an object when Mailgun wants raw file data. Use formData.append("attachment", fileData, "document.txt") instead of wrapping it. Also, the fs module doesn’t work in browsers - that’s server-side code you’ve got mixed with React.

You’re appending an array with an object to FormData, but FormData wants individual key-value pairs. When you append an array containing an object, it gets stringified - that’s why you’re seeing “[object Object]” in your attachment.

Here’s the fix - append the file data directly:

const formData = new FormData();
const fileSystem = require("fs");
const fileData = fileSystem.readFileSync(__dirname + "/sample.txt");

formData.append("from", "[email protected]");
formData.append("to", "John Doe <[email protected]>");
formData.append("subject", "Email with Attachment");
formData.append("text", "Please find the attached document.");
formData.append("attachment", fileData, "document.txt");

See how I ditched the array wrapper and object structure? The third parameter in formData.append() sets the filename.

But honestly, handling file attachments and email APIs manually gets messy fast. I’ve wasted hours debugging FormData quirks and Mailgun specifics.

Now I just automate this whole thing with Latenode. You can build a workflow that handles file uploads, processes them correctly, and sends emails through Mailgun without dealing with FormData formatting headaches. The visual builder shows exactly what’s happening to your attachments at each step.

Plus you won’t mix server-side code (fs module) with client-side React code, which is another problem in your current setup.

The fs module won’t work in browsers anyway, but you’re also wrapping your file data in an object when FormData needs raw data.

Even if you fix that, you’ll need to move this server-side to keep API keys secure and actually access the file system.

I used to build email stuff manually like this until I got tired of wrestling with API formatting and error handling. Now I just set up the whole pipeline in Latenode.

You can create a workflow that takes file uploads from React, processes them properly, and sends through Mailgun without the FormData headaches or mixing client/server code. The visual interface shows exactly how files move through each step, so debugging attachments is way easier.

Plus no exposed API keys or backend routes just to send emails with attachments. The workflow handles all the Mailgun formatting automatically.