balavishnuvj
Posted on March 2, 2020
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 }
);
Posted on March 2, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 28, 2024
November 15, 2024