Nodejs send stream via email

It seems that in this case, the only way to send the file is to read the entire stream and send it as a string or buffer:

const stream = examplePass.generate();

res.set({
    'Content-Type': 'application/vnd.apple.pkpass',
    'Content-disposition': `attachment; filename=${passName}.pkpass`,
});

stream.pipe(res);

const chunks = [];

stream.on('data', chunk => {
    chunks.push(chunk);
});

stream.on('end', () => {
    const content = Buffer.concat(chunks);

    const transporter = nodemailer.createTransport({
        host: 'smtp.gmail.com',
        port: 587,
        secure: false,
        requireTLS: true,
        auth: {
            user: '[email protected]',
            pass: 'password',
        },
    });

    const mailOptions = {
        from: '[email protected]',
        to: '[email protected]',
        subject: 'You\'re on your way to ',
        html: '<h1>Reciept email</h1>',
        attachments: [
            {
                filename: 'Event.pkpass',
                contentType: 'application/vnd.apple.pkpass',
                content
            },
        ],
    };

    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
            return console.log(error.message);
        }
        console.log('success:', info);
    });

});

BUT! You need to be careful with this approach if the file is large, as it is fully loaded into RAM.


Your problem is that you piped the stream to res which is a "StreamReader" aka consumer, instead you need just to pass it to nodeMailer which it is a StreamReader by itself.

const stream = examplePass.generate();

// res.set({
//   'Content-Type': 'application/vnd.apple.pkpass',
//   'Content-disposition': `attachment; filename=${passName}.pkpass`,
// });

// stream.pipe(res); <- remove this

//Send the receipt email

stream.on('finish', (attach) => {
  let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 587,
    secure: false,
    requireTLS: true,
    auth: {
      user: '[email protected]',
      pass: 'password',
    },
  });

  let mailOptions = {
    from: '[email protected]',
    to: '[email protected]',
    subject: "You're on your way to ",
    html: '<h1>Reciept email</h1>',
    attachments: [
      {
        filename: 'Event.pkpass',
        contentType: 'application/vnd.apple.pkpass',
        content: stream,
      },
    ],
  };

  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      return console.log(error.message);
    }
    console.log('success ' + info);
  });
});

This is how I'm streaming email attachments.