Skip to content

Instantly share code, notes, and snippets.

@astoiccoder
Last active March 18, 2023 13:06
Embed
What would you like to do?
reMarkable to Notion Sync
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)
});
}
@Ypolites
Copy link

Hi there !

Terrific idea. I tried it on my side (as your tutorial was very clear) unfortunaly I keep running in the error:

TypeError: Cannot read property 'getPlainBody' of undefined
postToNotion	@ rm.gs:36

I'm affraid I'm note enought of a programmer myself to solve this.
If you are disposed to help me it would be grand !

Cheers !

@astoiccoder
Copy link
Author

Hi @Ypolites, thanks for reaching out!
Your error message basically says, that the message object in line 36 is not there, which is probably caused by thread.getMessages() returning an empty array in line 8.
To verify this you could add this line console.log(JSON.stringify(thread.getMessages(), null, 2)); before line 8 and see what is printed in the output when you run the script again.
If the assumption is correct, it would print something like
11:13:59 AM Info []

To solve this my assumption would be that this is related to the threading feature of gmail. Would be interesting to know if you have the conversation view on or off (https://support.cloudhq.net/how-to-turn-off-threaded-conversations-in-gmail/).
If you could take a small screenshot of how the email looks in your inbox, it could be very helpful to find the issue.

In any case, I am happy to help :)

@emdsquared
Copy link

Hi, thanks so much for this! I use notion and a ReMarkable and this will make my life so much easier!

I am also struggling with an error message that I am not sure how to resolve - please can you help? Thanks :)

6:20:59 PM	Error	Exception: Request failed for https://api.notion.com returned code 400. Truncated server response: {"object":"error","status":400,"code":"validation_error","message":"body failed validation: body.children[0].paragraph.rich_text[0].text.content.le... (use muteHttpExceptions option to examine full response)
postToNotion	@ Code.gs:56
(anonymous)	@ Code.gs:9
gmailToNotion	@ Code.gs:7

@astoiccoder
Copy link
Author

Hi, thanks so much for this! I use notion and a ReMarkable and this will make my life so much easier!

I am also struggling with an error message that I am not sure how to resolve - please can you help? Thanks :)

6:20:59 PM	Error	Exception: Request failed for https://api.notion.com returned code 400. Truncated server response: {"object":"error","status":400,"code":"validation_error","message":"body failed validation: body.children[0].paragraph.rich_text[0].text.content.le... (use muteHttpExceptions option to examine full response)
postToNotion	@ Code.gs:56
(anonymous)	@ Code.gs:9
gmailToNotion	@ Code.gs:7

Hi @emdsquared, thanks for catching this - I actually always only send rather small converted notes, but I saw from your error message that the limits for the content was reached. You can view them here https://developers.notion.com/reference/request-limits#limits-for-property-values.
I updated this gist to chunk the message body now so that it will also work for larger messages.
In total the script can now handle messages of up to 2000*100 = 200.000 characters or 500kb message size total.
I manually copied the changes over from the working script, so I hope I didn't mess anything up. Let me know if it works when you get to try it :)

Cheers!

@emdsquared
Copy link

Hi @astoiccoder, thanks for responding so quickly! That now works perfectly! :)

@Barendgoes
Copy link

Hey @astoiccoder thanks for building this awesome automation!
I ran into a problem I'm afraid.
Exception: Request failed for https://api.notion.com returned code 404. Truncated server response: {"object":"error","status":404,"code":"object_not_found","message":"Could not find database with ID: 4019fcaa-ec18-4622-b464-7411e568e559. Make sur... (use muteHttpExceptions option to examine full response)

I've tried multiple times to make a new database and tried that ID but keeps giving me this error. Would you know what I'm doing wrong?

@Barendgoes
Copy link

Hey @astoiccoder thanks for building this awesome automation! I ran into a problem I'm afraid. Exception: Request failed for https://api.notion.com returned code 404. Truncated server response: {"object":"error","status":404,"code":"object_not_found","message":"Could not find database with ID: 4019fcaa-ec18-4622-b464-7411e568e559. Make sur... (use muteHttpExceptions option to examine full response)

I've tried multiple times to make a new database and tried that ID but keeps giving me this error. Would you know what I'm doing wrong?

Whoops sorry... Never mind, I forgot to add the Notion integration in the database in Notion. Now it works perfectly. :)

@diodon
Copy link

diodon commented Jan 26, 2023

Whoops sorry... Never mind, I forgot to add the Notion integration in the database in Notion. Now it works perfectly. :)

Hi @Barendgoes, I'm having the same error, but I don't get what you did. I created remarkable integration in connections and defined an empty database (no data source). But I still get the DB not found message. Could you please be more specific?

@Barendgoes
Copy link

Hi @diodon You also have to add the integration in the database you've created in Notion. So in Notion go to your created database and click on the 3 dots at the top right corner for settings. In there you'll find Connections, you can find your created Remarkable Integration there and have to select it. So that the Remarkable Integration is actually linked or has access to your database. That did the trick for me, hope this helps for you as well!

@crushcup
Copy link

crushcup commented Mar 9, 2023

Hi @astoiccoder , thanks for pulling this all together. I can't wait to start using this to stay organized. Couple issues arose:

The PDF is being sent to my gmail, but the document does not make it to the notion, only the Subject.
Only 1 page of the PDF gets sent from the remarkable to gmail, is there a way to send multiple pages at once?

Thanks again,

@crushcup
Copy link

crushcup commented Mar 9, 2023

Hi @astoiccoder , thanks for pulling this all together. I can't wait to start using this to stay organized. Couple issues arose:

The PDF is being sent to my gmail, but the document does not make it to the notion, only the Subject. Only 1 page of the PDF gets sent from the remarkable to gmail, is there a way to send multiple pages at once?

Thanks again,

Edit: I was able to send multiple PDFs to gmail from the remarkable, but the content of the PDF is not being relayed to Notion, although the subject line appears.. very strange. Wondering if it is a setting filter or a change can be made to the script.

@astoiccoder
Copy link
Author

Hi @astoiccoder , thanks for pulling this all together. I can't wait to start using this to stay organized. Couple issues arose:

The PDF is being sent to my gmail, but the document does not make it to the notion, only the Subject. Only 1 page of the PDF gets sent from the remarkable to gmail, is there a way to send multiple pages at once?

Thanks again,

Hi @crushcup, thanks for reaching out! The remarkable changed the way it converts handwritten notes to text.
Before you always had to send it via email directly, but now conversation creates a new page in the current document containing the converted text. The send by email functionality lets you now choose in the buttom left corner if you want to send your pages as pdf attachments or as "Text in email".
So if you are converting text and want to sent it to your notion, you could choose the "Text in email" option and the script would still work as intended.

The tricky part comes with the pdf attachments (e.g. if you also want to send handwritten notes which would not be included with the "Text in email" option).
Notion unfortunately does not allow a file upload via API.
So I thought I could still make the pdfs show up on the page by storing the files to google drive with the script and then show them as an embed block on the notion page with the google drive integration, but adding a link_preview to a notion page is also not possible via API. Even in mention blocks it is not possible to add a link_preview.

The only thing I could find is now to copy the file to a google drive folder and then add the link to that google drive file to the notion page. But then of course it won't show a nice preview. If you want to have that, all you need to do is create a new google drive folder and copy the folder id from the url when you are inside the folder over to the latest version of the script.

Wish you a great weekend!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment