# Mail Merge from Google Sheets to Gmail with n8n

> Mail merge from Google Sheets to Gmail with n8n: one personalized email per row, with a filter, safe test sends and the settings that matter.

Source: https://learn.ynteractive.com/content/blog/mail-merge-google-sheets-gmail · Updated 2026-10-01 · Free from Stepthrough (https://learn.ynteractive.com)

By [Robert Breen](https://learn.ynteractive.com/content/about) · Published October 1, 2026 · Updated October 1, 2026 · 6 min read

n8n · Gmail · Google Sheets

A [mail merge](https://learn.ynteractive.com/content/glossary/merge-field) sends one personalized email per row of a spreadsheet, and n8n can do it from Google Sheets to Gmail with three steps: **Get row(s) in sheet**, a **Filter**, and **Gmail: Send a message** with expressions in the To, Subject and Message fields. This guide is for office staff who send the same kind of email to a list of people, like staff schedules or appointment notes, and you can practice the pattern free in the [Daily Job Alerts](https://learn.ynteractive.com/content/n8n-daily-job-alerts-google-sheets-gmail) lesson.

## What is a mail merge?

A mail merge is one email template filled in with different details for each row of a list. Each person gets their own email with their own name and details, instead of one group email to everyone.

In the [Daily Job Alerts](https://learn.ynteractive.com/content/n8n-daily-job-alerts-google-sheets-gmail) lesson, the list is a Google Sheet of today's jobs at Rapid Flow Plumbing, a made-up company, and each tech gets an email for each job assigned to them. The same pattern works for any list where each row should become its own email.

## How does n8n send one email per row?

An [n8n node](https://learn.ynteractive.com/content/glossary/node) runs once for every item it receives, and **Get row(s) in sheet** turns each spreadsheet row into one item. So one Gmail node sends one email per row, with no loop to set up.

The workflow has four nodes:

1. **A trigger** that starts it: **On a schedule** in the lesson (7am daily), or a manual start for a one-time send.
2. **Google Sheets: Get row(s) in sheet**, pointed at your spreadsheet and tab. Choose **Get row(s)**, which reads rows; **Append** would add rows instead.
3. **Filter**, which keeps only the rows that should get an email.
4. **Gmail: Send a message**, with expressions that fill in each row's details.

In the lesson's test, six rows come out of the sheet, five pass the Filter, and the Gmail node sends five emails. [Email Each Tech Their Jobs Every Morning with n8n](https://learn.ynteractive.com/content/blog/n8n-daily-job-emails-google-sheets) shows the full 7am build; this post focuses on what makes any mail merge work.

## How should you set up the sheet for a mail merge?

Put clear headers in row 1, one recipient per row, and a column with each person's email address. The headers become the names you use in [n8n expressions](https://learn.ynteractive.com/content/glossary/expression), so keep them short and stable.

The lesson's **Jobs** tab has Customer, Address, Job, Time, Tech and Tech Email columns. One detail is worth copying: **Tech Email** isn't typed by hand. It's looked up from a separate **Techs** tab, so the office types only a first name and the address fills in. That cuts down on typos in the one column that decides where each email goes.

If you'll rename a column later, remember that every expression using the old name will come back empty.

## How do you send each email to a different address?

Put an expression that points at the email column in the Gmail node's **To** field, not a typed address. In the lesson, it's:

```text
{{ $json["Tech Email"] }}
```

The column name has a space, so it goes in square brackets and quotes. A name without spaces can use a dot, like `{{ $json.Tech }}`. Underneath the field, n8n shows what the expression gives for the first row, so you can confirm it reads Dave's address before sending anything.

If you type one address in **To**, every email goes to that one person. [n8n Expressions for Beginners](https://learn.ynteractive.com/content/blog/n8n-expressions-for-beginners) explains `$json`, dots and brackets.

## How do you personalize the subject and message?

Use expressions in the **Subject** and **Message** fields the same way, pulling in each row's details. The lesson's subject is `{{ $json.Time }} job: {{ $json.Customer }}`, and the message is:

```text
Hi {{ $json.Tech }},

Job: {{ $json.Job }}
Address: {{ $json.Address }}
Time: {{ $json.Time }}
Customer: {{ $json.Customer }}
```

Two settings make the result read like a normal email:

- **Email Type:** change it from HTML to **Text**. Plain text is simpler and reads fine on a phone.
- **Append n8n Attribution:** click **Add option**, choose **Append n8n Attribution** and switch it off. Otherwise n8n adds a line saying the email was sent with n8n.

## Try it free, step by step

**Daily Job Alerts: Email Each Tech Their Jobs from Google Sheets with n8n**. Every morning at 7, n8n reads a plumbing company's jobs sheet, skips anything not assigned yet, and emails each job to the tech it's assigned to — customer, address, time and what's wrong. No AI… You do every step yourself in a practice copy of n8n, it checks your work as you go, and “Do it for me” finishes any step you get stuck on. Free, and nothing touches your real accounts.

[Start the free lesson](https://learn.ynteractive.com/modules/job-alerts)

[Or read the full step-by-step guide](https://learn.ynteractive.com/content/n8n-daily-job-alerts-google-sheets-gmail)

## How do you skip rows that shouldn't get an email?

Add a **Filter** node between the sheet and Gmail with a condition that only the right rows pass. In the lesson, the condition is `{{ $json.Tech }}` **is not empty**, so the one job with no tech is dropped instead of emailed to nobody.

You can use the same idea for other rules. A column like **Send** or **Status** lets someone mark which rows go out today, and the Filter keeps only those. The Filter shows its counts after a test, such as six in and five out, so you can see what was dropped.

## How do you test a mail merge without emailing real people?

Send the first run to yourself. Make a copy of the sheet, or a test tab, where every email column holds your own address, point the workflow at it, and run it.

Then use n8n's own checks:

1. **Test step** on the Google Sheets node to see the rows as items, with column names as labels.
2. **Test step** on the Filter to confirm how many rows pass.
3. **Test workflow** to run the whole thing, then open your Gmail **Sent** folder and read a couple of the emails.

In the lesson, the Sent folder shows five emails, two to Dave, two to Luis and one to Tasha, each with its own job. Once the test emails look right, point the workflow back at the real sheet. If it runs on a schedule, click **Publish** to turn it on.

## Should you run a mail merge once or on a schedule?

Run it on a schedule when the list changes every day and should go out at the same time, like the lesson's 7am job emails. Use a manual start for a one-time send, so it only runs when you choose.

A scheduled merge sends every row that passes the Filter, every time it runs. The lesson's advice applies to any repeating merge: keep the sheet to the rows that should go out today, or use a status column so yesterday's rows don't go out again. If you'd rather start from a ready-made workflow, the [Find and Use n8n Templates](https://learn.ynteractive.com/content/find-and-use-n8n-templates) lesson shows how to import one from the n8n gallery.

## When should you not use n8n for a mail merge?

Don't use a Gmail mail merge for marketing emails to a customer list. Marketing email usually needs consent and an easy way to unsubscribe, and email marketing tools are built for that. Check the rules that apply to you; this isn't legal advice.

Gmail also has daily sending limits, so a large list can hit them. An n8n Gmail mail merge fits best for operational emails to people who expect them: your staff, your crews, or customers about their own appointment or order. More n8n lessons are on the [n8n tool page](https://learn.ynteractive.com/content/tool/n8n).

## Key takeaways

- A mail merge sends one personalized email per spreadsheet row, and n8n does it with Get row(s) in sheet, a Filter and Gmail: Send a message.
- An n8n node runs once per item, so one Gmail node sends a separate email for each row that passes the Filter.
- The Gmail To field should hold an expression like `{{ $json["Tech Email"] }}`, not a typed address.
- Set Email Type to Text and turn off Append n8n Attribution so the emails read like normal messages.
- Test the merge by sending to your own address first, check the Sent folder, and avoid using a Gmail merge for marketing lists.

## Frequently asked questions

**Can n8n do a mail merge from Google Sheets?**

Yes. Read the rows with Google Sheets: Get row(s) in sheet, filter them, and send with Gmail: Send a message using expressions for the address, subject and message.

**Why did every email go to the same person?**

The To field probably has a typed address instead of an expression. Use an expression that points at your email column, like `{{ $json["Tech Email"] }}`.

**How do I remove "sent with n8n" from the emails?**

In the Gmail node, click Add option, choose Append n8n Attribution and switch it off.

**Does this mail merge use AI?**

No. It reads the sheet, filters rows and fills in the template with expressions. There's no AI step and no OpenAI cost.

## Free lessons in this post

- [Daily Job Alerts: Email Each Tech Their Jobs from Google Sheets with n8n](https://learn.ynteractive.com/content/n8n-daily-job-alerts-google-sheets-gmail): Every morning at 7, n8n reads a plumbing company's jobs sheet, skips anything not assigned yet, and emails each job to the tech it's assigned to — customer, address…
- [Find and Use n8n Templates](https://learn.ynteractive.com/content/find-and-use-n8n-templates): Skip the blank canvas. Find a ready-made workflow in the n8n template gallery, import it into your workspace, connect Google Sheets and Gmail, test it with a real form…

## Related terms

Plain-English definitions, each with an example from a free lesson.

[Merge field](https://learn.ynteractive.com/content/glossary/merge-field) · [Node](https://learn.ynteractive.com/content/glossary/node) · [Expression](https://learn.ynteractive.com/content/glossary/expression) · [Automation](https://learn.ynteractive.com/content/glossary/automation) · [Autoresponder](https://learn.ynteractive.com/content/glossary/autoresponder) · [Dispatching](https://learn.ynteractive.com/content/glossary/dispatching) · [Filter node](https://learn.ynteractive.com/content/glossary/filter-node) · [Get rows (reading a sheet)](https://learn.ynteractive.com/content/glossary/get-rows)

[The full AI glossary](https://learn.ynteractive.com/content/glossary)

## Related prompts

- [Appointment reminder text prompt](https://learn.ynteractive.com/content/prompts/appointment-reminder-text-prompt): Write day-before reminder texts for each job on tomorrow's schedule: the time window, who's coming, one prep step and an easy…
- [Automation candidates prompt](https://learn.ynteractive.com/content/prompts/automation-candidates-prompt): Rank your repetitive tasks by which to automate first, using only your own counts and minutes, with a first workflow sketched…
- [Automation time savings estimate prompt](https://learn.ynteractive.com/content/prompts/automation-time-savings-estimate-prompt): Estimate what one automation saves from your own numbers only: minutes before and after, setup and upkeep, costs you look up…
- [Customer intake form questions prompt](https://learn.ynteractive.com/content/prompts/customer-intake-form-questions-prompt): Design the questions for a booking or intake form: only what you need to do the job, each with a field type, help text and a…

[All free prompt templates](https://learn.ynteractive.com/content/prompts)

## Visual guides

The same ideas as quick visual guides: swipe through the slides, or read each one as text.

- [5 Steps to Find, Import and Run an n8n Template](https://learn.ynteractive.com/content/visual/5-steps-use-an-n8n-template): A visual guide: find an n8n template, import it, connect your own Google Sheets and Gmail accounts, make it yours and run a test.
- [Mistake to Avoid: Scheduling Before Setting the Timezone](https://learn.ynteractive.com/content/visual/mistake-scheduling-before-the-timezone): A visual tip for n8n schedules: set the workflow timezone before the schedule, so 7am means 7am where your business is.
- [Mistake to Avoid: Sending Every Job Email to One Address](https://learn.ynteractive.com/content/visual/mistake-one-address-for-every-job): A visual tip for n8n and Gmail: make the To field an expression for the Tech Email column, written in square brackets because of the space.

[All visual guides](https://learn.ynteractive.com/content/visual)

## Keep reading

- [Email Each Tech Their Jobs Every Morning with n8n](https://learn.ynteractive.com/content/blog/n8n-daily-job-emails-google-sheets): n8n Google Sheets to Gmail, step by step: at 7am, read today's jobs, skip unassigned ones and email each job to its tech. Plus the timezone trap.
- [AI for Lawn Care Businesses: 3 Off-Season Projects](https://learn.ynteractive.com/content/blog/ai-for-lawn-care-business): AI for lawn care and landscaping owners: three off-season projects, from ChatGPT customer emails to morning crew job emails and an online estimate form.
- [n8n Triggers Explained: Which One Starts Your Workflow?](https://learn.ynteractive.com/content/blog/n8n-triggers-explained): n8n triggers explained: schedule, Gmail, chat, webhook and form triggers, how to test each one, and how the trigger changes your AI Agent's prompt.

[All blog posts](https://learn.ynteractive.com/content/blog) · [All free tutorials](https://learn.ynteractive.com/content)
