Back to BlogAutomation

Mail Merge in Google Sheets Without YAMM: Free Apps Script Alternative

Stop Paying \$400/Year for Mail Merge: Build a Free, Reliable System in Google Sheets. You are paying up to \$400 a year for brittle tools like YAMM

December 5, 2025
5 min read

Build Your Own Mail Merge

You're paying $300-400/year for tools like YAMM that break when you hit quotas. Outreach sequences stall. The team spends hours debugging "Daily limit exceeded" errors.

This is straightforward to solve. You can build a mail merge system in Google Sheets using Apps Script. It uses Gmail quotas you already have, handles errors properly, costs nothing to run.

Build vs. Buy

Subscription tools sell convenience. You get stuck with their limitations and their pricing. Building it yourself means full control, no monthly bills, and you can customize it however you need.

Feature Subscription Tool (e.g., YAMM) Google Apps Script (Build) The Bottom Line
Cost ~$40 - $400 USD/year $0 (Included with Google account) Build it once. Zero running cost.
Quota Tied to a paid tier Your native Google limit (100/day consumer, 1,500/day Workspace via MailApp) Maximize the tools you already own. You control the code that consumes the quota.
Customization Limited to UI features Unlimited (Full JavaScript/V8 runtime access) Total control over workflow, error handling, and email content (HTML, attachments).
Execution Limit N/A 6 mins/run (consumer), 30 mins/run (Workspace) Requires smart batch processing for large lists, which this script includes.

Apps Script runs on Google's servers and uses the native MailApp class, which means it uses your Gmail quota directly. You get real error handling and can control batching—something a third-party add-on can't.

How It Works

The script does four things:

  1. Reads your contact data from the Sheet in one call
  2. Loops through each row, personalizing your email template
  3. Sends via your Gmail account
  4. Marks each row as "SENT" or "ERROR" so it doesn't duplicate

It also stops gracefully when you hit your daily quota and can resume later.

The Core Script: Building the Engine

Prerequisites

  1. Permissions: You need editor access to the Google Sheet.
  2. Sheet Structure: Your active sheet must have headers in Row 1. Mandatory columns: Email and Status. You can add others like Name or Company.
  3. OAuth Scopes: The script requires authorization. When you first run it, a pop-up will ask for permission.

Setup & Code

  1. Open your Google Sheet.
  2. Go to Extensions > Apps Script.
  3. Delete any placeholder code and paste the following.
  4. Save the project.
/**
 * Adds a custom menu to the active spreadsheet.
 */
function onOpen() {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu('Mail Merge')
      .addItem('Send Emails', 'sendEmails')
      .addToUi();
}
 
/**
 * Sends emails based on the active sheet data.
 */
function sendEmails() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const dataRange = sheet.getDataRange();
  const data = dataRange.getValues();
  
  // Identify column indices (0-based)
  const headers = data[0];
  const emailCol = headers.indexOf('Email');
  const statusCol = headers.indexOf('Status');
  const nameCol = headers.indexOf('Name'); // Optional
  
  if (emailCol === -1 || statusCol === -1) {
    SpreadsheetApp.getUi().alert('Error: "Email" and "Status" columns are required.');
    return;
  }
  
  const subject = "Update regarding your account"; // Custom subject line
  
  // Iterate through rows (skipping header)
  for (let i = 1; i < data.length; i++) {
    const row = data[i];
    const email = row[emailCol];
    const status = row[statusCol];
    const name = nameCol !== -1 ? row[nameCol] : "Customer";
    
    // Skip if already sent or email is empty
    if (status === 'SENT' || !email) {
      continue;
    }
    
    // Check Quota
    if (MailApp.getRemainingDailyQuota() < 1) {
      sheet.getRange(i + 1, statusCol + 1).setValue('QUOTA_LIMIT_REACHED');
      break; 
    }
    
    try {
      // Send Email
      MailApp.sendEmail({
        to: email,
        subject: subject,
        htmlBody: `
          <p>Hi ${name},</p>
          <p>This is a personalized update just for you.</p>
          <p>Best,<br>Mereth Team</p>
        `
      });
      
      // Mark as Sent
      sheet.getRange(i + 1, statusCol + 1).setValue('SENT');
      SpreadsheetApp.flush(); // Force update UI
      
    } catch (e) {
      sheet.getRange(i + 1, statusCol + 1).setValue('ERROR: ' + e.message);
    }
  }
  
  SpreadsheetApp.getUi().alert('Mail merge complete.');
}

How to Run It

  1. To run it, refresh your spreadsheet.
  2. A new "Mail Merge" menu will appear after a few seconds.
  3. Click Mail Merge > Send Emails.
  4. The first time, you must grant permission to access your Sheet and send email on your behalf.

How to Avoid the "Daily Limit Exceeded" Error

The core technical constraint is Google's daily email quota. For Apps Script's MailApp service, this is 100 recipients/day for consumer Gmail accounts and 1,500 recipients/day for Google Workspace accounts.

Here is how the script handles this constraint:

  1. Mandatory State Management: The Status column is the source of truth. If the script stops for any reason, it restarts without emailing the same person twice.
  2. Proactive Quota Checks: MailApp.getRemainingDailyQuota() prevents the script from failing on a quota error.
  3. Use Time-Based Triggers for Large Lists: For lists over a few hundred contacts, set a time-driven trigger to run this function hourly. It will chip away at the list safely within limits.

Next Steps: Build It or Ship It

You now have a reliable, free mail merge system.

The code's above. Build it yourself this weekend.

Newsletter

Get more tips like this

Subscribe for practical Google Workspace automation tips.

Free updates. No spam. Unsubscribe any time.

Want more help?

We're here to help. Drop us an email and let's explore how we can optimize your workflows.

Email us

hello@mereth.dev

Google Workspaceautomation high ROIGoogle Apps Scriptbusiness efficiencylow-code workflow optimizationAutomation opportunitiesMail MergeGoogle SheetYAMM