Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Building a Gmail Watchdog: Automated Email Monitoring with Google Apps Script

I needed a way to monitor critical emails that should arrive regularly however, when they do not, I need to be notified. Rather than paying for expensive monitoring services, I built my own solution using Google Apps Script that runs 24/7 in the cloud and sends professional alerts when expected emails go missing.

What was the mission?

I have several automated systems that send me important emails:

  • Daily email confirmations from lee@bythepowerofskeyskull.com
  • Server status reports with subjects starting with "Automated Email Check"
  • System health notifications that arrive every 15 minutes

If emails were not being delivered I would like to get a notification, but this needed to come from outside the company (I already have an internal one) 

What I needed was a monitoring system that would:

  • Check Gmail every 15 minutes for expected emails
  • Stay completely silent when emails arrive normally
  • Send immediate alerts when emails don't arrive
  • Run automatically without any infrastructure on my end

Houston "we have a problem" Notification

This is a visual of the notification that is sent when the mail is not detected as per the script configuration, it needed to be very cleat and easy to read:

Core Monitoring Logic

Here's the heart of the monitoring system:

function checkForExpectedEmails() {
  // Calculate time range (last 15 minutes)
  const now = new Date();
  const checkTime = new Date(now.getTime() - (CONFIG.checkWindow * 60 * 1000));
  
  // Build Gmail search query
  const searchDate = Utilities.formatDate(checkTime, Session.getScriptTimeZone(), 'yyyy/MM/dd');
  const fullSearchQuery = `${CONFIG.searchQuery} after:${searchDate}`;
  
  // Search for emails matching criteria
  const threads = GmailApp.search(fullSearchQuery, 0, 10);
  
  // Only alert if NO emails found
  if (threads.length === 0) {
    console.log('No expected emails found - sending alert');
    sendAlert();
  } else {
    console.log(`Found ${threads.length} expected email(s) - no alert needed`);
  }
}

Configuration Setup

I made the system configurable so I could easily monitor different email types, this was looking for the email being sent into the Google Mail from a certain sender and with a certain subject.

const CONFIG = {
  // Email to send alerts to
  alertEmail: 'lee@bythepowerofskeyskull.com',
  
  // Search criteria for emails you're expecting
  searchQuery: 'from:manager@idobeleiveinfaries.co.uk subject:"Automated Email Check"',
  
  // Time window to check (in minutes)
  checkWindow: 15,
  
  // Alert details
  alertSubject: 'Email Alert: Automated Email Check not received',
  alertFromName: 'Email Monitor'
};

This searches for emails from a specific sender with subjects containing "Automated Email Check". Gmail automatically matches partial subjects, so it catches emails like:

  • "Automated Email Check - Daily Report"
  • "Automated Email Check: System Status"
  • "Automated Email Check (July 19)"
The target emails were as below, so this filtered worked well:


Professional Alert Emails

When something goes wrong, I want clear, actionable alerts. I built professional HTML email templates that look like enterprise monitoring systems:

function sendAlert() {
  const htmlBody = `
<!DOCTYPE html>
<html>
<body style="font-family: 'Segoe UI', sans-serif; margin: 0; padding: 0;">
  <div style="max-width: 600px; margin: 0 auto; background-color: #ffffff;">
    
    <!-- Alert Header -->
    <div style="background: linear-gradient(135deg, #ff6b6b, #ee5a24); color: white; padding: 30px 20px; text-align: center;">
      <div style="font-size: 48px; margin-bottom: 10px;">⚠️</div>
      <h1 style="margin: 0; font-size: 24px;">Email Monitoring Alert</h1>
      <p style="margin: 5px 0 0 0; opacity: 0.9;">Expected email not received</p>
    </div>
    
    <!-- Alert Details Table -->
    <div style="padding: 30px 20px;">
      <table style="width: 100%; border-collapse: collapse;">
        <tr>
          <td style="padding: 12px 15px; font-weight: 600;">Search Criteria:</td>
          <td style="padding: 12px 15px; font-family: monospace;">${CONFIG.searchQuery}</td>
        </tr>
        <tr>
          <td style="padding: 12px 15px; font-weight: 600;">Status:</td>
          <td style="padding: 12px 15px;">
            <span style="background-color: #dc3545; color: white; padding: 4px 12px; border-radius: 20px;">MISSING</span>
          </td>
        </tr>
      </table>
    </div>
    
  </div>
</body>
</html>
  `;

  GmailApp.sendEmail(CONFIG.alertEmail, CONFIG.alertSubject, textBody, { htmlBody: htmlBody });
}

These alerts include gradient headers, status badges, detailed tables, and recommended actions - much more professional than basic text emails.

Alert Strategy: Silence is Golden

I made a crucial design decision: the system only sends emails when there's a problem. There are no "everything is fine" notifications.

This prevents alert fatigue - when people receive too many routine notifications, they stop paying attention to alerts entirely. With this system:

  • Silence means everything is working
  • An email means immediate attention required

This approach ensures that when I do receive an email, I know it's genuinely important.

Step-by-Step Installation Guide

Here's how to set up the email monitoring system:

1. Create the Google Apps Script

  1. Go to script.google.com
  2. Click "New project" 
  3. Delete the defauly myFunction() code:


  4. Paste the data (when requested from the link)
  5. Save the project with a meaningful name like "Email Monitor"

2. Configure Your Settings

Update the "config" object at the top of the script:

Set alertEmail to where you want alerts sent
Set searchQuery to match your expected emails
Adjust checkWindow if you want different timing 
Save the script (Ctrl+S)

3. Set Up Automatic Triggers (not optional)

The script will NOT work without this step - triggers are mandatory for automatic operation.

Manual trigger creation:

Click on the Project


Click the clock icon (⏰) in the left sidebar


Click "+ Add Trigger" with the options below:



This should then add a trigger for that time interval:


4. Verify Automatic Operation

Check the "Executions" tab to see automatic runs


Look for entries with "Time-driven" type (not "Editor")


Monitor logs to ensure the system runs without errors, if you click on the logs you will see the outcome:


5. Monitor and Maintain

Check execution logs periodically for any errors which can be done from the Overview option:



Gmail API Limits and Scalability

I was initially concerned about hitting Google's API limits, but the usage is actually very light:

For Reading Emails (Monitoring):

  • Each Gmail search uses ~1-5 quota units
  • Running every 15 minutes = 96 daily executions
  • Total daily usage: ~500 quota units
  • Daily limit: 1 billion quota units

The key insight is that Google's limits are designed to prevent abuse, not restrict legitimate monitoring applications.

Previous Post Next Post

نموذج الاتصال