node.jsgatsbymailgunnetlifynetlify-function

Nodejs and Mailgun: Send generated attachment *not* from file system


I generate attachments in a node app and would like to send them using Mailgun. I have no access to the file system (Netlify functions).

Is there an easy way to accomplish that?

The hole picture

It's a Jamstack (Gatsby/React, Netlify, Mailgun) web app. Customers configure and request offers. Browser generates and posts offers and images to a Netlify function (fetch api). The function send the offer mail with the PDF-offer and images attached.

Code I tested (edit: 02/25)

const path = require('path');
const fs = require('fs');
const mailgun = require('mailgun-js')
const FormData = require('form-data');
const { Readable } = require('stream');

const API_KEY = 'SECRET';
const DOMAIN = 'brasilius.de';

const mg = mailgun({apiKey: API_KEY, domain: DOMAIN, host: "api.eu.mailgun.net"});

const stream = fs.createReadStream('test.txt');                     // This works
/* {
  id: '<20210225115125.1.BF14CC322F8E0DAC@brasilius.de>',
  message: 'Queued. Thank you.'
} */

/*
const stream = Readable.from(["Send this text as attachment."])   // Won't work

{ message: "'from' parameter is missing" }
*/

const data = {
  from: 'Excited User <me@brasilius.de>',
  to: 'test@user.de',
  subject: 'Hello',
  text: 'Testing some Mailgun awesomeness!',
  attachment: stream
};

mg.messages().send(data, (error, body) => {
  console.log(body);
});

Solution

  • The simplest solution I found here

    // https://thecodebarbarian.com/sending-emails-using-the-mailgun-api.html
    
    const mailgun = require('mailgun-js')
    
    const mg = mailgun({apiKey: process.env.API_KEY, domain: process.env.DOMAIN, host: "api.eu.mailgun.net"});
    
    const filename = 'test.txt';
    const text = "Example test content."
    const attch = new mg.Attachment({data: Buffer.from(text), filename: filename})
    
    const data = {
      from: process.env.FROM,
      to: process.env.TO,
      subject: 'Hello',
      text: 'Testing Mailgun attachments.',
      attachment: attch
    };
    
    mg.messages().send(data, (error, body) => {
      console.log(body);
    });
    

    As @Joe recommended, a solution with Nodemailers Mailcomposer:

    // See: https://documentation.mailgun.com/en/latest/api-sending.html#examples
    // See: http://nodemailer.com/extras/mailcomposer/#attachments
    
    const mailgun = require('mailgun-js')
    const MailComposer = require('nodemailer/lib/mail-composer');
    
    const mg = mailgun({apiKey: process.env.API_KEY, domain: process.env.DOMAIN, host: "api.eu.mailgun.net"});
    
    const mailOptions = {
      from: process.env.FROM,
      subject: 'Hello',
      text: 'Testing Mailgun attachments.',
      attachments: [
        { // utf-8 string as an attachment
          filename: 'text.txt',
          content: 'For testing just a text file. This could be a ReadStream, Buffer or other.'
        }
      ]
    };
    
    const mail = new MailComposer(mailOptions);
    
    mail.compile().build(function(mailBuildError, message) {
    
      var dataToSend = {
        to: process.env.TO,
        message: message.toString('ascii')
      };
    
      mg.messages().sendMime(dataToSend, function(sendError, body) {
        if (sendError) {
          console.log(sendError);
          return;
        }
      });
    });