pdftwiliosendgridtwilio-api

Possible to create PDF Attachment dynamically in SendGrid?


I'm trying to see if it is possible to create an email using SendGrid with a PDF attachment that utilising custom data...

For example, Customer A sees a PDF of Customer A related Data, Customer B sees a PDF of Customer B related data and so on.

I can create a PDF from an existing PDF, which I just find weird, and creating a PDF from a URL doesn't work as the PDF always comes out corrupted, so my only options at the moment are to make a PDF from an existing PDF.

Twilio/SendGrid documentation, StackOverflow and Google

Has anyone had experience with this and could offer some advice?


Solution

  • So in the end I used PDFKit to generate a PDF that I then attach to the SendGrid API request... here is a basic wireframe of what I am doing

    require('dotenv').config(); // Have to use this as my local is being a d*ck
    const sgMail = require('@sendgrid/mail');
    const apiKey = `${process.env.SENDGRID_API_KEY}`;
    const fs = require('fs');
    sgMail.setApiKey(apiKey);
    
    //Create PDF Dynamically
    const PDFDocument = require('pdfkit');
    const doc = new PDFDocument({size: 'A4'});
    const filename = "customerData.pdf";
    
    doc.pipe(fs.createWriteStream(filename)); // write to PDF
    
    // add stuff to PDF here...
    doc.font('Helvetica')
    doc.fontSize(12);
    doc.text('Hello world!')
    
    // finalise the PDF and end the stream
    doc.end();
    
    let attachment = fs.readFileSync(filename).toString("base64");
    
    const msg = {
      to: 'receipient@email.com',
      from: 'sender@email.com',
      subject: 'Attachment',
      html: '<p>Please find your PDF attached!</p>',
      attachments: [
        {
          content: attachment,
          filename: filename,
          type: "application/pdf",
          disposition: "attachment"
        }
      ]
    };
    (async () => {
      try {
        await sgMail.send(msg).then(() => console.log('send mail success'));
      } catch (error) {
        console.error(error);
    
        if (error.response) {
          console.error(error.response.body)
        }
      }
    })();
    

    Hopefully this will help someone else who is experiencing a similar problem