A Google Apps Script that archives your Gmail into a searchable Google Sheet. Works with any Gmail account — personal, Google Workspace, or enterprise.
Gmail has no built-in way to export your email to a spreadsheet. Google Takeout gives you an MBOX file, which isn't searchable without extra tools (and isn't available on all Workspace accounts). This script creates a Google Sheet you can search, filter, sort, and share — directly in your Drive.
A Google Sheet with one row per message, containing:
| Column | Description |
|---|---|
| Date | Send date/time |
| From | Sender name |
| From Email | Sender email address |
| To | Recipients |
| CC | CC recipients |
| Subject | Email subject line |
| Snippet | First ~200 chars of the message |
| Body | Full plain-text body (optional, configurable) |
| Labels | Gmail labels on the thread |
| Starred | Whether the message is starred |
| Unread | Whether the message is unread |
| Attachment Names | Names of attached files |
| Thread ID | Gmail thread ID |
| Message ID | Gmail message ID |
The sheet is auto-formatted with frozen headers, column filters, and date sorting.
- Go to script.google.com (log in with the Gmail account you want to archive)
- Click New Project
- Delete the placeholder code and paste the contents of
GmailArchiver.gs - Save (Ctrl+S / Cmd+S)
- In the function dropdown at the top, select
archiveInbox - Click Run (▶)
- Google will ask you to authorize — click "Review Permissions" → choose your account → "Allow"
- The script runs and creates a sheet called "Gmail Archive - Inbox" in your Drive
That's it. Open the sheet and use Ctrl+F or the column filter dropdowns to search.
Select any of these from the function dropdown and run them directly:
| Function | What it archives |
|---|---|
archiveInbox |
All Inbox messages |
archiveSent |
All Sent messages |
archiveAllMail |
Everything (inbox, sent, archived, drafts) |
archiveUnread |
Unread messages only |
archiveStarred |
Starred messages only |
archiveWithAttachments |
Messages that have attachments |
archiveCustomQuery |
Any custom Gmail search query (edit the query in the function) |
- Paste
GmailArchiver.gsinto a new Apps Script project, selectarchiveInbox, and click Run — after authorizing, a formatted Google Sheet appears with one row per message, sortable columns, and frozen headers. - Select
archiveSentand run it — a second pass adds your sent messages; compare the "From" column to see both sides of a thread. - Edit
CONFIG.QUERYtofrom:boss@company.com after:2024/01/01and runarchiveCustomQuery— only matching messages appear; any valid Gmail search syntax works here. - Let it run on a large mailbox (1,000+ messages) — when the 6-minute Apps Script limit approaches, it saves progress to a
_Metasheet and stops cleanly; run it again to resume exactly where it left off. - Add a column filter on "Has Attachments" in the sheet, then filter to TRUE — instantly see every email with an attachment alongside the file names in the "Attachment Names" column.
The CONFIG.QUERY field accepts any Gmail search syntax. Some examples:
from:boss@company.com → emails from a specific person
after:2024/01/01 before:2025/01/01 → date range
has:attachment filename:pdf → PDFs only
subject:"quarterly report" → subject line search
from:me to:client@example.com → emails you sent to someone
is:unread label:important → unread important messages
larger:5M → messages over 5MB
Edit the archiveCustomQuery function, or modify CONFIG.QUERY directly at the top of the script.
Google Apps Script enforces a 6-minute execution limit per run. This script handles it automatically:
- Before hitting the limit, it saves progress to a hidden
_Metasheet - It schedules a continuation trigger to run ~1 minute later
- The next run picks up exactly where it left off (no duplicates)
- When all messages are processed, it cleans up and formats the sheet
A mailbox with 10,000 messages typically completes in 3–5 automatic runs. You don't need to do anything — just let it work.
All options are in the CONFIG object at the top of the script:
const CONFIG = {
QUERY: 'in:inbox', // Gmail search query
SHEET_NAME: 'Gmail Archive', // Name of the output spreadsheet
BATCH_SIZE: 100, // Threads per API call (max 500)
MAX_RUNTIME_MS: 5 * 60000, // Stop before 6-min limit
INCLUDE_BODY: true, // Include full message body (slower if true)
BODY_MAX_LENGTH: 5000, // Truncate body text per message
INCLUDE_BCC: false, // Include BCC column
AUTO_CONTINUE: true, // Auto-schedule continuation runs
CONTINUE_DELAY_MS: 60000, // Delay between continuation runs
};Setting INCLUDE_BODY: false significantly speeds up the archive if you only need metadata for searching.
| Function | What it does |
|---|---|
checkProgress |
Logs the current status and message count of a running archive |
stopArchive |
Cancels scheduled continuation triggers without deleting the sheet |
resetArchive |
Trashes the existing archive sheet and removes triggers so you can start fresh |
If the script is interrupted (lost internet, closed the tab, hit an error), just run it again. It reads the existing sheet, identifies which messages are already archived by Message ID, and continues from where it stopped. No duplicates.
The script requests these Google API scopes:
- Gmail (read-only) — to read your messages
- Google Sheets — to create and write to the archive spreadsheet
- Google Drive — to check if an archive sheet already exists
It does not modify, delete, or send any emails. It only reads.
- 6-minute execution limit: handled automatically via continuation triggers, but very large mailboxes (50k+) will take many runs
- Google Sheets cell limit: Sheets has a 10 million cell limit. At ~15 columns per row, that's ~660k messages before hitting the cap. For mailboxes larger than that, consider setting
INCLUDE_BODY: falseor splitting into multiple archives by date range - Body text only: the script extracts plain-text bodies, not HTML. Rich formatting, inline images, and embedded content are not preserved
- Attachments not downloaded: attachment names are listed, but the files themselves are not saved. You could extend the script to save them to Drive if needed
- Workspace admin restrictions: some Google Workspace admins disable Apps Script or restrict OAuth scopes. If you can't authorize the script, check with your IT admin
MIT — do whatever you want with it.