CSV mail merge
Turn a template and CSV rows into one personalized message per row.
CSV mail merge
Write a message template once, drop your CSV rows into the second panel, and this tool produces one personalized message per row. Mark the parts that change with a placeholder — {{first_name}}, {{company}}, {{amount_due}} — and every row's own values are substituted in on generation. It supports three placeholder styles: {{column}}, {column} and $column, so you can match whatever your source template already uses.
The CSV side reads your header row as column names by default, so placeholders line up with the sheet. No header row is fine too — columns are then referenced positionally as Column 1, Column 2 and so on. Delimiters are auto-detected, or force comma, semicolon, tab or pipe. An empty cell can take a fallback value, or the whole row can be skipped when "Skip rows with a missing value" is on — handy when a message can't go out without that field. A case option can capitalize, uppercase or lowercase each substituted value without touching the surrounding text, and cell whitespace is trimmed by default.
Between messages you choose the separator — a blank line for a scrollable list, or a single newline for piping the result elsewhere. Numbering prefixes each message with its position, and the unused-columns warning catches CSV columns the template never references and placeholders with no matching column — a quick way to spot a typo before sending a hundred messages with the wrong name in them.
Everything runs locally in your browser: your template and your CSV data — customer names, email addresses, order details — are never uploaded anywhere. Copy the finished messages, download them as a .txt file, or send the output into another tool to keep processing it.