Instead of fighting with the limited formatting options in n8n's email nodes, build your HTML in a Code node.
Instead of fighting with the limited formatting options in n8n's email nodes, build your HTML in a Code node. This gives you full control over styling, conditional sections, and dynamic table generation.
Real-world example: A daily sales report email that includes a summary header, a table of top deals, and conditional warning banners when targets are missed.
// Mode: Run Once for All Items
const deals = $input.all().map(i => i.json);
const totalRevenue = deals.reduce((s, d) => s + d.amount, 0);
const target = 50000;
const hitTarget = totalRevenue >= target;
const tableRows = deals
.sort((a, b) => b.amount - a.amount)
.slice(0, 10)
.map(d => `
<tr>
<td style="padding:8px;border-bottom:1px solid #ddd;">${d.dealName}</td>
<td style="padding:8px;border-bottom:1px solid #ddd;">${d.rep}</td>
<td style="padding:8px;border-bottom:1px solid #ddd;text-align:right;">
$${d.amount.toLocaleString()}
</td>
<td style="padding:8px;border-bottom:1px solid #ddd;">${d.stage}</td>
</tr>
`).join('');
const warningBanner = hitTarget ? '' : `
<div style="background:#c0392b;color:#fff;padding:12px;margin:16px 0;
border-radius:4px;text-align:center;">
Revenue is $${(target - totalRevenue).toLocaleString()} below daily target.
Review pipeline immediately.
`;
const html = `
<div style="font-family:Arial,sans-serif;max-width:680px;margin:0 auto;">
<h2 style="color:#2c3e50;">Daily Sales Report</h2>
<p>Report generated: ${new Date().toISOString().slice(0, 10)}</p>
${warningBanner}
<div style="background:#ecf0f1;padding:16px;border-radius:4px;margin:16px 0;">
<strong>Total Revenue:</strong> $${totalRevenue.toLocaleString()} /
$${target.toLocaleString()} target
(${((totalRevenue / target) * 100).toFixed(1)}%)
<h3>Top 10 Deals</h3>
<table style="width:100%;border-collapse:collapse;">
<thead>
<tr style="background:#34495e;color:#fff;">
<th style="padding:8px;text-align:left;">Deal</th>
<th style="padding:8px;text-align:left;">Rep</th>
<th style="padding:8px;text-align:right;">Amount</th>
<th style="padding:8px;text-align:left;">Stage</th>
</tr>
</thead>
<tbody>${tableRows}</tbody>
</table>
`;
return [{ json: { html, subject: `Sales Report - $${totalRevenue.toLocaleString()} ${hitTarget ? '(Target Met)' : '(Below Target)'}` } }];
```text
Feed the `html` output into the Send Email node's HTML body field and the `subject` into the subject line.
**Related:** [Use Edit Fields in "Map Each" Mode for Simple Renames](../data-transformation/01-use-edit-fields-in-map-each-mode-for-simple-renames.md) | [Configure Payload Size and Binary Data Mode for Large Files](../performance-and-large-files/01-configure-payload-size-and-binary-data-mode-for-large-files.md)
I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.