← Back to blog
google-sheetsapps-scriptautomationtutorials

Google Sheets Apps Script Email Tutorial (Copy-Paste Ready)

February 7, 2026·Sam Ralston
Code editor showing JavaScript syntax with highlighted functions on screen

Google Apps Script is the fastest way to add email functionality to your Google Sheet. You can send alerts when conditions are met, daily summary reports, or notifications when data changes.

This tutorial gives you copy-paste ready code for the most common email scenarios. No prior coding experience needed. Just paste, customize, and run.

Getting Started

Open any Google Sheet. Click Extensions > Apps Script. You will see a code editor with a blank function. Delete it. You are going to paste in code from this tutorial.

After pasting, click the play button (triangle) to test. Google will ask for permissions the first time. You need to allow access to your spreadsheet and Gmail.

Script 1: Simple Email from Spreadsheet Data

This reads your sheet and sends one email with the data.

function sendSimpleEmail() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); var data = sheet.getDataRange().getValues(); var body = "Here is your data: "; for (var i = 1; i < data.length; i++) { body += data[i][0] + ": " + data[i][1] + " "; } MailApp.sendEmail("[email protected]", "Sheet Data Report", body); }

This loops through every row (skipping the header) and includes column A and B values. Change column indexes and the email address to match your setup.

Script 2: Conditional Alert Email

Only sends an email when specific conditions are met.

function sendConditionalAlert() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); var data = sheet.getDataRange().getValues(); var alerts = []; for (var i = 1; i < data.length; i++) { var name = data[i][0]; // Column A var value = data[i][2]; // Column C var status = data[i][3]; // Column D if (value > 100 && status !== "Resolved") { alerts.push(name + " - Value: " + value + " (Status: " + status + ")"); } } if (alerts.length > 0) { MailApp.sendEmail( "[email protected]", "Alert: " + alerts.length + " items need attention", "Items exceeding threshold: " + alerts.join(" ") ); } }

This checks if column C exceeds 100 AND column D is not "Resolved." Only matching rows trigger the alert. If nothing matches, no email is sent.

Script 3: Daily Summary Report

Sends a formatted daily summary of your data.

function sendDailySummary() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); var data = sheet.getDataRange().getValues(); var totalItems = data.length - 1; var completed = 0; var pending = 0; var overdue = 0; var today = new Date(); today.setHours(0, 0, 0, 0); for (var i = 1; i < data.length; i++) { var status = data[i][3]; // Column D: status var dueDate = new Date(data[i][2]); // Column C: due date if (status === "Complete") { completed++; } else if (dueDate < today) { overdue++; } else { pending++; } } var body = "Daily Summary - " + today.toDateString() + " " + "Total Items: " + totalItems + " " + "Completed: " + completed + " " + "Pending: " + pending + " " + "Overdue: " + overdue + " " + "Action needed: " + overdue + " overdue items require attention."; MailApp.sendEmail("[email protected]", "Daily Summary: " + overdue + " overdue", body); }

Script 4: HTML Formatted Email

Plain text emails work but look rough. Here is how to send formatted HTML emails:

function sendHtmlEmail() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); var data = sheet.getDataRange().getValues(); var rows = ""; for (var i = 1; i < data.length; i++) { var color = data[i][3] === "Overdue" ? "#ff4444" : "#ffffff"; rows += "" + "" + data[i][0] + "" + "" + data[i][1] + "" + "" + data[i][2] + "" + "" + data[i][3] + "" + ""; } var html = "

Status Report

" + "" + "" + "" + "" + "" + "" + rows + "
NameAmountDue DateStatus
"; MailApp.sendEmail({ to: "[email protected]", subject: "Status Report - " + new Date().toDateString(), htmlBody: html }); }

This creates a formatted table in the email with color-coded rows for overdue items. Much more readable than plain text.

Script 5: Send to Multiple Recipients

function sendToMultiple() { var recipients = ["[email protected]", "[email protected]", "[email protected]"]; MailApp.sendEmail({ to: recipients.join(","), subject: "Team Update", body: "This is a team-wide notification from your Google Sheet." }); }

Or send different emails to different people based on sheet data (like sending each tenant their own status):

function sendPersonalized() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Contacts"); var data = sheet.getDataRange().getValues(); for (var i = 1; i < data.length; i++) { var name = data[i][0]; var email = data[i][1]; var amount = data[i][2]; MailApp.sendEmail( email, "Payment Reminder", "Hi " + name + ", Your balance is $" + amount + ". Please submit payment at your earliest convenience. Thank you." ); } }

Setting Up Triggers

To run any of these scripts automatically:

1. In the Apps Script editor, click the clock icon (Triggers) in the left sidebar.

2. Click "Add Trigger" in the bottom right.

3. Choose your function name from the dropdown.

4. Set Event source to "Time-driven."

5. Choose frequency: "Day timer" for daily, "Hour timer" for hourly, "Week timer" for weekly.

6. Pick your time window.

7. Save.

The script now runs automatically on your schedule.

Error Handling

Add basic error handling to prevent silent failures:

function robustEmailScript() { try { // Your email logic here var remaining = MailApp.getRemainingDailyQuota(); if (remaining < 10) { Logger.log("Warning: Only " + remaining + " emails remaining today"); return; } // ... send emails ... } catch (error) { Logger.log("Script error: " + error.toString()); // Optionally email yourself about the error MailApp.sendEmail( "[email protected]", "Script Error Alert", "Your Google Sheets email script encountered an error: " + error.toString() ); } }

This checks your daily email quota before sending and catches any errors. If something goes wrong, it emails you about the failure instead of failing silently.

Important Limits

Daily email quota: Free Google accounts: 100 emails/day. Google Workspace accounts: 1,500/day. Check remaining with MailApp.getRemainingDailyQuota().

Execution time: Scripts time out after 6 minutes (free) or 30 minutes (Workspace). Keep loops efficient.

Trigger reliability: Time-driven triggers are not exact. A "7am-8am" trigger runs sometime in that window. Occasionally triggers skip entirely. Check monthly.

Or Skip the Code Entirely

Apps Script is powerful and free. But it requires maintenance. Scripts break when columns move. Triggers fail silently. Email quotas limit scale.

If you are building email alerts for something critical - like rent payments, financial deadlines, or maintenance tracking - and you do not want to maintain code, RentGuard handles it without any scripting. Connect your sheet, map your columns, get text and email alerts. $15/month.

Skip the code: RentGuard does what these scripts do - monitors your Google Sheet and sends alerts - without any coding or maintenance. Start free.
📋 Free templates: We built 6 free spreadsheet templates for landlords — rent tracking, maintenance logs, lease management, expense tracking, and more. Pre-formatted for Google Sheets and Excel.

For more Apps Script patterns, see email alerts in Google Sheets, send email when cell changes, and conditional notifications.

Stop missing late rent payments

RentGuard monitors your Google Sheet and alerts you when rent is overdue or maintenance is aging. No migration. 5 minute setup. 30 days free.

Start Free Monitoring →