Gmail Automation: The Complete Google Apps Script Guide (2025)
Table of Contents
- Apps Script Demystified
- Your First Gmail Automation: The “Out of Office” Upgrade
- 8 More Powerful Examples You Can Copy-Paste
- Use OpenAI to summarize long emails in Gmail
- Log complaints to a CRM
- Auto-generate calendar events from emails with time mentions
- Send follow-up reminders automatically
- Automatically resend unanswered emails
- Slack notification when an important email is received
- Forward specific emails to a different address
- Sync email attachments with Google Drive by category
- Deploy and Monitor Your Script
- Coding Is Too Hard. How to Gain Email Productivity?
Google Apps Script is a powerful tool that allows you to create custom Gmail automations. With automation, you can eliminate tideous and routine tasks such as manually sorting and labeling hundreds of emais per day, and sending follow-up emails to customers or candidates.
This posts explains:
- what is Google Apps Script
- how to create your first Gmail automation script
- 8 more powerful examples you can copy-paste
- how to run and monitor your script
- how to gain extra email productivity without coding at all
Apps Script Demystified
Google Apps Script is a cloud-based JavaScript platform that integrates seamlessly with Google Workspace. The script lives within your Google account, ready to automate all those mind-numbing tasks you secretly dread. No more copy-pasting, no more endless clicking—just pure unadulterated automation bliss.
Your First Gmail Automation: The “Out of Office” Upgrade
Let’s start with a classic: the out-of-office reply. But with a twist. Instead of a generic message, we’ll create a script that sends a personalized response based on the sender’s email address.
Setting Up Apps Script
Access the Script Editor: Open your Gmail account. Click the grid icon at the top-right corner, go to Google Drive, and create a new Google Apps Script project by selecting
New > Google Apps Script
.Authorize the Script: Your script will require access to Gmail. When prompted, grant the necessary permissions.
Write the Code: Use the editor to write custom scripts for your automation tasks. Here is the code for the “Out of Office” script. This script checks who emailed you and sends a tailored response. Pretty neat, right?
1function autoReply() {
2 // Get the current thread.
3 let thread = GmailApp.currentThread()
4 // Get the sender's email address.
5 const sender = thread.getMessage(0).getFrom()
6
7 // Check if the sender is already in the 'Replied To' list.
8 const labels = thread.getLabels()
9 if (labels.some(label => label.getName() === 'Replied To')) {
10 return // Skip if already replied
11 }
12
13 const importantResponse = `
14 Thanks for your email!
15 I'm currently out of the office, but I'll get back to you as soon as I can.
16 In the meantime, please contact my colleague at colleague@example.com.`
17 const defaultResponse = `
18 Thanks for your email!
19 I'm currently out of the office and will respond upon my return.`
20
21 // Personalized responses.
22 var responses = {
23 "importantclient@example.com": importantResponse,
24 "default": defaultResponse
25 }
26
27 var replyMessage = responses[sender] || responses["default"]
28
29 // Send the personalized reply.
30 thread.reply(replyMessage)
31 // Add a label to avoid duplicate replies
32 thread.addLabel(GmailApp.createLabel('Replied To'))
33}
8 More Powerful Examples You Can Copy-Paste
Use OpenAI to summarize long emails in Gmail
1function summarizeLongEmailsUsingOpenAI() {
2 const apiKey = "your-openai-api-key" // Replace with your OpenAI API key
3 const threads = GmailApp.search("is:unread")
4
5 threads.forEach(thread => {
6 const message = thread.getMessages()[0]
7 const emailBody = message.getPlainBody()
8
9 // OpenAI API URL
10 const openAiUrl = "https://api.openai.com/v1/completions"
11
12 // Request payload
13 const payload = {
14 model: "gpt-4o-mini",
15 prompt: `Summarize the following email:\n\n${emailBody}\n\nSummary:`,
16 temperature: 0.5
17 }
18
19 // Set up the API request
20 const options = {
21 method: "post",
22 contentType: "application/json",
23 payload: JSON.stringify(payload),
24 headers: {
25 Authorization: `Bearer ${apiKey}`
26 }
27 }
28
29 // Make the API request
30 try {
31 const response = UrlFetchApp.fetch(openAiUrl, options)
32 const jsonResponse = JSON.parse(response.getContentText())
33 const summary = jsonResponse.choices[0].text.trim()
34
35 // Reply to the thread but only send to yourself
36 thread.replyAll(
37 `Summary of the email:\n\n${summary}\n\n---\nAutomatically generated by AI`,
38 {
39 to: Session.getActiveUser().getEmail(), // Only send to yourself
40 noReply: true // Don't include original recipients
41 }
42 )
43
44 message.markRead()
45
46 // Add a label to track summarized emails
47 const summaryLabel = GmailApp.createLabel('AI-Summarized')
48 thread.addLabel(summaryLabel)
49 } catch (error) {
50 Logger.log("Error summarizing email: " + error)
51 }
52 })
53}
Log complaints to a CRM
1function logComplaintsToCRM() {
2 const crmApiUrl = "https://api.crm.com/complaints"
3 const threads = GmailApp.search("label:complaints")
4
5 threads.forEach(thread => {
6 const message = thread.getMessages()[0]
7 const payload = {
8 customer: message.getFrom(),
9 subject: message.getSubject(),
10 complaint: message.getPlainBody()
11 }
12
13 UrlFetchApp.fetch(crmApiUrl, {
14 method: "post",
15 contentType: "application/json",
16 payload: JSON.stringify(payload),
17 headers: { Authorization: `Bearer your-crm-api-key` }
18 })
19 })
20}
Auto-generate calendar events from emails with time mentions
1function autoCreateCalendarEvents() {
2 const threads = GmailApp.search("subject:(meeting OR schedule)")
3 const calendar = CalendarApp.getDefaultCalendar()
4
5 threads.forEach(thread => {
6 const message = thread.getMessages()[0]
7 const body = message.getPlainBody()
8 const timeMatch = body.match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}/) // Example: 2025-01-15 14:00
9
10 if (timeMatch) {
11 const eventDate = new Date(timeMatch[0])
12 calendar.createEvent(message.getSubject(), eventDate, new Date(eventDate.getTime() + 60 * 60 * 1000)) // 1-hour event
13 }
14 })
15}
Send follow-up reminders automatically
1function sendFollowUpReminders() {
2 const labelName = "Follow-Up"
3 const threads = GmailApp.getUserLabelByName(labelName).getThreads()
4
5 threads.forEach(thread => {
6 const messages = thread.getMessages()
7 const lastMessage = messages[messages.length - 1]
8 if (!lastMessage.isInInbox()) {
9 GmailApp.sendEmail(thread.getFirstMessageSubject(), "Follow-Up Reminder")
10 }
11 })
12}
Automatically resend unanswered emails
1function resendUnansweredEmails() {
2 const threads = GmailApp.search("label:sent newer_than:7d")
3
4 threads.forEach(thread => {
5 const messages = thread.getMessages()
6 const lastMessage = messages[messages.length - 1]
7 if (lastMessage.isDraft() && !thread.hasStarredMessages()) {
8 GmailApp.sendEmail(thread.getFirstMessageSubject(), lastMessage.getBody())
9 }
10 })
11}
Slack notification when an important email is received
1function notifySlackForImportantEmails() {
2 const slackWebhookUrl = "https://hooks.slack.com/services/your/slack/webhook"
3 const threads = GmailApp.search("label:important is:unread")
4
5 threads.forEach(thread => {
6 const message = thread.getMessages()[0]
7 const payload = {
8 text: `New Important Email: ${message.getSubject()} from ${message.getFrom()}`
9 }
10 UrlFetchApp.fetch(slackWebhookUrl, {
11 method: "post",
12 contentType: "application/json",
13 payload: JSON.stringify(payload)
14 })
15 })
16}
Forward specific emails to a different address
1function forwardEmails() {
2 const recipient = "assistant@example.com"
3 const threads = GmailApp.search("label:important")
4
5 threads.forEach(thread => {
6 const messages = thread.getMessages()
7 messages.forEach(message => {
8 GmailApp.sendEmail(recipient, message.getSubject(), message.getPlainBody())
9 })
10 })
11}
Sync email attachments with Google Drive by category
1function organizeAttachmentsByCategory() {
2 const categories = ["Invoices", "Reports", "Contracts"]
3 const parentFolderId = "your-parent-folder-id-in-google-drive"
4
5 // Ensure all category folders exist and get their IDs
6 const folderIds = {}
7 categories.forEach(category => {
8 folderIds[category] = getOrCreateFolder(category, parentFolderId)
9 })
10
11 // Process Gmail threads with attachments
12 const threads = GmailApp.search("has:attachment")
13 threads.forEach(thread => {
14 const message = thread.getMessages()[0]
15 const subject = message.getSubject()
16 const attachments = message.getAttachments()
17
18 // Match email subject to a category and move attachments
19 for (const category in folderIds) {
20 if (subject.includes(category)) {
21 const folder = DriveApp.getFolderById(folderIds[category])
22 attachments.forEach(attachment => folder.createFile(attachment))
23 }
24 }
25 })
26}
27
28// Helper function to get or create a folder by name under a parent folder
29function getOrCreateFolder(folderName, parentFolderId) {
30 const parentFolder = DriveApp.getFolderById(parentFolderId)
31 const folders = parentFolder.getFoldersByName(folderName)
32
33 // If the folder already exists, return its ID
34 if (folders.hasNext()) {
35 return folders.next().getId()
36 }
37
38 // Otherwise, create the folder and return the new ID
39 const newFolder = parentFolder.createFolder(folderName)
40 return newFolder.getId()
41}
Deploy and Monitor Your Script
Before deploying, run your script in the Apps Script editor to ensure it works as expected. Use the debug console to identify errors.
Then, set a trigger to automate the script. Go to Triggers
in the Apps Script
editor. Click Add Trigger
and configure it.
If sharing is needed, publish the script as an add-on for others to install and use.
Use the Logger.log
function to debug your script. Access logs under View >
Logs in the Apps Script editor. You can also set up email notifications for
errors. This way, you’re alerted when something goes wrong.
Coding Is Too Hard. How to Gain Email Productivity?
You are here probably because you are swamped by emails and are looking for every chance to save time.
TypeTab is the real answer. It will 10x your email productivity. It offers a drop-in replacement for gmail autocomplete but is context-aware and powered by the best AI models. No prompting. Just press Tab to accept AI suggestions. TypeTab works right in the gmail page. No more copy-paste or switching apps. TypeTab never sells or trains on your data. Take back your time—Think about your hourly salary and how much time you spend on emails.
Start your free trial at typetab.com, no credit card required.
Most Popular Posts On Email Productivity
- From ChatGPT to Gmail: How to Adopt AI Writing for Emails
- A Guide to Organizing Your Inbox Using Gmail Labels and Automation
- The Smart Way to Connect Gmail & Google Calendar
- Gmail + Google Tasks: The Ultimate Guide to Email Task Management (2025)
- How to Customize Gmail Settings for Max Productivity
- Use Gmail with Your Own Domain
- Mastering Gmail: Expert Tips to Streamline Your Inbox
- Email Delegation in Gmail Beats Shared Inboxes Every Time
- Gmail Automation: The Complete Google Apps Script Guide (2025)
- Stay Productive with Gmail Offline Mode: A Guide for the Modern Professional
Learn More About TypeTab
- Why Your Emails Get Ignored And How to Increase Response Rate
- From ChatGPT to Gmail: How to Adopt AI Writing for Emails
- Gemini Smart Compose vs. TypeTab: Which Truly Boosts Email Productivity? (Spoiler: One Reads Your Mind)
- Why Prompting is Wrong for Email Productivity
- Measuring Email Communication Costs and ROI of Email Efficiency Tools
- TypeTab Onboarding Guide (1-minute read)