Automation

Google Apps Script Email Recipient Quotas Per Day

Marc SeanOctober 13, 20266 min read

Google also limits each message to 50 recipients. Before scheduling a send, check the official Apps Script quota table, as Google can change these limits without notice.

QuotaConsumer accountGoogle Workspace
Email recipients per day1001,500
Within-domain recipients per day1002,000
Recipients per message5050

The 2,000 figure is a separate within-domain allowance, not the general Workspace daily limit. Confirm which quota applies to your recipient mix, and don't assume the general and within-domain limits can be added together.

Recipients and messages are separate counts

The daily quota counts recipients rather than messages. One message addressed to three email addresses across To, Cc, and Bcc uses three planned recipient deliveries.

Meanwhile, the 50-recipient limit applies separately to each message. A message with 51 recipients exceeds that limit even if daily capacity remains. Multiple smaller messages can stay below 50 recipients individually while collectively exceeding the daily quota.

Exceeding an applicable quota can cause the script to throw an exception and stop. Workspace trial accounts also have additional restrictions. Google says limits increase after conversion to a paid account only when the domain has cumulatively paid at least USD 100 for Google services and 60 days have passed since reaching that threshold.

Audit a 10,000-row recipient plan in Google Sheets

The Synthetic 10,000-row recipient audit compares planned recipient occurrences with quota scenarios and identifies messages containing more than 50 recipient rows.

Copy this Google Sheets template or download the Excel file. The data is synthetic. The workbook sends no email, doesn't query a live quota, and doesn't verify deliverability.

1. Review recipient rows

Open Recipient audit!A1:I10001. Its schema is:

ColumnContents
AMessage ID
BRecipient field: To, CC, or BCC
CRaw synthetic address
DNormalized address
EBasic syntax result
FInternal or external classification
GFirst occurrence of a valid normalized identity
HPlanned valid delivery
IRow review flag

For example, D2 normalizes the raw address with:

=LOWER(TRIM(C2))

Inspect the message ID in A2, recipient field in B2, raw address in C2, normalized address in D2, syntax result in E2, and review flag in I2. Resolve every REVIEW row. Although the syntax check can identify obvious problems, it can't determine whether a mailbox exists or will accept a message.

2. Reconcile the audit summary

Next, open Audit summary!A1:B21 and inspect B2:B16.

Actual Google Sheets recipient audit summary with occurrences, identities, and quota warnings

Synthetic native Google Sheets check; no email sent or live quota queried.

The restored baseline contains:

CellResult
B2 Input rows10,000
B3 Basic-syntax-pass occurrences9,800
B4 Missing addresses100
B5 Syntax-review rows100
B6 Internal occurrences7,900
B7 External occurrences1,900
B8 Distinct valid normalized addresses4,900
B9 Planned valid deliveries9,800
B15 Rows requiring review200

These totals reconcile: 9,800 basic-pass occurrences plus 100 missing addresses and 100 syntax-review rows equal 10,000 inputs. The internal and external occurrences also total 9,800.

Set B16 to your internal email domain. The fixture uses demo.invalid. In a recorded check, changing the domain to example.org changed the internal and external counts to 1,900 and 7,900. Restoring demo.invalid returned the baseline.

Compare the quotas with all 9,800 planned delivery occurrences, not only the 4,900 distinct normalized addresses. These totals show repeated addresses, but they don't establish that every address occurs exactly twice. Each occurrence in a separate send can consume recipient capacity.

3. Find messages over 50 recipients

Now inspect Message audit!A2:D201. In the restored baseline:

  • M-001 has 51 raw recipient rows and is marked OVER 50.
  • M-200 has 49 raw recipient rows and is marked WITHIN 50.
  • Audit summary!B14 reports one message over the limit.

To reproduce the boundary check, change Recipient audit!A52 from M-001 to M-200. Both raw message sizes become 50, and Audit summary!B14 falls from one to zero. Restore A52 to M-001 afterward.

Raw rows remain relevant to the message-size review even when an address fails the basic syntax screen. Treat invalid addresses as issues requiring review, not as a reason to ignore a message with too many recipient rows.

4. Compare planned occurrences with cap scenarios

Audit summary!B10 and B11 are editable planning caps, with restored values of 100 and 1,500. Because B9 contains 9,800 planned valid deliveries, both B12 and B13 return OVER CAP.

These cells are planning inputs, not live measurements of an account's remaining quota. If the separate 2,000 within-domain Workspace quota applies to a send, evaluate it as another confirmed scenario instead of treating 1,500 as the only Workspace figure.

5. Reject invalid cap inputs

Cap inputs must be numeric, nonnegative integers. B12 uses:

=IFERROR(IF(AND(ISNUMBER(B10),B10>=0,B10=INT(B10)),IF(B9>B10,"OVER CAP","WITHIN CAP"),"INVALID CAP"),"INVALID CAP")

B13 applies the same guard to B11:

=IFERROR(IF(AND(ISNUMBER(B11),B11>=0,B11=INT(B11)),IF(B9>B11,"OVER CAP","WITHIN CAP"),"INVALID CAP"),"INVALID CAP")

Recorded native Google Sheets checks produced these results:

  • Blank, whitespace, ordinary text, numeric text such as '9800, negative values, and fractions returned INVALID CAP.
  • Zero was accepted as a valid cap and returned OVER CAP.
  • A cap of exactly 9,800 returned WITHIN CAP.
  • A cap of 9,799 returned OVER CAP.

After testing, the baseline values of 100 and 1,500 were restored. Spreadsheet locales that use semicolons as argument separators may require semicolons instead of commas. The Excel download contains the formulas, but the supplied evidence doesn't establish execution in the Excel interface.

Check the remaining quota at execution time

For a script you control, MailApp.getRemainingDailyQuota() reports the remaining recipient quota available to the current execution:

const remainingRecipients = MailApp.getRemainingDailyQuota();
Logger.log(remainingRecipients);

This code contains no send call. It doesn't reserve capacity, increase the quota, or guarantee that a later execution will receive the same result. Check the quota near execution time, then stop the workflow if the remaining amount can't cover the next message.

Frequently Asked Questions