SMSTunnel for Google Calendar

Text reminders from your own phone and number

Free Google Apps Script template · no server
Text reminders for your events

Google Calendar no longer texts you. This does.

Google Calendar stopped sending SMS notifications on 7 January 2019; since then its reminders come as app and email notifications only (Google Workspace Updates). SMSTunnel for Google Calendar brings text reminders back: your calendar hands each reminder to your SMSTunnel account, and your own Android phone texts it from your own number. People see a number they know, and they can reply to you.

What it texts

Remind me

Before each event, 10 minutes to a day before. Only the calendars you choose, and only events with a word you choose if you like ("dentist").

Reminder: Dentist at 2:30 PM (in 15 min)

My agenda

One text every morning, at the hour you choose.

Today, Mon, Nov 2: 9:00 AM Dentist, 2:00 PM Call with Ana

Remind your clients

For appointments: the person in the event gets a reminder from your number, the day before or a few hours before.

Reminder: your appointment on Mon, Nov 2 at 9:30 AM. Reply to this text if you need to change it.

Each reminder goes out once. If an event moves, the new time gets one new text. Turn on any of the three, or all of them, in one spreadsheet.

Your calendar is in Outlook? See reminder texts for Outlook Calendar events.

1. Get your key

  1. 1. Install the SMSTunnel app from Google Play on your Android phone and sign in.
  2. 2. In your dashboard, open Apps → Add an app, pick Google Sheets, Forms or Calendar, name it (for example "Google Calendar") and click Create the key.
  3. 3. Copy the key right away: it's shown only once. You can stop or delete the app there anytime, and Google Calendar can't send texts anymore.

Get the steps with your key in them

It opens Add an app with Google Sheets, Forms or Calendar picked. Once the key is made, the dashboard shows every step and command with the key already filled in, ready to copy.

Make one key per spreadsheet or form, so you can stop one without touching the others.

2. Add the template to your spreadsheet

Ready-made copies (Make a copy) are coming soon. Pasting the code works today and takes a few minutes:

  1. 1. Make a new spreadsheet for it: the script lives in a spreadsheet, which keeps the log and, if you want, your guests' numbers. Then open Extensions → Apps Script.
  2. 2. Make the same files as the template's folder on GitHub (apps-script/calendar-reminders) and paste each one's content:
    • SmsTunnel, SmsTunnelKit and Code: script files (+ → Script; the editor names them .gs);
    • Setup: an HTML file (+ → HTML).
  3. 3. Open Project Settings (the gear), tick Show "appsscript.json" manifest file in editor, open appsscript.json and replace it with the template's.
  4. 4. Save, go back to your spreadsheet and reload it. The SMSTunnel menu shows up after a few seconds (reload the page once if it doesn't).

3. Set it up

  1. 1. Choose SMSTunnel → Set up. Google asks you to allow the script the first time (see below).
  2. 2. Paste your key, click Check, choose the phone that sends the texts, fill in the rest and click Save and turn on.
  3. 3. Send yourself a test: SMSTunnel → Send me a test reminder.

The setup dialog has the same test button, so you can try your text before saving.

Google's permission screen, explained

The first time you choose Set up, Google asks you to allow the script. Because it is your own copy of a script Google hasn't reviewed, Google shows "Google hasn't verified this app". That is expected for a script you own: click Advanced → Go to … (unsafe). You can read every line of it in Extensions → Apps Script first. Google may let you tick the permissions one by one: tick all of them, because the texts can't go out without them (Set up asks again if one is missing).

What each permission is for (Google's screen words them its own way):

Connect to an external service
Handing each text to SMSTunnel at https://smstunnel.io. Nothing else is called. (script.external_request)
This spreadsheet only
Writing the "SMSTunnel log" sheet and the list of texts sent, and reading the "Phone numbers" sheet. No other spreadsheet. (spreadsheets.currentonly)
See your calendars
Reading your events. It never changes or adds an event. (calendar.readonly)
Show dialogs
The SMSTunnel menu, the setup dialog and the previews. (script.container.ui)
Run when you are not present
The triggers that run when a response comes in, a cell changes or the time comes. (script.scriptapp)

You can remove the script's access anytime in your Google Account (Security → Third-party apps & services), and stop every text at once by deleting the key under Apps in your SMSTunnel dashboard.

What you choose in Set up

Remind me before each event

A text to your own numbers (up to 5, one text each) 10, 15, 30 or 45 minutes, 1 to 12 hours, or a day before each event in the calendars you choose. Optionally only events whose title has a word you choose ("dentist, call"). All-day events are left out unless you include them (they then count as starting at the hour you choose, 8:00 by default).

Text me my agenda every day

One text each day at the hour you choose: "Today, Mon, Nov 2: 9:00 AM Dentist, 2:00 PM Call with Ana". Days with nothing planned are skipped unless you say otherwise.

Remind the people in your events

  • For appointments. The person's number comes from a line in the event's description that starts with a word you choose and a colon, such as SMS: +1 415 555 0123 or Phone: 0722 123 456, or from the Phone numbers sheet (Email, Phone, Name) for guests you invited. The word can be in any language (Téléphone:, Telefon:).
  • Other numbers in a description, such as a video call's dial-in line, are never used.
  • Only events you created count, unless you untick Only events you created: otherwise an invitation from someone else could put a number in its description and choose who gets a text from your phone.
  • Reminders to people go out only between the hours you choose (8:00 to 21:00 by default), at most 10 people per event. Only text people who asked for these reminders.

Texts can use {Title}, {Date}, {Time}, {Location}, {Calendar}, {In} ("in 15 min") and, for people, {Name}. Under More settings: the country code for numbers written without one, how dates and times look in texts, and at most how many texts go out per check.

The SMSTunnel menu

Set up
Your key, your phone, and the three kinds of texts.
Send me a test reminder
Uses your next event, or a made-up one.
Preview the next texts
What goes out in the next 24 hours, without sending anything.
Send due texts now
Sends the texts that are due without waiting for the next check.
Turn texts off
Removes the triggers; your settings and key stay, so Set up turns them back on.
Help
Shows the last problem, if there was one.

If it doesn't work

No SMSTunnel menu
Reload the spreadsheet and wait a few seconds.
"Google hasn't verified this app"
Expected for your own copy: Advanced → Go to … (unsafe). See the permission screen above.
A text didn't go out
Help shows the last problem; the SMSTunnel log sheet shows each text and why one was not sent. Check that your phone is online under Phones in your dashboard: when it's offline, texts wait and go out when it's back.
"has no country code"
Write the number with + and the country code, or set the country code in Set up → More settings.
Google emails "Summary of failures for Google Apps Script"
A run stopped on purpose, usually because the key was deleted or the chosen phone was unlinked. Open Help, then Set up to fix it.
Texts arrive at odd times
Check the time zone: the calendar's own.

How it keeps track

  • Never twice. Each text is recorded (event, start time and number) in a hidden SMSTunnel sent sheet. If an event moves, its new time gets one new text. Declined events are left out.
  • How often it checks: every 5 minutes when you want a reminder 10 or 15 minutes before (so two checks fall inside the time you chose), every 10 minutes up to an hour, every 15 minutes otherwise or for the agenda, and every hour when only people get reminders. That stays well within Google's daily limits.
  • The log: every text, and every event that could not be texted, is listed in the SMSTunnel log sheet (the last 2000 lines).

Good to know

  • Numbers: write them in international format, like +14155550123. Numbers without a country code need the country code in Set up; without it they are skipped, so a text never goes to a number in the wrong country.
  • When something stops the texts (a deleted key, a phone no longer linked), the run fails on purpose, so Google emails you about it, and Help shows the last problem. Short outages and "too many texts" just wait for the next run.
  • Your phone offline: the text waits and goes out as soon as the phone is back online.
  • One setup per file: if two editors both run Set up, the latest one sends and the other one's trigger removes itself, so nobody gets a text twice.
  • Limits: SMSTunnel takes 30 send requests a minute, up to 1600 characters per text, and your plan's daily allowance applies. Google Apps Script (quotas) gives a free Google account 20,000 URL Fetch calls a day (one per text), 90 minutes of trigger run time a day and 6 minutes per run; Google Workspace accounts get 100,000 calls and 6 hours. The template pauses 2 seconds between texts and caps each run.

Privacy and security

  • The key stays in the script's user properties: only you can read it, and it is never written to a cell, a note or a log. The setup dialog shows only its last 4 characters.
  • Who can change the script: everyone with edit access to the spreadsheet can edit its script, and a trigger runs with the permissions of the person who set it up. Give edit access only to people you trust.
  • What leaves your file: for each text, the number and the text go to SMSTunnel and to your phone. Logs stay in your spreadsheet. Nothing is sent anywhere else.
  • Safe writes: anything SMSTunnel writes to a cell (an event title from someone else's invite, a reason from the server) is written as text, never as a formula.
  • Stop everything by deleting the key under Apps in your SMSTunnel dashboard.

Questions

Does it cost anything?
The template is free, and Google Apps Script is free with any Google account. The texts count against your SMSTunnel plan, and your mobile plan applies to the texts your phone sends.
Whose number do people see?
Yours. The texts leave your own phone, from its SIM, like a text you type yourself. Replies come back to your phone.
What if my phone is off?
The text waits and goes out as soon as your phone is back online.
Will it text a number twice?
No. It writes down each text it sends in a hidden list and checks it before each text. If an event moves, its new time gets one new text.
Where is my key kept?
In the script's own private storage for your account, which only you can read. It never goes into a cell or a log. Delete the key under Apps in your dashboard and every text stops at once.
Does it work with Google Workspace accounts?
Yes, with personal Google accounts and Google Workspace accounts. Workspace accounts get higher daily limits from Google.

Build it with an AI assistant

Copy this prompt into Claude, ChatGPT, Cursor or Copilot and replace the part in [brackets]. Don't paste your API key into the chat: the prompt doesn't need it.

Help me write Google Apps Script code (V8 runtime) that texts reminders for my Google Calendar events from my own phone, with SMSTunnel.

About SMSTunnel (https://smstunnel.io): my own apps and tools hand text messages (SMS) to my SMSTunnel account, and my own Android phone sends them from my own number, on my own SIM and plan. The phone runs the SMSTunnel app from Google Play (https://play.google.com/store/apps/details?id=io.smstunnel.app), signed in to my account.

What I want: [describe what should send a text, to whom, and when]

How it works:
- Install: paste the file SmsTunnel.js from "SMSTunnel for Google Sheets, Forms and Calendar" (https://github.com/narcisbodea/smstunnel-google, apps-script/library/SmsTunnel.js) into my Apps Script project. Then call SmsTunnel.sendSms(to, message, options).
- SmsTunnel.sendSms(to, message, { deviceId, defaultCountryCode }) makes one call to POST https://smstunnel.io/api/v1/sms/send with the header X-API-Key: <key> and the JSON body { "to": "+14155550123", "message": "...", "deviceId": "...", "defaultCountryCode": "+1" } (deviceId and defaultCountryCode are optional). It returns { messageId, queued }.
- One recipient per call: to text several people, call it once per person.
- Numbers in international format (+14155550123). defaultCountryCode ("+1", "40") completes numbers written without + or 00, and wins over the phone's own country. SmsTunnel.normalizePhone(value, countryCode) gives the exact number or the reason it is refused.
- Texts: up to 1600 characters. Sending is limited to 30 requests a minute.
- Sign-in codes: SmsTunnel.sendCode(to, message) calls POST /api/v1/sms/send-2fa; the text must contain a code of 4 to 10 digits standing on its own (or 123-456), at most 320 characters, or it is refused (400).
- Errors throw an Error named SmsTunnelError with status, code and retryable: 401 = wrong or deleted key, 403 = the key lacks a permission (code PERMISSION_REQUIRED) or the plan doesn't allow it, 429 = too many requests (retryable, retryAfter in seconds), 5xx and network errors = retryable.
- When my phone is offline the text waits (queued: true) and goes out as soon as the phone is back online.
- Optional { idempotencyKey: "..." } (the Idempotency-Key header): a retry with the same key within 24 hours gets the first answer instead of sending a second text. Use one key per text you mean to send.
- For calendar reminders: read the events with CalendarApp (read-only), check them from a time-driven trigger every few minutes, and record each text sent (event, start time and number) so a reminder goes out once and a moved event gets one new text.
- The API key comes from my SMSTunnel dashboard (https://dashboard.smstunnel.io): Apps → Add an app → Create the key. It is shown only once and can send texts and check whether they went out.

Rules for your answer:
- Keep the API key in an environment variable or the platform's secret store (for example SMSTUNNEL_API_KEY). Never put it in source code, in a repository, or in code that runs in a browser or a mobile app: call SMSTunnel from a server. I will not paste my key in this chat; use a placeholder.
- Validate phone numbers before sending (international format, like +14155550123) and skip or report the invalid ones.
- Handle errors: log or show what went wrong, retry only after 429, 5xx or network errors and only a few times, and never send the same text twice.
- Only send texts people expect from me: alerts to myself, reminders, sign-in codes, updates they asked for. No unsolicited texts.
- Keep the API key in PropertiesService (SmsTunnel.setApiKey from a one-time prompt or dialog, which stores it in user properties). Never put the key in the code, in a cell, in a log, or in HTML/JavaScript that runs in the browser.
- Check every number with SmsTunnel.normalizePhone before sending; skip invalid ones and say why.
- Handle errors: stop and tell me on 401 or 403; leave the item for the next run on 429 or 5xx; write down what was sent so nothing is sent twice; cap the texts per run.
- Only send texts people expect from me: to people who gave me their number for these texts.
- Apps Script only: UrlFetchApp (no fetch), no setTimeout, no async/await; installable triggers for automation.

Responsible use

Built for alerts to yourself and your team, and texts people expect from you. One text goes to one number. Sending unsolicited messages from a consumer SIM generally breaches mobile carrier terms of service.

Google, Google Sheets, Google Forms, Google Calendar and Google Apps Script are trademarks of Google LLC. SMSTunnel is a third-party integration and is not affiliated with, endorsed by, or sponsored by Google.

No phone paired yet?

Install the Android app and sign in with your account, and you're ready in about a minute.

Get it on Google Play