Ritesh Jagga
Ritesh Jagga

Reputation: 1442

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

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.

Upvotes: 6

Views: 14287

Answers (4)

Zoltiel
Zoltiel

Reputation: 31

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();

Upvotes: 3

user6922460
user6922460

Reputation:

var pdfMake = require('pdfmake/build/pdfmake.js');
var pdfFonts = require('pdfmake/build/vfs_fonts.js');
pdfMake.vfs = pdfFonts.pdfMake.vfs;
//var base64 = require('base64-js');

var docDefinition = function(json) {
  return {
    content: [
      'PARAGRAPH 1',
      'paragraph 2', {
        columns: [
          'first column is a simple text', {
            stack: [
              // second column consists of paragraphs
              'paragraph A',
              'paragraph B',
              'these paragraphs will be rendered one below another inside the column'
            ],
            fontSize: 15
          }]}]};};

const pdfDocGenerator = pdfMake.createPdf(docDefinition);
pdfDocGenerator.getBuffer((pdfBuffer) => {
    // HERE YOU HAVE THE PDF BUFFER 
    //var pdfbase64 = base64.fromByteArray(buffer);
    //console.log("pdfDocGenerator.getBuffer OK" + pdfbase64);
    fs.writeFileSync('foo.pdf', buffer);
}

Upvotes: 0

Eneas Mar&#237;n
Eneas Mar&#237;n

Reputation: 164

Here's what I did. It works in a Meteor app.

Client Side:

var docDefinition = {
    content: [
        'First paragraph'
    ]
};

var data;
pdfMake.createPdf(docDefinition).getBase64(function(encodedString) {
    data = encodedString;
    Meteor.call("sendPDFEmail", data);
});

Server Side

sendPDFEmail: function(thepdf){
    Email.send({
        to: "receiver",
        from: "sender",
        subject: "Test",
        html: "text",
        attachments: [
            {
                filename: "test.pdf",
                type: "application/pdf",
                content: Buffer.from(thepdf, 'base64')
            }
        ]
    });
},

Upvotes: 0

mithril_knight
mithril_knight

Reputation: 547

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
}

Upvotes: 12

Related Questions