Generating Attachments
Learn how FormaMail automatically generates PDF and Excel attachments from templates when sending emails.
Overview
FormaMail can automatically generate PDF invoices, reports, and Excel spreadsheets from templates and attach them to your emails. Attachments are generated dynamically using variables you provide when sending emails.
Important: Attachment templates are created and configured exclusively in the Dashboard. When you send an email via API, FormaMail automatically generates the attachments based on your template configuration.
How Attachment Generation Works
1. Create Attachment Template (Dashboard)
All attachment template design happens in the dashboard:
- Navigate to Templates → Attachment Templates
- Create a PDF or Excel template
- Design the layout using visual components
- Define variables for dynamic content
- Configure attachment settings
See the Attachment Templates User Guide for detailed instructions.
2. Send Email with Attachment (API)
When you send an email that references an attachment template, FormaMail:
- Receives your API request
- Validates the template and variables
- Generates the attachment (PDF/Excel)
- Attaches the file to the email
- Sends the email with attachment
const response = await fetch('https://api.formamail.com/api/emails/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'tmpl_invoice_email', // Email template with attachment reference
to: [{ email: 'customer@example.com', name: 'John Doe' }],
variables: {
invoiceNumber: 'INV-12345',
customer: {
name: 'John Doe',
company: 'Acme Corp'
},
items: [
{ name: 'Product A', quantity: 2, price: 49.99 },
{ name: 'Product B', quantity: 1, price: 29.99 }
],
total: 129.97
}
})
});Attachment Types
FormaMail supports two types of dynamically generated attachments:
PDF Attachments
Generate professional PDF documents:
- Invoices: Itemized invoices with calculations
- Reports: Business reports with charts and tables
- Certificates: Completion certificates
- Tickets: Event tickets with QR codes
- Receipts: Payment receipts
Features:
- Custom branding and styling
- Charts and graphs
- Tables with calculations
- Headers and footers
- Page breaks
- Custom fonts
Excel Attachments
Generate Excel spreadsheets:
- Data exports: Tabular data export
- Reports: Financial reports with calculated columns
- Invoices: Editable invoices
- Statements: Account statements
- Logs: Activity logs
Features:
- Multiple worksheets
- Calculated columns (JavaScript expressions)
- Cell styling and formatting
- Charts and graphs
- Data validation
- Conditional formatting
Configuring Attachments in Templates
Email Template with Attachment
When creating an email template in the dashboard, you can configure it to include attachments:
- Create or edit an email template
- In the template settings, add attachment reference
- Select the attachment template to use
- Configure attachment filename pattern
- Save and publish
Example Configuration (Dashboard)
Email Template: “Invoice Email”
- Template ID:
tmpl_invoice_email - Subject:
Invoice {{invoiceNumber}} - Attachments:
- PDF Template:
tmpl_invoice_pdf - Filename:
Invoice-{{invoiceNumber}}.pdf
- PDF Template:
API Usage:
// Sending email automatically generates PDF
{
templateId: 'tmpl_invoice_email',
to: [{ email: 'customer@example.com' }],
variables: {
invoiceNumber: 'INV-12345',
// ... other variables
}
}
// Result: Email sent with "Invoice-INV-12345.pdf" attachedVariables in Attachments
Attachments support variable inheritance from email variables, making your API calls simpler:
How Variable Inheritance Works
- Email variables (from the
variablesfield) are automatically available to all attachments - Attachment-specific variables (from
attachments[].variables) can override or extend inherited values - Priority: Attachment-specific variables override email variables with the same name
This means you don’t need to duplicate variables - provide them once at the email level!
Simple Example
API Request:
{
templateId: 'tmpl_receipt_email',
to: [{ email: 'customer@example.com' }],
variables: {
receiptNumber: 'RCP-789',
date: '2025-11-07',
amount: 99.99,
paymentMethod: 'Credit Card'
}
}Generated PDF contains:
- Receipt Number: RCP-789
- Date: November 7, 2025
- Amount: $99.99
- Payment Method: Credit Card
Complex Data Example
For invoices with line items:
{
templateId: 'tmpl_invoice_email',
to: [{ email: 'customer@example.com' }],
variables: {
invoiceNumber: 'INV-12345',
issueDate: '2025-11-07',
dueDate: '2025-12-07',
customer: {
name: 'John Doe',
company: 'Acme Corp',
email: 'john@acme.com',
address: '123 Main St, City, ST 12345'
},
items: [
{
description: 'Professional Services',
quantity: 10,
rate: 150.00,
amount: 1500.00
},
{
description: 'Consulting Fee',
quantity: 5,
rate: 200.00,
amount: 1000.00
}
],
subtotal: 2500.00,
tax: 250.00,
total: 2750.00
}
}Charts in Attachments
Attachment templates can include charts for visual data representation:
Supported Chart Types
- Bar Chart: Compare values across categories
- Line Chart: Show trends over time
- Pie Chart: Show proportions
- Area Chart: Show cumulative trends
- Scatter Chart: Show correlations
Example with Charts
Sales Report with Chart:
{
templateId: 'tmpl_sales_report',
to: [{ email: 'manager@company.com' }],
variables: {
reportMonth: 'October 2025',
salesByRegion: [
{ region: 'North', sales: 125000 },
{ region: 'South', sales: 98000 },
{ region: 'East', sales: 156000 },
{ region: 'West', sales: 142000 }
],
monthlySales: [
{ month: 'July', sales: 98000 },
{ month: 'August', sales: 112000 },
{ month: 'September', sales: 135000 },
{ month: 'October', sales: 156000 }
],
totalSales: 521000
}
}The attachment template (configured in dashboard) renders:
- Bar chart showing sales by region
- Line chart showing monthly trend
- Summary table with totals
Calculated Columns
Attachments support calculated columns using JavaScript expressions. These work identically for both PDF and Excel outputs.
Configuration (Dashboard)
When creating an attachment template in the dashboard:
- Add table components
- Enable “Calculated Column” for computed values
- Write JavaScript expressions (e.g.,
row.quantity * row.price) - Expressions are evaluated when the attachment is generated
Example: Invoice with Calculations
API Request:
{
templateId: 'tmpl_invoice',
to: [{ email: 'customer@example.com' }],
variables: {
invoiceNumber: 'INV-12345',
items: [
{ description: 'Item A', quantity: 2, price: 49.99 },
{ description: 'Item B', quantity: 1, price: 29.99 },
{ description: 'Item C', quantity: 3, price: 19.99 }
]
}
}Generated Attachment contains:
- Description column (field:
description) - Quantity column (field:
quantity) - Price column (field:
price, formatted as currency) - Amount column (calculated:
row.quantity * row.price)
Attachment File Names
Control attachment filenames using template variables:
Static Filename (Dashboard Configuration)
Invoice.pdfDynamic Filename (Dashboard Configuration)
Invoice-{{invoiceNumber}}.pdf
Report-{{month}}-{{year}}.xlsx
Receipt-{{date}}.pdfAPI Usage:
{
templateId: 'tmpl_invoice_email',
to: [{ email: 'customer@example.com' }],
variables: {
invoiceNumber: 'INV-12345'
}
}
// Generated filename: "Invoice-INV-12345.pdf"Multiple Attachments
Email templates can be configured to generate multiple attachments:
Dashboard Configuration
Email Template Settings:
- Attachment 1: Invoice PDF (
tmpl_invoice_pdf) - Attachment 2: Detailed Report Excel (
tmpl_detailed_report_excel)
API Usage:
{
templateId: 'tmpl_invoice_with_report',
to: [{ email: 'customer@example.com' }],
variables: {
invoiceNumber: 'INV-12345',
// Email template variables
},
attachments: [
{
attachmentTemplateId: 'tmpl_invoice_pdf',
variables: { /* Override or provide attachment-specific variables */ }
},
{
attachmentTemplateId: 'tmpl_detailed_report_excel',
variables: { /* Override or provide attachment-specific variables */ }
}
]
}
// Result: Email with both Invoice.pdf and Report.xlsx attachedAttachment Generation Status
Successful Generation
{
"id": "email_abc123",
"status": "sent",
"attachments": [
{
"id": "attach_xyz789",
"filename": "Invoice-INV-12345.pdf",
"size": 45678,
"contentType": "application/pdf",
"status": "completed"
}
]
}Generation Failed
{
"statusCode": 500,
"code": "ERR_ATTACH_001",
"message": "Attachment generation failed",
"relatedInfo": {
"templateId": "tmpl_invoice_pdf",
"error": "Invalid chart data format"
}
}Attachment Errors
Missing Required Data
If attachment template requires data not provided:
{
"statusCode": 400,
"code": "ERR_TMPL_004",
"message": "Missing required template variable",
"relatedInfo": {
"variable": "items",
"templateId": "tmpl_invoice_pdf"
}
}Solution: Provide all required variables for both email and attachment templates.
Invalid Data Format
If data doesn’t match expected format:
{
"statusCode": 400,
"code": "ERR_ATTACH_002",
"message": "Invalid attachment data format",
"relatedInfo": {
"field": "items",
"expected": "array",
"received": "string"
}
}Solution: Ensure data types match template expectations (arrays for tables, objects for nested data, etc.).
Best Practices
1. Use Meaningful Variable Names
âś… Good:
{
variables: {
invoiceNumber: 'INV-12345',
lineItems: [...],
customerDetails: {...}
}
}❌ Bad:
{
variables: {
inv: 'INV-12345',
items: [...],
cust: {...}
}
}2. Validate Data Before Sending
function validateInvoiceData(data) {
if (!data.invoiceNumber) {
throw new Error('Invoice number required');
}
if (!Array.isArray(data.items) || data.items.length === 0) {
throw new Error('Invoice must have at least one item');
}
if (typeof data.total !== 'number') {
throw new Error('Total must be a number');
}
return true;
}
// Use it
validateInvoiceData(invoiceData);
await sendEmail({
templateId: 'tmpl_invoice_email',
to: [{ email: customer.email }],
variables: invoiceData
});3. Test Attachments with Real Data
Always test attachments with production-like data:
const testData = {
invoiceNumber: 'TEST-001',
customer: {
name: 'Test Customer',
company: 'Test Corp',
email: 'test@example.com'
},
items: [
{ description: 'Test Product A', quantity: 2, price: 49.99 },
{ description: 'Test Product B', quantity: 1, price: 29.99 }
],
total: 129.97
};
// Send test email
await sendEmail({
templateId: 'tmpl_invoice_email',
to: [{ email: 'test@yourdomain.com' }],
variables: testData
});4. Handle Large Attachments
Be mindful of attachment sizes:
- Keep PDFs under 5MB
- Limit Excel rows to reasonable amounts (< 10,000 rows)
- Optimize images in PDFs
- Consider pagination for large reports
5. Use Descriptive Filenames
Include relevant information in filenames:
// Good filenames
Invoice-{{invoiceNumber}}-{{date}}.pdf
Report-{{month}}-{{year}}.xlsx
Receipt-{{transactionId}}.pdf
// Examples:
// Invoice-INV-12345-2025-11-07.pdf
// Report-October-2025.xlsx
// Receipt-TXN-789.pdfCommon Use Cases
Invoice with PDF
{
templateId: 'tmpl_invoice_email',
to: [{ email: 'customer@example.com' }],
variables: {
invoiceNumber: 'INV-12345',
issueDate: '2025-11-07',
dueDate: '2025-12-07',
customer: {
name: 'John Doe',
company: 'Acme Corp'
},
items: [
{ description: 'Service A', quantity: 10, rate: 150, amount: 1500 },
{ description: 'Service B', quantity: 5, rate: 200, amount: 1000 }
],
subtotal: 2500,
tax: 250,
total: 2750
}
}Sales Report with Excel
{
templateId: 'tmpl_sales_report',
to: [{ email: 'manager@company.com' }],
variables: {
reportMonth: 'October 2025',
salesData: [
{ date: '2025-10-01', revenue: 5000, orders: 50 },
{ date: '2025-10-02', revenue: 6200, orders: 62 },
// ... more daily data
],
totalRevenue: 156000,
totalOrders: 1540
}
}Certificate with PDF
{
templateId: 'tmpl_certificate_email',
to: [{ email: 'student@example.com' }],
variables: {
studentName: 'John Doe',
courseName: 'Advanced JavaScript',
completionDate: '2025-11-07',
instructorName: 'Jane Smith',
certificateId: 'CERT-2025-12345'
}
}Performance Considerations
Generation Time
Attachment generation adds processing time:
- Simple PDF: 1-3 seconds
- PDF with charts: 3-5 seconds
- Excel with formulas: 2-4 seconds
- Large Excel (1000+ rows): 5-10 seconds
Optimization Tips
- Limit data size: Send only necessary data
- Use pagination: For large datasets, generate multiple reports
- Optimize images: Compress images before including in PDFs
- Cache templates: Templates are cached automatically
- Test performance: Monitor generation times with your data
Troubleshooting
Attachment Not Generated
Possible causes:
- Template not published in dashboard
- Missing required variables
- Invalid data format
- Template configuration error
Solution:
- Check template status in dashboard
- Verify all required variables are provided
- Validate data types match expectations
- Review error message in API response
Attachment Looks Wrong
Possible causes:
- Variable values not formatted correctly
- Template styling issues
- Missing data
Solution:
- Test template with same data in dashboard preview
- Check variable formatting (dates, currencies, etc.)
- Update template design in dashboard
Next Steps
- Create Attachment Templates: Learn how to design attachment templates in the Attachments User Guide
- Send Emails: See complete API documentation in Sending Emails
- Use Templates: Learn more about template variables in Working with Templates
Related: Sending Emails | Working with Templates | Attachments User Guide