Google Sheets + Gmail: newsletters sent only when approved
You wrote the newsletter. You double-checked the links. Then someone sends the wrong version anyway, or hits “send” before the client signs off. It’s the kind of mistake that feels small until it isn’t.
This Sheets Gmail approval automation hits marketing managers first, but agency teams and solo operators feel it too. You get a simple control system: drafts are generated and stored, and only rows marked “Approved” actually send.
Below, you’ll see how the workflow works, what it replaces, and how to put it into production without turning your newsletter process into another “project.”
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Google Sheets + Gmail: newsletters sent only when approved
flowchart LR
subgraph sg0["When clicking 'Test workflow' Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking 'Test workflow'", pos: "b", h: 48 }
n3@{ icon: "mdi:database", form: "rounded", label: "Get topic from newsletter sh..", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Validate Status as Pending", pos: "b", h: 48 }
n5@{ icon: "mdi:robot", form: "rounded", label: "Create HTML for Newsletter", pos: "b", h: 48 }
n6["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Prepare Data to create word .."]
n7@{ icon: "mdi:cog", form: "rounded", label: "Upload doc to google drive", pos: "b", h: 48 }
n8@{ icon: "mdi:message-outline", form: "rounded", label: "Send an email to admin", pos: "b", h: 48 }
n9@{ icon: "mdi:database", form: "rounded", label: "Update Status as Generated", pos: "b", h: 48 }
n8 --> n9
n5 --> n6
n7 --> n8
n4 --> n5
n0 --> n3
n3 --> n4
n6 --> n7
end
subgraph sg1["Schedule Flow"]
direction LR
n1@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Validate Status as Approved", pos: "b", h: 48 }
n11@{ icon: "mdi:database", form: "rounded", label: "Pick records to send email t..", pos: "b", h: 48 }
n12@{ icon: "mdi:database", form: "rounded", label: "Get Client email address", pos: "b", h: 48 }
n13@{ icon: "mdi:message-outline", form: "rounded", label: "Send email to client", pos: "b", h: 48 }
n14@{ icon: "mdi:database", form: "rounded", label: "Update status as Sent", pos: "b", h: 48 }
n2 --> n14
n2 --> n13
n1 --> n11
n13 --> n2
n12 --> n2
n10 --> n12
n11 --> n10
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n0,n1 trigger
class n5 ai
class n4,n10 decision
class n3,n9,n11,n12,n14 database
class n6 code
classDef customIcon fill:none,stroke:none
class n6 customIcon
The Problem: Newsletters Ship Before They’re Truly Ready
Newsletter operations usually start simple: a spreadsheet of topics, a doc somewhere, and a “we’ll remember” approval step. Then real life shows up. You’re juggling multiple clients, last-minute edits, and “can we send it today?” messages. The weak point is always the same: there’s no single source of truth that decides what gets sent and what stays parked. So drafts get emailed early, the wrong audience gets the wrong version, and you spend your morning doing cleanup instead of planning the next campaign.
It adds up fast. Here’s where it breaks down in most teams.
- Approval lives in someone’s inbox, so the sending step turns into guesswork.
- Draft files end up scattered in Drive, which makes “final” hard to define.
- Manual copying of subject lines and HTML leads to tiny errors that look sloppy in production.
- When you manage multiple clients, you risk sending Client A’s content to Client B.
The Solution: Google Sheets Runs the Entire Approval-to-Send Pipeline
This workflow turns one Google Sheet into your newsletter command center. You add topics as “Pending,” then run a manual generation flow that creates AI-written HTML for each topic and stores it in Google Drive for review. The system updates the row so everyone can see the draft is “Generated,” and it sends an admin notification so nothing gets lost. Separately, a schedule checks your sheet for rows marked “Approved.” Only those rows move forward. n8n pulls the client email, sends the newsletter through Gmail, then marks the row “Sent” so you have a clean audit trail and you don’t send duplicates.
The workflow starts with either a manual run (to generate content from Pending rows) or a timed schedule (to distribute only Approved rows). In the middle, OpenAI generates newsletter HTML, Google Drive stores the file, and Gmail handles both admin alerts and client delivery. At the end, Google Sheets updates every status so your spreadsheet always matches reality.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you manage 10 client newsletters a week. Manually, you might spend about 20 minutes generating content, 10 minutes saving and organizing files, and 10 minutes prepping the send per client. That’s roughly 40 minutes each, or about 7 hours weekly. With this workflow, you drop topics into Sheets, run the generation, and you’re mostly waiting on processing (about 5 minutes per newsletter). When rows flip to “Approved,” scheduled sending handles delivery automatically. You get most of that 7 hours back, and approvals stop getting skipped.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets to store topics, statuses, and send dates.
- Gmail to send admin notifications and client emails.
- OpenAI API key (get it from your OpenAI dashboard).
Skill level: Intermediate. You’ll connect accounts, map a few fields, and tweak an AI prompt without writing “real code.”
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A manual run generates drafts from “Pending.” You trigger the workflow when you’re ready to create newsletters, and it pulls the queued topics from your Google Sheet. If a row isn’t truly Pending (or the date rules don’t match), it gets skipped.
AI creates newsletter HTML, then it’s packaged for storage. OpenAI produces the draft content in HTML, and a small formatting step prepares it so it can be saved cleanly as a document.
Google Drive stores the draft, and the sheet becomes your tracker. The workflow uploads the file to Drive, emails the admin that it’s ready, and updates the Google Sheets status to “Generated” so review can happen without confusion.
A scheduled run sends only “Approved.” On a timer, n8n searches for rows marked Approved, looks up the client email, loops through recipients, and sends the newsletter via Gmail. Once sent, it marks the row “Sent.” Done.
You can easily modify the approval rules to include a “Needs edits” state or a second reviewer based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Trigger Nodes
Set up both manual and scheduled entry points so you can run the newsletter generation on demand or automatically.
- Open Manual Run Initiator to enable manual test runs in the editor.
- Open Timed Schedule Trigger and configure your schedule rule (e.g., daily or weekly) in the rule settings.
- Confirm that Manual Run Initiator connects to Fetch Newsletter Topics, and Timed Schedule Trigger connects to Retrieve Approved Records as shown in the workflow.
Step 2: Connect Google Sheets
These nodes read newsletter topics, approvals, client emails, and update statuses. Connect Google Sheets once and reuse it across all Sheets nodes.
- Open Fetch Newsletter Topics and confirm the documentId is
[YOUR_ID]and sheetName isgid=0. The filter should match Status =Pending. - Open Retrieve Approved Records and ensure the documentId is
[YOUR_ID]and sheetName isgid=0. - Open Lookup Client Emails and set sheetName to the client list sheet id
[YOUR_ID]. - Open Mark as Generated and confirm it updates Status to
Generatedand maps fields like Date to{{ $('Fetch Newsletter Topics').item.json.Date }}. - Open Mark as Sent and confirm it updates Status to
Sentand matches on Date. - Credential Required: Connect your googleSheetsOAuth2Api credentials to all Google Sheets nodes (5 total: Fetch Newsletter Topics, Retrieve Approved Records, Lookup Client Emails, Mark as Generated, Mark as Sent).
Step 3: Set Up the Date and Approval Filters
These checks ensure only today’s pending topics are generated and only approved newsletters are sent.
- In Check Pending Date, verify the condition compares
{{ $json.Date }}to{{ new Date().toLocaleDateString('en-US') }}. - In Confirm Approved Status, ensure the condition checks
{{ $json.Status }}equalsApproved. - Confirm the flow: Fetch Newsletter Topics → Check Pending Date → Generate Newsletter HTML, and Retrieve Approved Records → Confirm Approved Status → Lookup Client Emails.
Step 4: Set Up the AI and HTML File Generation
Generate the newsletter content with AI and format it into an HTML file for Google Drive.
- Open Generate Newsletter HTML and set the model to
gpt-4o. - In Generate Newsletter HTML, confirm the prompt includes
{{ $json.Topic }}and{{ $json.hooks }}in the message content. - Credential Required: Connect your openAiApi credentials in Generate Newsletter HTML.
- Open Format HTML for Drive and keep the jsCode block as-is to generate a binary HTML file and filename based on the current date.
- Confirm the flow: Generate Newsletter HTML → Format HTML for Drive → Upload File to Drive.
Step 5: Configure Drive Upload and Admin Review Email
Store the generated HTML in Drive and notify an admin for review before sending to clients.
- In Upload File to Drive, set name to
=newsletter-{{ $('Fetch Newsletter Topics').item.json.Date }}.html. - Set driveId to
My Driveand folderId to[YOUR_ID]. - Set inputDataFieldName to
=data. - Credential Required: Connect your googleDriveOAuth2Api credentials in Upload File to Drive.
- In Notify Admin via Email, set sendTo to
[YOUR_EMAIL]and verify message is=Review the attached newsletter {{ $json.webViewLink }}. - Set subject to
=Newsletter Preview for {{ $('Fetch Newsletter Topics').item.json.Date }} and HTML body attachedand emailType totext. - Credential Required: Connect your gmailOAuth2 credentials in Notify Admin via Email.
- Confirm the flow: Upload File to Drive → Notify Admin via Email → Mark as Generated.
[YOUR_ID].Step 6: Configure Client Delivery and Status Updates
This section dispatches the approved newsletter to each client and marks records as sent.
- In Dispatch Client Email, set sendTo to
{{ $json.Email }}. - Set message to
=Attached is the newsletter {{ $('Retrieve Approved Records').item.json['Document URL'] }}and emailType totext. - Credential Required: Connect your gmailOAuth2 credentials in Dispatch Client Email.
- Verify the batching flow: Lookup Client Emails → Batch Iterator → Dispatch Client Email → Batch Iterator → Mark as Sent.
Step 7: Test and Activate Your Workflow
Validate both the manual generation path and the scheduled delivery path before turning the workflow on.
- Click Execute Workflow using Manual Run Initiator and confirm a newsletter HTML file is created in Drive.
- Check Notify Admin via Email to verify the admin email includes a
webViewLinkto the uploaded file. - Run a test on the scheduled path by temporarily triggering Timed Schedule Trigger, then verify that Dispatch Client Email sends to addresses from Lookup Client Emails.
- Confirm Mark as Generated and Mark as Sent update the Google Sheet with
GeneratedandSentstatuses. - Once validated, toggle the workflow to Active to run automatically on schedule.
Common Gotchas
- Google Sheets permissions can block updates even when reads work. If status changes fail, check the Google connection and sharing settings on the spreadsheet first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- OpenAI prompts that are too generic create bland newsletters. Add your brand voice, target audience, and “what to avoid” early, or you will be rewriting every draft.
Frequently Asked Questions
About 45 minutes if your Google accounts and sheet are ready.
No. You’ll mostly connect apps and map columns to fields. The “code” step is included and usually doesn’t need edits.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenAI API costs (often just a few dollars a month at low volume).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, but keep it simple. Add a second status like “Review” or “Client Approved,” then adjust the “Confirm Approved Status” check so only the final state sends. Many teams also add an extra admin notification after “Mark as Generated” so reviewers get pinged immediately.
Usually it’s the Google authentication scope or a spreadsheet permission mismatch. Reconnect the Google account in n8n, then confirm that same account can edit the exact file (not a copy) and the right sheet/tab names haven’t changed. If you renamed columns, check the node mappings too because n8n can’t update a field it can’t find.
It can handle 100+ clients without breaking a sweat, as long as your Google and OpenAI rate limits are respected.
Often, yes. The big win is control: n8n makes it easier to enforce “only Approved sends,” loop through multiple rows, and update statuses reliably without paying extra for every branch. You also get the option to self-host, which matters once you’re running lots of scheduled checks. Zapier or Make can still be fine for a simple two-step “row added → send email,” but approvals plus file storage plus status tracking gets messy. If you want help choosing, Talk to an automation expert.
Once Sheets becomes the gatekeeper, “Oops, wrong version” stops being a regular event. Set it up once, then let approvals decide what actually ships.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.