Send email alerts for overdue dates in Google Sheets via Apps Script
Learn how to write a Google Apps Script that checks a date column, sends an email if the date is past due, and marks the row to prevent duplicates.
You track project deadlines, unpaid invoices, or renewals in a Google Sheet. Eventually, a date slips by because you forgot to open the file and look at it.
Formulas alone cannot send emails or notify you outside the spreadsheet. Google Sheets includes a built-in tool called Apps Script that runs JavaScript in the background. You can write a small script that reads your rows, finds the overdue items, sends you an email, and marks them as notified.
1 Structuring your spreadsheet
Your script needs predictable columns to read. If your columns move around, the script will read the wrong data and either crash or send incorrect emails.
We will use a simple layout. Put your task name in column A. Put the deadline date in column B. Leave column C empty for the status. Put headers in row 1. Give the sheet tab a clear name like "Tasks".
If you do not track what was already sent, the script will email you about the exact same overdue row every day. The script writes a note in this column after it sends the email, and ignores rows that already have that note.
Select column B and make sure the data is formatted as an actual date. If you typed dates in a way that Google Sheets thinks is text, the script will not be able to do math with them.
2 Writing the Apps Script
Click Extensions in the top menu, then select Apps Script. This opens a new tab with a code editor. Delete the placeholder code inside the editor and paste the script below.
function checkOverdueDates() {
var sheetName = "Tasks";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var data = sheet.getDataRange().getValues();
var today = new Date();
var emailAddress = "you@example.com";
today.setHours(0, 0, 0, 0);
for (var i = 1; i < data.length; i++) {
var taskName = data[i][0];
var deadline = new Date(data[i][1]);
var status = data[i][2];
if (deadline instanceof Date && !isNaN(deadline)) {
deadline.setHours(0, 0, 0, 0);
if (deadline < today && status !== "Alert Sent") {
var subject = "Overdue: " + taskName;
var message = "The task '" + taskName + "' was due on " + deadline.toDateString() + ".";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(i + 1, 3).setValue("Alert Sent");
}
}
}
}
Update the email address in the code to your actual email address. Update the sheet name variable if you named your tab something other than "Tasks".
The script loads your entire sheet into memory at once using the data range values. It creates a date object for today and forces the time to midnight. This ensures we only compare calendar days, avoiding situations where a task due today at 5 PM is flagged as overdue at 8 AM.
It then loops through your data. Arrays in JavaScript start counting at zero. The loop starts at 1 to skip your header row. Inside the loop, data[i][0] is column A, data[i][1] is column B, and data[i][2] is column C.
If the date is valid, it compares it to today. If the deadline is older than today and the status does not say "Alert Sent", it uses the MailApp tool to send an email. Finally, it targets the exact cell in column C using getRange and writes the status.
3 Testing and authorizing the script
Before relying on the automation, test it manually. Go back to your spreadsheet. Change one of the dates in column B to yesterday. Leave column C completely empty.
Go back to the script editor. Select your function from the dropdown at the top and click Run.
Google will show a warning popup requiring you to authorize the script to read your spreadsheets and send emails on your behalf. Click Review permissions. Choose your Google account. Google will show a warning that the app is unverified. Click Advanced, then click the link at the bottom to proceed to your script. Click Allow.
Check your email inbox. You will see a new email with the task name and the due date. Column C in that spreadsheet row will now say "Alert Sent". Run the script one more time manually. You will not get a second email because the script sees the status and skips the row.
4 Scheduling the daily automation
You need Google's servers to run this function automatically every morning by setting up a trigger.
- In the left sidebar of the script editor, click the clock icon labeled Triggers.
- Click the button to add a new trigger at the bottom right.
- Choose your script function name from the first dropdown.
- Set the event source to time-driven.
- Set the type of time based trigger to day timer.
- Pick a time slot for the emails, like 8 AM to 9 AM, and save.
Google will now wake up your script every day during that window. It will scan the entire sheet and email you only about tasks that fell behind schedule since yesterday.
Still stuck?
Simple scripts work well for flat data, but things get complicated when you need to fetch data from APIs, parse incoming emails, or sync your sheet with external databases. If your spreadsheet automation needs have outgrown a basic script, this is the kind of fix I do.
Quick answers
Why does the script email me multiple times for the same row?
The script is likely failing to read the status column correctly, or the column index in the code does not match your actual spreadsheet layout. Ensure the script writes "Alert Sent" to the correct column and checks that exact spelling on the next run.
Can I send emails to different people based on the row data?
Yes, if you put email addresses in another column, you can read that column in the script loop. You assign that value to a variable and pass it to the MailApp function instead of using a hardcoded email address.
Why does the date comparison fail and ignore my rows?
The script expects a real date format in your spreadsheet cells so it can create a valid JavaScript date object. If your dates are stored as plain text, the math will fail and the script will skip the row.