To send an email with dynamically created PDF as an attachment. There are two steps.
Step 1: Dynamically create a pdf
Step 2: Send this pdf as an attachment
Libraries used.
npm install aws-sdk ejs nodemailer html-pdf
Why do we need all these libraries?
aws-sdk is used for sending the email.
nodemailer is used to create an email with an attachment.
ejs is the templating engine used for create dynamic HTML.
html-pdf is used to convert HTML to pdf.
Step 1: Dynamically create a pdf
Let us create a template for html.
<!-- template.ejs --!>
<!DOCTYPE html>
<html>
<head>
<title>My Table</title>
</head>
<body>
<h1>Table</h1>
<table style="width: 100%;">
<tr>
<th>Qty.</th>
<th>Unit Price</th>
<th>Total Cost</th>
</tr>
<% if (products.length) { %>
<tr>
<% products.forEach(function (product) { %>
<td id="quantity"><%= product.quantity %></td>
<td id="unitPrice"><%= product.unitPrice %></td>
<td id="totalPrice"><%= product.totalPrice %></td>
<% }) %>
</tr>
<% } %>
</table>
</body>
</html>
Now let's use this template to generate the HTML. I'm not writing the file to disk. Instead, keep the file in memory and pass it on.
import ejs from 'ejs';
import htmlPdf from 'html-pdf';
export async function htmlToPdfBuffer(pathname, params) {
const html = await ejs.renderFile(pathname, params);
return new Promise((resolve, reject) => {
htmlPdf.create(html).toBuffer((err, buffer) => {
if (err) {
reject(err);
} else {
resolve(buffer);
}
});
});
}
Usage would be like
const fileBuffer = await htmlToPdfBuffer('template.ejs', {
products: [{ quantity: 2, unitPrice: 10, totalPrice: 20 }]
});
Now, fileBuffer
is the dynamic pdf file which has to be sent. You could use toFile
method of html-pdf
to write this to disk.
Step 2: Send this pdf as an attachment
We could use aws-sdk
directly for attachments. You would have to do MIME encoding manually, which is a bit tedious.
export function sendEmailWithAttachments(
subject,
html,
toAddresses,
attachments
) {
const ses = new AWS.SES();
const transporter = nodemailer.createTransport({
SES: ses
});
const mailOptions = {
from: "from@example.com",
subject,
html,
to: toAddresses,
attachments
};
transporter.sendMail(mailOptions, (err, data) => {
});
}
Final usage
const fileBuffer = await htmlToPdfBuffer("template.ejs", {
products: [{ quantity: 2, unitPrice: 10, totalPrice: 20 }]
});
sendEmailWithAttachments(
"This is test subject",
"<p>This email contails attachment</p>",
["to@example.com"],
{ filename: "attachment.pdf", content: fileBuffer }
);
Top comments (0)