Scroll to Top
Published on September 22, 2025 Updated on September 22, 2025

Google Sheets to Email...

Author Avatar
Ashish Dwivedi
Editorial Team

Google Sheets to Email Automation

Google Sheets to Email automation lets you send personalized emails directly from a Google Sheet. By linking data with Gmail (using Apps Script or add-ons), you can automate updates, reminders, or campaigns. It saves time, ensures accuracy, and streamlines communication without manual copy-paste tasks..
  1. Step 1: Click on the Copy button to copy the code snippet.
  2. Step 2: Paste the copied code into your project’s script editor.

Apps Scripts Blog

Read Blog

Apps Scripts Code

// =====================
// RUN ON SHEET OPEN
//dataUpdateScript.gs
// =====================
// DATA UPDATE SCRIPT
// =====================

// === MAIN FUNCTION ===
function updateSelectedCells(dateValue) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var rangeList = sheet.getActiveRangeList();

  if (!rangeList) {
    return "⚠️ No cells selected!";
  }

  var formattedDate = new Date(dateValue);
  var updatedCount = 0;

  var ranges = rangeList.getRanges();
  ranges.forEach(function(range) {
    var values = range.getValues();

    // === UPDATE CELLS ===
    for (var i = 0; i < values.length; i++) {
      for (var j = 0; j < values[i].length; j++) {
        var cellValue = values[i][j];
        if (cellValue === "" || cellValue instanceof Date) {
          values[i][j] = formattedDate;
          updatedCount++;
        }
      }
    }

    // === WRITE BACK UPDATED VALUES ===
    range.setValues(values);
  });

  // === RETURN STATUS ===
  if (updatedCount === 0) {
    return "No date fields found in selected range!";
  }
  return "✅ Updated " + updatedCount + " date cell(s) successfully!";
}





// === customEmail.html ===

Company Updates Email Template


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
      background: #f4f7fb;
      margin: 0;
      padding: 0;
      color: #333;
    }
    .container {
      max-width: 600px;
      margin: 30px auto;
      background: #ffffff;
      border-radius: 16px;
      box-shadow: 0 6px 18px rgba(0,0,0,0.1);
      overflow: hidden;
      animation: fadeInUp 0.6s ease;
    }
    .header {
      background: linear-gradient(135deg, #6a11cb, #2575fc);
      padding: 20px;
      text-align: center;
      color: white;
    }
    .header h1 {
      margin: 0;
      font-size: 22px;
      letter-spacing: 1px;
    }
    .body {
      padding: 30px;
      line-height: 1.6;
      font-size: 15px;
      color: #444;
    }
    .body h2 {
      font-size: 18px;
      margin-bottom: 15px;
      color: #6a11cb;
    }
    .attachments {
      margin-top: 25px;
      padding: 15px;
      background: #f9f9ff;
      border-left: 4px solid #6a11cb;
      border-radius: 10px;
      font-size: 14px;
      color: #555;
    }
    .attachments h3 {
      margin-top: 0;
      margin-bottom: 10px;
      font-size: 16px;
      color: #2575fc;
    }
    .attachments ul {
      padding-left: 20px;
      margin: 0;
    }
    .attachments li {
      margin-bottom: 6px;
    }
    .button {
      display: inline-block;
      background: linear-gradient(45deg, #6a11cb, #2575fc);
      color: white !important;
      padding: 12px 24px;
      border-radius: 8px;
      text-decoration: none;
      font-size: 15px;
      margin-top: 20px;
      transition: transform 0.2s;
    }
    .button:hover {
      transform: scale(1.05);
    }
    .footer {
      background: #f4f7fb;
      padding: 15px;
      text-align: center;
      font-size: 12px;
      color: #777;
    }
    @keyframes fadeInUp {
      from { transform: translateY(20px); opacity: 0; }
      to { transform: translateY(0); opacity: 1; }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>✨ Company Updates</h1>
    </div>
    <div class="body">
      <h2>Hello {{NAME}},</h2>
      <p>{{MESSAGE}}</p>

      {{ATTACHMENTS_SECTION}}

    </div>
    <div class="footer">
      © 2025 Your Company. All rights reserved.
    </div>
  </div>
</body>
</html>

//dateUpdateSidebar.gs
// =====================

Update Last Contact Date


<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <style>
    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      text-align: center;
    }
    h3 { color: #333; }
    input[type="date"] {
      padding: 10px;
      font-size: 16px;
      border: 2px solid #6a11cb;
      border-radius: 8px;
      outline: none;
    }
    .btn {
      background: linear-gradient(45deg, #6a11cb, #2575fc);
      color: white;
      border: none;
      padding: 12px 24px;
      font-size: 16px;
      border-radius: 8px;
      cursor: pointer;
      transition: transform 0.2s, box-shadow 0.2s;
      margin-top: 20px;
    }
    .btn:hover {
      transform: scale(1.1);
      box-shadow: 0px 4px 12px rgba(0,0,0,0.3);
    }
    #message {
      margin-top: 15px;
      font-size: 14px;
      font-weight: bold;
    }
    .success { color: green; }
    .error { color: red; }
  </style>
</head>
<body>

  <div>
    <h3>📅 Update Last Contact</h3>
    <input type="date" id="selectedDate" />
    <br>
    <button class="btn" onclick="updateDate()">Update Date</button>
    <div id="message"></div>
  </div>

  <script>
    function updateDate() {
      var dateValue = document.getElementById("selectedDate").value;
      var msg = document.getElementById("message");
      if (!dateValue) {
        msg.innerHTML = "<span class='error'>⚠️ Please select a date first!</span>";
        return;
      }
      msg.innerHTML = "⏳ Updating...";
      google.script.run.withSuccessHandler((res) => {
        msg.innerHTML = "<span class='success'>✅ " + res + "</span>";
      }).updateSelectedCells(dateValue);
    }
  </script>

</body>
</html>

// === dateUpdateSidebar.html ===

Update Date Sidebar Code


<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      body {
        font-family: Arial, sans-serif;
        padding: 20px;
        text-align: center;
      }
      h3 {
        color: #333;
      }
      input[type="date"] {
        padding: 10px;
        font-size: 16px;
        border: 2px solid #6a11cb;
        border-radius: 8px;
        outline: none;
      }
      .btn {
        background: linear-gradient(45deg, #6a11cb, #2575fc);
        color: white;
        border: none;
        padding: 12px 24px;
        font-size: 16px;
        border-radius: 8px;
        cursor: pointer;
        transition: transform 0.2s, box-shadow 0.2s;
        margin-top: 20px;
      }
      .btn:hover {
        transform: scale(1.1);
        box-shadow: 0px 4px 12px rgba(0,0,0,0.3);
      }
      #message {
        margin-top: 15px;
        font-size: 14px;
        font-weight: bold;
      }
      .success { color: green; }
      .error { color: red; }
    </style>
  </head>
  <body>
    <div>
      <h3>📅 Update Last Contact</h3>
      <input type="date" id="selectedDate" />
      <br>
      <button class="btn" onclick="updateDate()">Update Date</button>
      <div id="message"></div>
    </div>

    <script>
      function updateDate() {
        var dateValue = document.getElementById("selectedDate").value;
        var msg = document.getElementById("message");
        if (!dateValue) {
          msg.innerHTML = "<span class='error'>⚠️ Please select a date first!</span>";
          return;
        }
        msg.innerHTML = "⏳ Updating...";
        google.script.run.withSuccessHandler((res) => {
          msg.innerHTML = "<span class='success'>✅ " + res + "</span>";
        }).updateSelectedCells(dateValue);
      }
    </script>
  </body>
</html>

// === emailSidebar.html ===

Update Date Sidebar Code


<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      body {
        font-family: "Segoe UI", Arial, sans-serif;
        padding: 20px;
        text-align: center;
        background: #f9f9fb;
      }
      h3 {
        color: #333;
        margin-bottom: 15px;
      }
      input[type="date"] {
        padding: 12px;
        font-size: 16px;
        border: 2px solid #6a11cb;
        border-radius: 8px;
        outline: none;
        transition: border-color 0.2s, box-shadow 0.2s;
      }
      input[type="date"]:focus {
        border-color: #2575fc;
        box-shadow: 0px 0px 4px rgba(37,117,252,0.3);
      }
      .btn {
        background: linear-gradient(45deg, #6a11cb, #2575fc);
        color: white;
        border: none;
        padding: 12px 24px;
        font-size: 16px;
        border-radius: 8px;
        cursor: pointer;
        transition: transform 0.2s, box-shadow 0.2s;
        margin-top: 20px;
      }
      .btn:hover {
        transform: scale(1.05);
        box-shadow: 0px 4px 12px rgba(0,0,0,0.3);
      }
      #message {
        margin-top: 15px;
        font-size: 14px;
        font-weight: bold;
      }
      .success { color: green; }
      .error { color: red; }
    </style>
  </head>
  <body>
    <div>
      <h3>📅 Update Last Contact</h3>
      <input type="date" id="selectedDate" />
      <br>
      <button class="btn" onclick="updateDate()">Update Date</button>
      <div id="message"></div>
    </div>

    <script>
      function updateDate() {
        const dateValue = document.getElementById("selectedDate").value;
        const msg = document.getElementById("message");
        if (!dateValue) {
          msg.innerHTML = "<span class='error'>⚠️ Please select a date first!</span>";
          return;
        }
        msg.innerHTML = "⏳ Updating...";
        google.script.run.withSuccessHandler(res => {
          msg.innerHTML = "<span class='success'>✅ " + res + "</span>";
        }).updateSelectedCells(dateValue);
      }
    </script>
  </body>
</html>
  

//dateUpdateSidebar.gs
// =====================

Update Last Contact Date


<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <style>
    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      text-align: center;
    }
    h3 { color: #333; }
    input[type="date"] {
      padding: 10px;
      font-size: 16px;
      border: 2px solid #6a11cb;
      border-radius: 8px;
      outline: none;
    }
    .btn {
      background: linear-gradient(45deg, #6a11cb, #2575fc);
      color: white;
      border: none;
      padding: 12px 24px;
      font-size: 16px;
      border-radius: 8px;
      cursor: pointer;
      transition: transform 0.2s, box-shadow 0.2s;
      margin-top: 20px;
    }
    .btn:hover {
      transform: scale(1.1);
      box-shadow: 0px 4px 12px rgba(0,0,0,0.3);
    }
    #message {
      margin-top: 15px;
      font-size: 14px;
      font-weight: bold;
    }
    .success { color: green; }
    .error { color: red; }
  </style>
</head>
<body>

  <div>
    <h3>📅 Update Last Contact</h3>
    <input type="date" id="selectedDate" />
    <br>
    <button class="btn" onclick="updateDate()">Update Date</button>
    <div id="message"></div>
  </div>

  <script>
    function updateDate() {
      var dateValue = document.getElementById("selectedDate").value;
      var msg = document.getElementById("message");
      if (!dateValue) {
        msg.innerHTML = "<span class='error'>⚠️ Please select a date first!</span>";
        return;
      }
      msg.innerHTML = "⏳ Updating...";
      google.script.run.withSuccessHandler((res) => {
        msg.innerHTML = "<span class='success'>✅ " + res + "</span>";
      }).updateSelectedCells(dateValue);
    }
  </script>

</body>
</html>

// === emailSidebarScript.gs ===

Email Sidebar Script


function emailSidebarScript(data) {
  try {
    var subject = data.subject;
    var message = data.message;
    var attachments = data.attachments || [];

    if (!subject || !message) {
      throw new Error("Subject and message are required!");
    }

    var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    var headerRow = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];

    // Detect "Email" and "Name" columns from header
    var emailColIndex = headerRow.findIndex(h => h.toString().toLowerCase().includes("email")) + 1;
    var nameColIndex = headerRow.findIndex(h => h.toString().toLowerCase().includes("name")) + 1;

    if (emailColIndex === 0 || nameColIndex === 0) {
      throw new Error("Could not find 'Email' or 'Name' column in header row!");
    }

    // Convert attachments to blobs and generate HTML list
    var blobs = [];
    var attachmentListHtml = "";
    if (attachments.length > 0) {
      attachmentListHtml = '<div class="attachments"><h3>Attachments</h3><ul>';
      attachments.forEach(function(file) {
        var blob = Utilities.newBlob(
          Utilities.base64Decode(file.content),
          file.type,
          file.name
        );
        blobs.push(blob);
        attachmentListHtml += "<li>" + file.name + "</li>";
      });
      attachmentListHtml += "</ul></div>";
    }

    // Load email template
    var template = HtmlService.createTemplateFromFile("customEmail").getRawContent();

    var rangeList = sheet.getActiveRangeList();
    if (!rangeList) {
      throw new Error("⚠️ No cells selected!");
    }

    var sentCount = 0;
    var processedRows = new Set();

    // Process each selected range
    rangeList.getRanges().forEach(function(range) {
      var rowStart = range.getRow();
      var numRows = range.getNumRows();
      var numCols = range.getNumColumns();

      for (var i = 0; i < numRows; i++) {
        for (var j = 0; j < numCols; j++) {
          var rowNumber = rowStart + i;

          if (!processedRows.has(rowNumber)) {
            var email = sheet.getRange(rowNumber, emailColIndex).getValue();
            var name = sheet.getRange(rowNumber, nameColIndex).getValue() || "there";

            if (email && email.toString().includes("@")) {
              var htmlMessage = template
                .replace("{{NAME}}", name)
                .replace("{{MESSAGE}}", message)
                .replace("{{ATTACHMENTS_SECTION}}", attachmentListHtml || "");

              GmailApp.sendEmail(email, subject, "", {
                htmlBody: htmlMessage,
                attachments: blobs
              });

              sentCount++;
            }
            processedRows.add(rowNumber);
          }
        }
      }
    });

    if (sentCount === 0) {
      return "⚠️ No valid emails found in selected rows!";
    }
    return "✅ Sent " + sentCount + " email(s) successfully!";

  } catch (error) {
    throw new Error("Failed to send: " + error.message);
  }
}
  

// === menu.gs ===

Spreadsheet Sidebar Launcher


// =====================
// Adds a custom menu to launch sidebars
// =====================
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu("✨ My Tools")
    .addItem("Open Date Updater", "showDateSidebar")
    .addItem("Send Email", "showEmailSidebar")
    .addToUi();
}

// Show the "Update Last Contact" sidebar
function showDateSidebar() {
  var html = HtmlService.createHtmlOutputFromFile("dateUpdateSidebar")
    .setTitle("Update Last Contact");
  SpreadsheetApp.getUi().showSidebar(html);
}

// Show the "Send Email" sidebar
function showEmailSidebar() {
  var html = HtmlService.createHtmlOutputFromFile("emailSidebar")
    .setTitle("Send Email");
  SpreadsheetApp.getUi().showSidebar(html);
}