How to Use Mailgun's Send Mail Function to Send Multiple Attachments?

This topic was automatically generated from Slack. You can find the original thread here.

How to set the object to send multiple attachments with Mailgun’s send mail function?

To send multiple attachments with Mailgun’s send mail function in a Pipedream workflow, you can use the Mailgun API directly since the pre-built “Send Email” action in Pipedream’s UI does not explicitly document handling multiple attachments. You’ll need to construct a multipart/form-data request that includes your email fields and the attachments. Here’s how you can do it using a custom Node.js code step in Pipedream: import { axios } from "@pipedream/platform" export default defineComponent({ props: { mailgun: { type: "app", app: "mailgun", }, }, async run({ steps, $ }) { const formData = new $send.http.FormData() formData.append("from", "Excited User <mailgun@YOUR_DOMAIN_NAME>") formData.append("to", "[bar@example.com](mailto:bar@example.com)") formData.append("subject", "Hello") formData.append("text", "Testing some Mailgun awesomeness!") // Append the first attachment formData.append("attachment", $send.http.fileFromPath("/tmp/your-first-file.pdf")) // Append the second attachment formData.append("attachment", $send.http.fileFromPath("/tmp/your-second-file.pdf")) return await axios($, { method: "post", url: `https://${this.mailgun.$auth.region && this.mailgun.$auth.region === "EU" ? "[api.eu](http://api.eu)" : "api"}.[mailgun.net/v3/YOUR_DOMAIN_NAME/messages](http://mailgun.net/v3/YOUR_DOMAIN_NAME/messages)`, auth: { username: "api", password: `${this.mailgun.$auth.api_key}`, }, headers: { ...formData.getHeaders(), }, data: formData, }) }, }) Please replace "YOUR_DOMAIN_NAME" with your actual Mailgun domain name and adjust the "from", "to", "subject", and "text" fields as necessary. Also, replace "/tmp/your-first-file.pdf" and "/tmp/your-second-file.pdf" with the paths to your actual files. You may need to download or otherwise prepare these files in previous steps of your workflow. This example demonstrates how to send an email with two attachments, but you can append more attachments in the same manner by adding more formData.append("attachment", $send.http.fileFromPath("/path/to/your-file")) lines for each additional

Hi , how are you?
Would you help me ?
thanks

hi

Hi Marcelo - thanks for the screenshots. The error message states that you need to provide a Buffer, Stream, File or String, but instead two objects were passed as arguments.

I suggest reading the Mailgun API documentation and then using Pi to help you make the appropriate conversion

how to set the attachments parameter with multiple files to use with this function: async download($, attachments) {
const promises = Object.entries(attachments).map(async ([
filename,
url,
]) => downloader.run.bind({
url,
filename,
})({
$,
}));

To set the attachments parameter with multiple files for use with the provided function, you’ll need to structure the attachments object in a way that maps filenames to their respective URLs. This object will then be passed to the download function, which iterates over each entry to download the files. Here’s an example of how you can structure the attachments object and call the download function with it: import { axios } from "@pipedream/platform"; // Example downloader function const downloader = { async run({ url, filename, $ }) { // Example download logic const response = await axios($, { method: "GET", url: url, responseType: "stream", }); // Example saving logic, assuming '/tmp' directory and using `filename` const path = `/tmp/${filename}`; response.data.pipe(fs.createWriteStream(path)); return path; }, }; // Your download function async function download($, attachments) { const promises = Object.entries(attachments).map(async ([ filename, url, ]) => downloader.run.bind({ url, filename, })({ $, })); // Wait for all downloads to complete const results = await Promise.all(promises); return results; } // Example usage (async () => { const $ = {}; // Your context object const attachments = { "example1.txt": "https://example.com/file1.txt", "example2.txt": "https://example.com/file2.txt", // Add more files as needed }; const downloadedFiles = await download($, attachments); console.log(downloadedFiles); })(); In this example, attachments is an object where each key is a filename and each value is the URL to download the file from. The download function iterates over this object, downloading each file using the provided downloader.run method. Note that the actual download logic and saving to /tmp directory is just an example and should be adjusted according to your requirements. Remember, when working with files in Pipedream, you should use the /tmp directory for temporary file storage as shown in the example.

hey Pierce, I get this function here: pipedream/components/mailgun/actions/send-email/send-email.mjs at 96cdb30b3217cd859e6eba4fea5604268eaedecc · PipedreamHQ/pipedream · GitHub

so i created a nodejs script: **let** anexos = {};
**if**(steps.trigger.event.body["attachment-count"]>=1){
**for** (**let** i = 1; i <= steps.trigger.event.body["attachment-count"]; i++) {
Object.assign(anexos, {[steps.trigger.event.body[attachment-${i}].filename]: steps.trigger.event.body[attachment-${i}].url});
}
}

but I am getting the error: Unknown value [object Object],[object Object] with type object for property “attachment”

solution: **const** attachments = **await** Promise.all(steps.trata_email.$return_value.files.map(**async** (filepath) => {
**return** {
filename: filepath.replace('/tmp/',''),
data: **await** fs.promises.readFile(filepath)
};
}));
messageParams.attachment = attachments;