pdfsendgridemail-attachmentspassword-protectionqpdf

Sending password protected attachments via SendGrid


I want to send password protected pdfs as email attachments using SendGrid for nodejs.

I tried to password protect my pdf using qpdf. This outputs a new pdf file that is password protected locally. I then try to read data from this file and send it as the content of the attachment per SendGrid's documentation.

const fs = require('fs');
const qpdf = require('node-qpdf');

const options = {
  keyLength: 128,
  password: 'FAKE_PASSWORD',
  outputFile: filename
}
const attachments = []

await new Promise(res => {
  const writeStream = fs.createWriteStream('/tmp/temp.pdf');
  writeStream.write(buffer, 'base64');
  writeStream.on('finish', () => {
      writeStream.end()
  });
  res();
})
await qpdf.encrypt('/tmp/temp.pdf', options);
const encryptedData = await new Promise(res => {
  const buffers = []
  const readStream = fs.createReadStream('/tmp/temp.pdf');
  readStream.on('data', (data) => buffers.push(data))
  readStream.on('end', async () => {
    const buffer = Buffer.concat(buffers)
    const encryptedBuffer = buffer.toString('base64')
    res(encryptedBuffer)
  })
})
attachments.push({
  filename,
  content: encryptedData,
  type: 'application/pdf',
  disposition: 'attachment'
})

I get the email with the pdf as an attachment, but it's not password protected. Is this possible to do with these 2 libraries?


Solution

  • It looks like your sending the unencrypted file. Maybe this would work?

    const fs = require('fs');
    const qpdf = require('node-qpdf');
    
    const options = {
      keyLength: 128,
      password: 'FAKE_PASSWORD'
    }
    const attachments = []
    
    await new Promise(res => {
      const writeStream = fs.createWriteStream('/tmp/temp.pdf');
      writeStream.write(buffer, 'base64');
      writeStream.on('finish', () => {
          writeStream.end()
          res(); // CHANGED
      });
    })
    await qpdf.encrypt('/tmp/temp.pdf', options, filename); // CHANGED
    const encryptedData = await new Promise(res => {
      const buffers = []
      const readStream = fs.createReadStream(filename); // CHANGED
      readStream.on('data', (data) => buffers.push(data))
      readStream.on('end', async () => {
        const buffer = Buffer.concat(buffers)
        const encryptedBuffer = buffer.toString('base64')
        res(encryptedBuffer)
      })
    })
    attachments.push({
      filename,
      content: encryptedData,
      type: 'application/pdf',
      disposition: 'attachment'
    })