How to save Gmail emails to Notion
Short answer: Gmail™ and Notion do not file emails into each other by themselves. You can copy and paste an email into a Notion page, let an automation service create a database item for new emails that match a rule, or run a short Apps Script that sends labelled emails to a Notion database through Notion’s API. A Gmail add-on such as StashLane saves the email you are reading with one click, the subject, sender, date and Gmail link already in your database’s fields.
1. By hand: copy and paste
- In Notion, open the database and add a new page.
- In Gmail, select the text of the email, copy it, and paste it into the page.
- Fill in the properties yourself: the sender, the date, a status.
- For a way back to the email, copy the link from the browser’s address bar while the email is open, and paste it into a URL property. It opens only in your own Gmail account.
- For attachments, download each file from Gmail and drag it onto the page.
It is free and needs nothing installed. It is also five steps per email, and the fields are only as consistent as your copying. For an email you want to keep exactly as it looked, Gmail’s print button and your browser’s Save as PDF make a PDF you can drop into the page.
2. An automation service
Automation services such as Zapier and Make connect Gmail to Notion: a rule such as “a new email gets the label Invoices” creates an item in a Notion database, with the fields you map once. It runs without you, which suits a steady stream of similar emails.
It works on emails that match the rule, not on the one you happen to be reading, so saving a single email means labelling it first. What goes along (the full text, the attachments, a link back) and what it costs depend on the service and the plan. You also give a third service access to your mailbox and your Notion workspace.
3. A free Apps Script: labelled emails to a Notion database
If you are comfortable with a little code, Google Apps Script can do it in your own account. The script below saves every conversation with the Gmail label To Notion to a Notion database, then removes the label.
- In Notion, open the integrations page for developers (
notion.so/my-integrations), create an internal integration for your workspace, and copy its secret. - Open your database in Notion, click ••• at the top right, and add your integration under Connections. Without this, the API cannot see the database.
- In Gmail, create the label
To Notion. - Go to
script.google.com, create a project, paste the code below and put your secret inNOTION_TOKEN. - Run
listDataSourcesonce. The log lists the databases your integration can see, each with an ID. Put the ID of yours inDATA_SOURCE_ID. - Label an email
To Notionand runsaveLabelledEmails. The first time, Google asks you to allow the script to read your Gmail and connect to an external service.
const NOTION_TOKEN = 'ntn_...'; // your integration's secret
const DATA_SOURCE_ID = '...'; // from listDataSources()
const TITLE = 'Name'; // the title property of your database
function listDataSources() {
const r = notion('/search', { filter: { property: 'object', value: 'data_source' } });
r.results.forEach(d => {
const t = Array.isArray(d.title) ? d.title.map(x => x.plain_text).join('') : d.title;
console.log(d.id + ' ' + t);
});
}
function saveLabelledEmails() {
const label = GmailApp.getUserLabelByName('To Notion');
if (!label) return;
label.getThreads(0, 20).forEach(thread => {
const m = thread.getMessages()[0];
const text = s => [{ type: 'text', text: { content: String(s).slice(0, 2000) } }];
notion('/pages', {
parent: { type: 'data_source_id', data_source_id: DATA_SOURCE_ID },
properties: { [TITLE]: { title: text(m.getSubject() || '(no subject)') } },
children: [
{ object: 'block', type: 'quote', quote: { rich_text: text('From: ' + m.getFrom() + '\nDate: ' + m.getDate()) } },
{ object: 'block', type: 'paragraph', paragraph: { rich_text: text(m.getPlainBody()) } }
]
});
thread.removeLabel(label);
});
}
function notion(path, body) {
const res = UrlFetchApp.fetch('https://api.notion.com/v1' + path, {
method: 'post', contentType: 'application/json', payload: JSON.stringify(body),
headers: { Authorization: 'Bearer ' + NOTION_TOKEN, 'Notion-Version': '2026-03-11' }
});
return JSON.parse(res.getContentText());
}
To make it run by itself, open Triggers (the clock icon) in the editor, add a trigger for saveLabelledEmails, and choose Time-driven with a timer such as every 15 minutes or every hour.
4. Where the simple script falls short
- Only 2,000 characters. Notion takes at most 2,000 characters in one piece of text, so the script cuts long emails. Keeping all of it means splitting the text into many blocks, and sending more than 100 blocks in later requests.
- Only the title. Every other property (the sender as an email, the date as a date, a status) needs its own code, written for the types of your database, and changed whenever the database changes.
- No attachments. Uploading files to Notion is a separate, multi-step API call per file, with size limits to check.
- The first email only. A conversation needs a loop over every message, with a heading for each.
- Your secret sits in the code. Anyone who can open the script can use your integration on the databases you connected.
- Errors go quietly. If Notion refuses a page, the script stops; Google emails a failure summary to the person who made the trigger, by default once a day.
- Labelling is a step too. The script saves what you label, later, not the email in front of you now.
None of this is hard on its own. Together, it is a small program to look after.
5. With a Gmail add-on: StashLane
StashLane is our Gmail add-on for this job. It works on the email you have open, in the side panel next to it:
- Connect Notion once through Notion’s own window, selecting the databases StashLane may use. It cannot see the rest of your workspace.
- Pick a database and press Save to Notion. The page gets the subject as its title (or the title you type), a quote with From, To, Cc and the date, an Open in Gmail link and, if you like, the whole email text, split to fit Notion’s limits.
- Your fields filled in. Under Fields…, choose for each property the subject, the sender’s name or address, To, Cc, the date received or saved, the Gmail link, the first lines or the attachment names. It works with text, email, URL, date, select, status, multi-select, number, checkbox, phone and files properties.
- Already saved shows when you open an email you saved before, with a link to its page.
- Save as PDF to Google Drive™, free: a PDF of the email in a StashLane folder of your Drive.
- Pro, for $4.99 a month or $39 a year: unlimited saves, attachments uploaded to Notion (up to 20 MB each), a whole conversation on one page, and fixed values such as Status = To do.
- It reads only the email you open it on, and the email goes straight from Google to your Notion; nothing passes through a BiLingoPlus server.
30 saves a month are free. How to set it up: StashLane help.
Questions
Can I save a Gmail email to Notion for free?
Yes. Copy and paste is free, and so is a short Apps Script that uses Notion’s API with your own integration. The StashLane add-on saves 30 emails a month free.
How do I keep a link from the Notion page back to the email?
In Gmail on the web, the address bar holds a link to the open email; paste it into a URL property. It opens only in your own Gmail account. A script or add-on can add the link for you.
How do I get Gmail attachments into Notion?
By hand, download each file and drag it onto the Notion page. Notion’s API can also take file uploads, which is how scripts and add-ons such as StashLane Pro attach them.
Can I save a whole email conversation on one Notion page?
Yes. By hand, paste the emails one after another. In a script, loop over thread.getMessages(). StashLane Pro has a switch for it.