Daily
Send personalised emails from a Google Doc template
Each person in your sheet gets an email written from your Google Doc template with their own name and company, and is marked as sent.
- Runs
- Daily
- Apps
- Google Docs, Google Sheets
- AI
- Not needed
- Access
- Doc read; Sheet edit
Send this to your assistant
Create a ClickRuntime automation: every day, send each unsent person in my Contacts sheet an email using my Google Doc template with their name and company filled in, then mark them Sent.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
An events coordinator at a small conference company sends the same invitation to a few dozen sponsors and speakers, each with their name and company in the greeting. Writing them one at a time takes an afternoon, and mail-merge add-ons need to be set up again each time the wording changes.
Keeping the wording in a Google Doc and the recipients in a sheet means the copy can be edited by anyone who can write a document, and the list can grow during the week. Event teams, recruiters, account managers and small agencies use it for invitations, onboarding notes and follow-ups that should read as personal.
What you get out of it
The wording lives in a normal document
Colleagues edit the template in Google Docs with comments and suggestions as usual. The next send uses the latest version without anyone copying text into another tool.
Each email reads as written for that person
Names, companies and any other column you add are filled into the template. Recipients see a message addressed to them, not a bulk mail.
Add people over time
New rows added during the week are picked up on the next daily run. People already marked as sent are never emailed again.
A clear record of who was contacted
Each row is marked with the date it was sent. When someone asks whether a sponsor got the invitation, the answer is in the sheet.
How it works
What happens, step by step
Once a day, ClickRuntime reads the text of your template Google Doc.
It goes through the Contacts sheet and picks the rows not yet marked as Sent.
For each person, the placeholders in the template are replaced with their name, company and other details, and the email is sent from your Gmail.
The row is marked as Sent with the date, so nobody receives the same email twice.
Before it runs live
- Connect Google Docs
- Connect your Google Sheets account and pick the spreadsheets it may use
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Run it at a different time, more or less often, or only on weekdays
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Google Docs and Google Sheets steps into one automation
Under the hood
The code that runs this automation
import base64
from datetime import date
from email.message import EmailMessage
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from clickruntime import on_trigger, credentials
DOC_ID, SHEET_ID = "your-doc-id", "your-spreadsheet-id"
@on_trigger
def run(event):
creds = Credentials(credentials.connection("google", "work"))
doc = build("docs", "v1", credentials=creds, cache_discovery=False).documents().get(documentId=DOC_ID).execute()
text = "".join(r["textRun"]["content"] for c in doc["body"]["content"] for r in c.get("paragraph", {}).get("elements", []) if "textRun" in r)
values = build("sheets", "v4", credentials=creds, cache_discovery=False).spreadsheets().values()
head, *rows = values.get(spreadsheetId=SHEET_ID, range="Contacts!A1:Z").execute()["values"]
gmail, sent, status_col = build("gmail", "v1", credentials=creds, cache_discovery=False), 0, chr(65 + head.index("Status"))
for i, row in enumerate(rows, start=2):
rec = dict(zip(head, row + [""] * len(head)))
if rec["Status"] or not rec.get("Email"):
continue
filled = text
for k, v in rec.items():
filled = filled.replace("{{" + k + "}}", v)
subject, _, body = filled.partition("\n")
msg = EmailMessage()
msg["To"], msg["Subject"] = rec["Email"], subject.strip()
msg.set_content(body.strip())
gmail.users().messages().send(userId="me", body={"raw": base64.urlsafe_b64encode(msg.as_bytes()).decode()}).execute()
values.update(spreadsheetId=SHEET_ID, range=f"Contacts!{status_col}{i}", valueInputOption="RAW",
body={"values": [[f"Sent {date.today().isoformat()}"]]}).execute()
sent += 1
return {"sent": sent}
FAQ
Common questions
How do I mark where names go in the template?
Which address are the emails sent from?
Where does the subject line come from?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Turn feedback in a sheet into a Google Doc report
Each week, new feedback rows in your sheet are grouped into themes by AI and written up as a report in a Google Doc, with the link emailed to you.
See how it worksSummarise new Google Docs into a sheet
Every new document in your folder gets a short summary added to a Google Sheet, with its title and link.
See how it worksTurn companies in a sheet into research briefs in Google Docs
Add a company to your sheet and a research brief appears in a Google Doc, with the link written back into the row.
See how it worksKeep exploring
Set up “Send personalised emails from a Google Doc template” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.