Document Stack
Document Stack
Docs

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