KEEP LEARNING
Build the bigger picture.
The Workflow Engineer connects individual n8n concepts to testing, deployment and running a complete workflow.
Tips > Building Workflows
Instead of fighting with the limited formatting options in n8n's email nodes, build your HTML in a Code node.
Instead of fighting the limited formatting in n8n's email nodes, build your HTML in a Code node. This gives full control over styling, conditional sections, and dynamically generated tables. Compute your values, assemble an HTML string with template literals, and feed the result into the Send Email node's HTML body field alongside a generated subject line.
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)'}` } }];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 · Configure Payload Size and Binary Data Mode for Large Files
KEEP LEARNING
The Workflow Engineer connects individual n8n concepts to testing, deployment and running a complete workflow.
APPLY IT TO YOUR SYSTEM
Bring the process, the tools involved and an example of where the current workflow gets stuck.