Updated October 2026 · 7 minute read
If you already keep invoices in Google Sheets, you don’t need new software to email them. A short Apps Script can email every invoice you mark as ready, log the date it went out and chase overdue ones automatically. Here is the full script, copy and paste, with setup steps and the limits to know about.
- Tool: Google Apps Script, built into Sheets under Extensions → Apps Script.
- Send:
MailApp.sendEmailemails each row marked Ready, then marks it Sent.1 - Automate: a daily time-driven trigger runs it for you.2
- Limit: 100 recipients a day on gmail.com, 1,500 on Google Workspace.2
Set up the sheet
Name a tab Invoices and use these columns, with headers in row 1:
| Column | Header | Example |
|---|---|---|
| A | Invoice # | INV-1042 |
| B | Client | Maria |
| C | maria@example.com | |
| D | Amount | 240 |
| E | Due date | 11/15/2026 |
| F | Status | Ready, Sent or Paid (use a drop-down) |
| G | Sent on | filled in by the script |
| H | Reminder sent | filled in by the script |
A drop-down for Status (Data → Data validation) stops typos like “ready ” that the script would skip.
The script
Open Extensions → Apps Script, delete the empty function and paste this. Change Your Business Name to yours.
function sendInvoiceEmails() {
const sh = SpreadsheetApp.getActive().getSheetByName('Invoices');
const last = sh.getLastRow();
if (last < 2) return; // no invoices yet
const rows = sh.getRange(2, 1, last - 1, 7).getValues();
const tz = Session.getScriptTimeZone();
rows.forEach((r, i) => {
const [inv, client, email, amount, due, status] = r;
if (status !== 'Ready' || !email) return; // only rows marked Ready
if (MailApp.getRemainingDailyQuota() < 1) return;
const dueTxt = Utilities.formatDate(new Date(due), tz, 'MMM d, yyyy');
const amt = Number(amount).toFixed(2);
const body = '<p>Hi ' + client + ',</p>' +
'<p>Invoice <b>' + inv + '</b> for <b>$' + amt + '</b> is due on <b>' + dueTxt + '</b>.</p>' +
'<p>Thank you for your business.</p>';
MailApp.sendEmail({
to: email,
subject: 'Invoice ' + inv + ' - $' + amt + ' due ' + dueTxt,
htmlBody: body,
name: 'Your Business Name'
});
sh.getRange(i + 2, 6, 1, 2).setValues([['Sent', new Date()]]);
});
}It reads every row, emails only rows with Status Ready and an email address, and writes Sent plus the date into columns F and G straight away so the invoice is never sent twice. It also stops if your daily email quota runs out, using MailApp.getRemainingDailyQuota().1
Test it first: put your own email address on one row, set it to Ready and click Run. Google will ask you to authorise the script to send email as you; approve it for your own account.
Add overdue reminders
Paste this second function under the first. It emails one reminder for any invoice still marked Sent after its due date, then writes the date into column H. When a client pays, change their Status to Paid and they drop out.
function sendOverdueReminders() {
const sh = SpreadsheetApp.getActive().getSheetByName('Invoices');
const last = sh.getLastRow();
if (last < 2) return;
const rows = sh.getRange(2, 1, last - 1, 8).getValues();
const today = new Date(); today.setHours(0, 0, 0, 0);
rows.forEach((r, i) => {
const [inv, client, email, amount, due, status, sentOn, reminded] = r;
if (status !== 'Sent' || reminded || !email) return;
if (new Date(due) >= today) return; // not overdue yet
if (MailApp.getRemainingDailyQuota() < 1) return;
MailApp.sendEmail({
to: email,
subject: 'Reminder: invoice ' + inv + ' is past due',
htmlBody: '<p>Hi ' + client + ',</p><p>A quick reminder that invoice <b>' + inv +
'</b> for <b>$' + Number(amount).toFixed(2) + '</b> is now past due.</p>',
name: 'Your Business Name'
});
sh.getRange(i + 2, 8).setValue(new Date()); // column H: reminder sent
});
}Run it every day
- In the Apps Script editor, click the clock icon (Triggers) on the left.
- Click Add Trigger.
- Choose
sendInvoiceEmails, event source Time-driven, type Day timer, and a time such as 8 to 9am. - Save, then add a second trigger for
sendOverdueReminders.
Now you only fill in a row and pick Ready; the email goes out the next morning. Google allows 20 triggers per user per script and limits total trigger runtime to 90 minutes a day on gmail.com accounts, far more than this script needs.2
Limits and good habits
| Limit | gmail.com | Google Workspace |
|---|---|---|
| Email recipients per day | 100 | 1,500 |
| Script runtime per execution | 6 minutes | 6 minutes |
| Total trigger runtime per day | 90 minutes | 6 hours |
| Triggers | 20 per user per script | 20 per user per script |
Source: Google Apps Script quotas, accessed October 2026.2
- Send from a business address with Google Workspace if you can; invoices from a personal gmail.com address look less professional.
- Include a payment link in the email body so clients can pay straight away.
- Keep the Status column honest: Ready, Sent, Paid. It doubles as your accounts receivable list.
- Back up the sheet before editing the script, and test changes on your own email first.
Want this built and tested for you?
We set up Google Sheets and Excel automations like this one, including PDF invoices, payment links and reminders, at a fixed price agreed before we start.
Questions
Can Google Sheets send emails automatically?
Yes. A short Google Apps Script attached to the sheet can send an email for each row with MailApp.sendEmail, and a time-driven trigger can run it every day without you opening the file.
How many emails can Apps Script send per day?
Google’s quota is 100 email recipients a day for a personal gmail.com account and 1,500 a day for a Google Workspace account. MailApp.getRemainingDailyQuota() tells you how many you have left.
Can I attach the invoice as a PDF?
Yes, MailApp.sendEmail accepts an attachments option. Creating a PDF of each invoice takes a few more lines of script, so you can start with the email summary and a payment link, then add PDFs later.
Will the script send the same invoice twice?
Not with the setup on this page. It only emails rows marked Ready and changes them to Sent with a date straight after, so the next run skips them.
Do I need to pay for Google Workspace?
No. The script works on a free Google account, within the 100 recipients a day limit. Workspace raises the limit and lets you send from your business domain.
Related guides
Sources
- Google Apps Script: Class MailApp
- Google Apps Script: Quotas for Google Services, accessed October 2026
Tahir Abbas
Founder of Softotech Solutions. Tahir builds Excel and Google Sheets automations for small businesses, from invoice emails to full reporting. Quotas come from Google’s documentation, which can change; check it if you send large volumes.


