Invoice and receipt emails serve legal, accounting, and customer service purposes. Here's how to design them effectively.
Receipt vs invoice
- —Receipt: Confirms payment received
- —Invoice: Requests payment (may be pre-paid)
Both need similar information but serve different purposes.
Essential elements
Receipt email
interface ReceiptEmail {
customer: {
name: string;
email: string;
billingAddress?: Address;
};
transaction: {
id: string;
date: Date;
paymentMethod: string;
last4?: string;
};
items: Array<{
description: string;
quantity: number;
unitPrice: number;
total: number;
}>;
totals: {
subtotal: number;
tax: number;
discount?: number;
total: number;
currency: string;
};
business: {
name: string;
address: string;
taxId?: string;
};
}
await sendEmail({
to: customer.email,
subject: `Receipt for your purchase - $${totals.total}`,
template: 'receipt',
data: receipt,
attachments: [
{
filename: `receipt-${transaction.id}.pdf`,
content: await generateReceiptPDF(receipt)
}
]
});
Invoice email
interface InvoiceEmail {
customer: {
name: string;
email: string;
billingAddress: Address;
};
invoice: {
number: string;
issueDate: Date;
dueDate: Date;
status: 'draft' | 'sent' | 'paid' | 'overdue';
};
items: InvoiceItem[];
totals: {
subtotal: number;
tax: number;
total: number;
currency: string;
amountDue: number;
};
paymentOptions: PaymentOption[];
}
await sendEmail({
to: customer.email,
subject: `Invoice #${invoice.number} - $${totals.amountDue} due ${formatDate(invoice.dueDate)}`,
template: 'invoice',
data: invoiceData,
attachments: [
{
filename: `invoice-${invoice.number}.pdf`,
content: await generateInvoicePDF(invoiceData)
}
]
});
Payment reminders
Upcoming due date
const reminderSequence = [
{ daysBefore: 7, template: 'invoice-reminder-7d' },
{ daysBefore: 3, template: 'invoice-reminder-3d' },
{ daysBefore: 1, template: 'invoice-reminder-1d' },
{ daysAfter: 1, template: 'invoice-overdue-1d' },
{ daysAfter: 7, template: 'invoice-overdue-7d' }
];
async function sendInvoiceReminder(invoice: Invoice, reminder: Reminder) {
await sendEmail({
to: invoice.customer.email,
subject: reminder.daysBefore
? `Invoice #${invoice.number} due in ${reminder.daysBefore} days`
: `Invoice #${invoice.number} is overdue`,
template: reminder.template,
data: {
invoice,
payNowUrl: `${baseUrl}/invoices/${invoice.id}/pay`,
amountDue: invoice.amountDue
}
});
}
Formatting best practices
Currency display
function formatMoney(amount: number, currency: string, locale: string): string {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency
}).format(amount);
}
// $1,234.56 (en-US, USD)
// €1.234,56 (de-DE, EUR)
// ¥1,235 (ja-JP, JPY)
Line item table
<table>
<thead>
<tr>
<th>Description</th>
<th>Qty</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{this.description}}</td>
<td>{{this.quantity}}</td>
<td>{{formatMoney this.unitPrice}}</td>
<td>{{formatMoney this.total}}</td>
</tr>
{{/each}}
</tbody>
<tfoot>
<tr>
<td colspan="3">Subtotal</td>
<td>{{formatMoney totals.subtotal}}</td>
</tr>
<tr>
<td colspan="3">Tax</td>
<td>{{formatMoney totals.tax}}</td>
</tr>
<tr>
<td colspan="3"><strong>Total</strong></td>
<td><strong>{{formatMoney totals.total}}</strong></td>
</tr>
</tfoot>
</table>
Legal requirements
Required elements
const requiredReceiptElements = {
business: ['name', 'address', 'taxId'],
transaction: ['date', 'id', 'paymentMethod'],
items: ['description', 'quantity', 'price'],
totals: ['subtotal', 'tax', 'total']
};
// Validate before sending
function validateReceipt(receipt: ReceiptEmail): boolean {
// Check all required fields present
for (const [section, fields] of Object.entries(requiredReceiptElements)) {
for (const field of fields) {
if (!receipt[section]?.[field]) {
throw new Error(`Missing required field: ${section}.${field}`);
}
}
}
return true;
}
Best practices
- —Attach PDF - Customers need printable records
- —Clear totals - Break down subtotal, tax, discounts
- —Payment info - Show how they paid or how to pay
- —Business details - Legal name, address, tax ID
- —Unique identifiers - Invoice/receipt numbers for reference
- —Mobile-friendly - Tables that work on small screens
Invoice and receipt emails are legal documents. Get them right and you'll reduce accounting questions and build trust.