Last active
October 1, 2025 20:50
-
-
Save eudamniac/77577ea58eaf2a9b91cee8ca78c0a6f0 to your computer and use it in GitHub Desktop.
reMarkable to Notion Sync
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const GMAIL_LABEL_NAME = 'NotionToSync'; | |
| const SYNCED_LABEL = 'SyncedToNotion'; | |
| // if you set this, the attachments will be copied over to google drive and the links added to the notion page | |
| const GDRIVE_FOLDER_ID = ''; | |
| const gmailToNotion = () => { | |
| const label = GmailApp.getUserLabelByName(GMAIL_LABEL_NAME); | |
| const successLabel = GmailApp.getUserLabelByName(SYNCED_LABEL); | |
| label.getThreads(0, 20).forEach((thread) => { | |
| const [message] = thread.getMessages().reverse(); | |
| postToNotion(message); | |
| thread.removeLabel(label); | |
| thread.addLabel(successLabel) | |
| }); | |
| }; | |
| function getRichTextChunks(messageBody) { | |
| let remainingString = messageBody; | |
| const content = []; | |
| while (remainingString.length > 0) { | |
| // https://developers.notion.com/reference/request-limits#limits-for-property-values | |
| if (remainingString.length <= 2000) { | |
| content.push(getRichTextObjectForChunk(remainingString)); | |
| remainingString = ''; | |
| } else { | |
| const maximalChunk = remainingString.substring(0, 2000); | |
| const lastLineBreakInChunk = maximalChunk.lastIndexOf('\n'); | |
| const actualChunk = remainingString.substring(0, lastLineBreakInChunk); | |
| content.push(getRichTextObjectForChunk(actualChunk)); | |
| remainingString = remainingString.substring(lastLineBreakInChunk + 1); | |
| } | |
| } | |
| return content; | |
| } | |
| function getRichTextObjectForChunk(messageChunk) { | |
| return { | |
| type: 'text', | |
| text: { | |
| content: messageChunk | |
| }, | |
| } | |
| } | |
| function getPdfBlocksForAttachments(message) { | |
| var attachments = message.getAttachments(); | |
| var pdfBlocks = []; | |
| for (var k = 0; k < attachments.length; k++) { | |
| Logger.log('Message contains the attachment "%s" (%s bytes)', attachments[k].getName(), attachments[k].getSize()); | |
| var folder = DriveApp.getFolderById(GDRIVE_FOLDER_ID); | |
| var ts = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyMMddHHmmss"); | |
| var createdFile = folder.createFile(attachments[k].copyBlob()).setName(attachments[k].getName() + ts); | |
| pdfBlocks.push({ | |
| "object": "block", | |
| "type": "paragraph", | |
| "paragraph": { | |
| "rich_text": [ | |
| { | |
| "type": "text", | |
| "text": { | |
| "content": attachments[k].getName(), | |
| "link": { | |
| "url": createdFile.getUrl() | |
| } | |
| }, | |
| "annotations": { | |
| "bold": false, | |
| "italic": false, | |
| "strikethrough": false, | |
| "underline": false, | |
| "code": false, | |
| "color": "default" | |
| }, | |
| "plain_text": attachments[k].getName(), | |
| "href": createdFile.getUrl() | |
| } | |
| ], | |
| "color": "default" | |
| } | |
| }) | |
| } | |
| } | |
| function postToNotion(message) { | |
| const richTextChunks = getRichTextChunks(message.getPlainBody()); | |
| const pdfBlocks = GDRIVE_FOLDER_ID ? getPdfBlocksForAttachments(message) : []; | |
| const url = 'https://api.notion.com/v1/pages'; | |
| const body = { | |
| parent: { | |
| type: "database_id", | |
| database_id: "<Your Target Notion Database Id>", | |
| }, | |
| icon: { | |
| type: "emoji", | |
| emoji: "📝" | |
| }, | |
| children: [ | |
| ...pdfBlocks, | |
| { | |
| object: 'block', | |
| type: 'paragraph', | |
| paragraph: { | |
| rich_text: richTextChunks, | |
| }, | |
| } | |
| ], | |
| properties: { | |
| Name: { | |
| title: [ | |
| { | |
| text: { | |
| content: message.getSubject(), | |
| }, | |
| }, | |
| ], | |
| } | |
| } | |
| } | |
| UrlFetchApp.fetch(url, { | |
| method: 'post', | |
| contentType: "application/json", | |
| muteHttpExceptions: false, | |
| headers: { | |
| Authorization: `Bearer <Your Notion Secret>`, | |
| 'Notion-Version': '2022-02-22' | |
| }, | |
| payload: JSON.stringify(body) | |
| }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've created an updated fork that is working with pdfs, pngs and svgs uploaded directly into Notion
https://gist.github.com/powmod/f248ab6147d0664a96da5e448e0622eb