How to use pdf output of PDFMake in the attachment mail options of NodeMailer?

10,248

Solution 1

you could instead of pipe, pass the entire pdfdoc to the attachment

var pdfDoc = printer.createPdfKitDocument(docDefinition); 
pdfDoc.end();

and then:

attachments: {
    // stream as an attachment
    filename: 'text4.pdf',
    content: pdfDoc
}

Solution 2

I was able to get it to work using a buffer, and ending the buffer AFTER the email was sent with the attachment from PDFMake. If you end the buffer before the email is sent it will not work:

const printer = new pdfMakePrinter(fontDescriptors);
const doc = printer.createPdfKitDocument(docDefinition);
let buffers = [];
doc.on('data', buffers.push.bind(buffers));
doc.on('end', () => {
    let pdfData = Buffer.concat(buffers);

    let mailOptions = {
        from: '"John Doe" <[email protected]>', // sender address
        to: '[email protected]', // list of receivers
        subject: 'stuff' // Subject line
        text: '',
        html: '', // html body
        attachments: [{
            filename: 'attachment.pdf',
            content: pdfData
        }]
    };

    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
            return console.log(error);
        }
        console.log('Message sent: %s', info.messageId);
        console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
    });

});

//end buffer
doc.end();
Share:
10,248
Ritesh Jagga
Author by

Ritesh Jagga

Updated on June 04, 2022

Comments

  • Ritesh Jagga
    Ritesh Jagga almost 2 years

    Here is a one of PDFMake's code snippet to create pdf file:

    var pdfDoc = printer.createPdfKitDocument(docDefinition);
    pdfDoc.pipe(fs.createWriteStream('pdfs/absolute.pdf'));
    pdfDoc.end();
    

    and here is one of the attachment option in NodeMailer:

    {
      // stream as an attachment
      filename: 'text4.txt',
      content: fs.createReadStream('file.txt')
    }
    

    I am able to create pdf and save it to a file in a directory and attach that saved file in the e-mail but I want to directly send the output of pdf to the attachment content of e-mail without saving the pdf output to a file.

    I tried to understand nodejs pipe and stream features but couldn't understand them to meet my requirement. I think it should be possible through stream and pipe but don't know how to achieve.

    I want to prevent saving of pdf output to file because there can be multiple users using the functionality of creating pdf file and sending e-mail. There can be a situation when a pdf file created by one user will be overwritten by another user.

  • sɐunıɔןɐqɐp
    sɐunıɔןɐqɐp over 5 years
    From Review: Hi, please don't answer just with source code. Try to provide a nice description about how your solution works. See: How do I write a good answer?. Thanks
  • Anil
    Anil about 5 years
    Uncaught Error { filename: undefined, line: NaN, row: NaN, message: 'Converting circular structure to JSON', type: 'TypeError', stack: 'TypeError: Converting circular structure to JSON\n at JSON.stringify (<anonymous>)\n at mandrill (C:\\Users\\MITVJADEV011\\Desktop\\react\\manyuBackEnd\\node‌​_modules\\node-mandr‌​ill\\mandrill.js:28:‌​39)\n at Object.sendMail (C:\\Users\\MITVJADEV011\\Desktop\\react\\manyuBackEnd\\serv‌​ices\\auth.service.j‌​s:87:2)
  • mithril_knight
    mithril_knight about 5 years
    hi there @Anil . please correct me if I'm wrong. are you using node-mailer with a mandrill transport/plugin? I haven't really tested that setup, I used this approach for out of the box node-mailer setup. do you mind to share a little more details about your situation?
  • Anil
    Anil about 5 years
    var mandrill = require('node-mandrill')('mykey'); var pdfDoc = printer.createPdfKitDocument(docDefinition);pdfDoc.end(); mailData['fileName'] = 'WoorOrderReminder.pdf'; mailData['fileType'] = 'application/pdf' mailData['fileContent'] = pdfDoc; attachments: [{ "type": mailData.fileType, "name": mailData.fileName, "content": mailData.fileContent }] this is my code i got above error
  • mithril_knight
    mithril_knight about 5 years
    @Anil ok my man, one thing first: this question and answer were about node-mailer module, you are using a totally different one node-mandrill. no worries, look at the readme of the module you are using, it says it uses the mandrill api with a minimal overhead, I looked a bit into the source code and is just a little wapper, has no utils for handling files from streams or disc locations. and as the module says, you should read the official mandrill api docs, which says that attachments must be base64 string content. personal note: if the api has an official module use it. is mandrill-api
  • mithril_knight
    mithril_knight about 5 years
    @Anil and also please go to devRant, will be nice to have you over there :)