Why Automate Gmail with Apps Script?
Gmail is central to most workflows, and automating it can save hours every week. Google Apps Script's GmailApp service lets you send personalized emails, parse incoming messages, apply labels, archive threads, and more — all without leaving the Google ecosystem.
Sending a Simple Email
The most fundamental operation is sending an email. Here's the basic syntax:
function sendSimpleEmail() {
GmailApp.sendEmail(
"recipient@example.com",
"Your Weekly Report is Ready",
"Hi there,\n\nYour report has been generated and is attached.\n\nBest regards,\nThe Automation Bot"
);
}
You can also use the optional fourth parameter for advanced options like CC, BCC, HTML body, and attachments.
Sending HTML Emails with Dynamic Content
Plain text emails are functional, but HTML emails look far more professional. Use the htmlBody option to send rich content:
function sendHtmlEmail(recipientName, recipientEmail, reportUrl) {
const subject = `Your Report for ${new Date().toDateString()}`;
const htmlBody = `
<h2>Hi ${recipientName},</h2>
<p>Your automated report is ready. Click the button below to view it.</p>
<a href="${reportUrl}" style="background:#1a73e8;color:#fff;padding:10px 20px;text-decoration:none;border-radius:4px;">
View Report
</a>
<p>This email was sent automatically.</p>
`;
GmailApp.sendEmail(recipientEmail, subject, "", { htmlBody });
}
Reading and Processing Incoming Emails
You can search your inbox using the same query syntax as Gmail's search bar:
function processIncomingOrders() {
const threads = GmailApp.search("subject:New Order is:unread", 0, 20);
threads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(message => {
const body = message.getPlainBody();
const sender = message.getFrom();
Logger.log(`Order from: ${sender}`);
Logger.log(`Body preview: ${body.substring(0, 100)}`);
});
thread.markRead(); // Mark as read after processing
});
}
Applying Labels Automatically
Organize your inbox automatically by applying labels to threads that match certain criteria:
function labelImportantEmails() {
// Get or create the label
let label = GmailApp.getUserLabelByName("Auto-Processed");
if (!label) {
label = GmailApp.createLabel("Auto-Processed");
}
const threads = GmailApp.search("from:boss@company.com is:unread");
threads.forEach(thread => {
thread.addLabel(label);
thread.markRead();
});
}
Building a Mail Merge from Google Sheets
One of the most practical Gmail automations is a mail merge — sending personalized emails to a list of contacts stored in a spreadsheet:
function runMailMerge() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const data = sheet.getDataRange().getValues();
const headers = data[0]; // First row is headers
// Expected columns: Name, Email, CustomField
for (let i = 1; i < data.length; i++) {
const row = data[i];
const name = row[0];
const email = row[1];
const customField = row[2];
if (!email) continue; // Skip rows without email
const subject = `Hello ${name}, here's your update`;
const body = `Hi ${name},\n\nYour reference: ${customField}\n\nThank you!`;
GmailApp.sendEmail(email, subject, body);
Utilities.sleep(200); // Brief pause to avoid rate limits
}
}
Setting Up a Time-Based Trigger for Email Automation
To run your email automation on a schedule, set up a time-driven trigger:
- In the Apps Script editor, click the clock icon (Triggers) in the left sidebar.
- Click Add Trigger.
- Select your function, choose Time-driven, and set your interval (daily, weekly, etc.).
- Save and authorize.
Your Gmail automation will now run without any manual intervention.
Important Limits to Keep in Mind
Free Google accounts can send a limited number of emails per day through Apps Script. Google Workspace accounts have higher limits. Always build in error handling and check quota usage if you're sending to large lists. Use MailApp.getRemainingDailyQuota() to check how many emails you can still send before triggering your script.