Sending PDFs as Email Attachments
Generate a PDF and send it as an email attachment using Nodemailer, SendGrid, or Resend.
Overview
A common workflow: generate a PDF, then email it to a customer. This guide shows how to generate a document and attach it to an email using popular email services.
Nodemailer
Nodemailer + Document Stack
import { DocumentStack } from "@document-stack/sdk-node";
import nodemailer from "nodemailer";
const ds = new DocumentStack({ apiKey: process.env.DS_API_KEY! });
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
async function sendInvoiceEmail(customer: { name: string; email: string; amount: number }) {
// 1. Generate the PDF
const pdf = await ds.generate({
templateId: "tmpl_invoice",
data: { customerName: customer.name, amount: customer.amount },
});
// 2. Download the PDF content
const pdfResponse = await fetch(pdf.url);
const pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
// 3. Send the email with attachment
await transporter.sendMail({
from: "billing@acmecorp.com",
to: customer.email,
subject: "Your Invoice from Acme Corp",
html: "<p>Hi " + customer.name + ",</p><p>Please find your invoice attached.</p>",
attachments: [
{
filename: "invoice.pdf",
content: pdfBuffer,
contentType: "application/pdf",
},
],
});
}SendGrid
SendGrid
import sgMail from "@sendgrid/mail";
sgMail.setApiKey(process.env.SENDGRID_API_KEY!);
async function sendWithSendGrid(email: string, pdfUrl: string) {
const pdfResponse = await fetch(pdfUrl);
const pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
await sgMail.send({
to: email,
from: "billing@acmecorp.com",
subject: "Your Invoice",
html: "<p>Your invoice is attached.</p>",
attachments: [
{
filename: "invoice.pdf",
content: pdfBuffer.toString("base64"),
type: "application/pdf",
disposition: "attachment",
},
],
});
}Resend
Resend
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);
async function sendWithResend(email: string, pdfUrl: string) {
const pdfResponse = await fetch(pdfUrl);
const pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
await resend.emails.send({
from: "billing@acmecorp.com",
to: email,
subject: "Your Invoice",
html: "<p>Your invoice is attached.</p>",
attachments: [
{
filename: "invoice.pdf",
content: pdfBuffer,
},
],
});
}URL vs Attachment
For large PDFs or when attachment size is a concern, consider including a download link in the email body instead of attaching the file directly.Python Example
Python + SMTP
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
import httpx
from document_stack import DocumentStack
ds = DocumentStack(api_key=os.environ["DS_API_KEY"])
def send_invoice_email(customer_email, customer_name, amount):
pdf = ds.generate(
template_id="tmpl_invoice",
data={"customerName": customer_name, "amount": amount},
)
pdf_content = httpx.get(pdf.url).content
msg = MIMEMultipart()
msg["From"] = "billing@acmecorp.com"
msg["To"] = customer_email
msg["Subject"] = "Your Invoice"
attachment = MIMEApplication(pdf_content, _subtype="pdf")
attachment.add_header("Content-Disposition", "attachment", filename="invoice.pdf")
msg.attach(attachment)
with smtplib.SMTP("smtp.gmail.com", 587) as server:
server.starttls()
server.login(os.environ["SMTP_USER"], os.environ["SMTP_PASS"])
server.send_message(msg)Next Steps
- Batch Generation — Send emails in bulk
- Scheduled Generation — Automate recurring emails
- Cloud Storage — Store PDFs in S3/GCS