I'm a newbie so please bear with me.
I'm trying to set up a Google Cloud Function that can access a single GMail account on the same domain, download some emails and push them to Cloud Storage. I honestly would like to just use an email & password in the script (using Google KMS /w environment variables?) but I understand that isn't possible, and OAuth2 is required.
I've set up an OAuth Client in GCP and I have run the GMail API Python Quickstart guide. Running it locally I am prompted to allow access, and the token is saved so subsequent runs work without prompts.
I deployed the Cloud Function with the pickle file to test if the refresh token will still work, planning to figure out how to use KMS to make this more secure later on. But there's an issue loading the pickle:
UnpicklingError: invalid load key, '\xef'
Which makes it seem like the pickle gets compressed/corrupted on upload.
Is this even a sane approach? How could I do this? The email address is mine, so I was hoping I could just authenticate once and be done with it.
It's not possible for me to use a domain-delegated Service Account by the way- nor use IMAP.
Since you can't do domain delegated service accounts, you can try following this guide on setting up server side authorization. This sounds like what you want since it requires that the user authorizes the app once and then reuses that token. Here is a codelab that will take you through the auth part.
Alternatively, you can use push notifications. It sounds like your current design is to poll the Gmail API to look for new emails periodically, which also involves authorizing access to the account in the Cloud Function. However, if you take advantage of Push Notifications, you can both get the data in real time, and avoid having to authorize the Cloud Function to read the Gmail API. See guide here.
However, probably the easiest solution is to use app scripts. If you set up your cloud function to be triggered via an HTTP target, you can write an app script to ping that URL with the messages you want to send to GCS. Docs here.
function getEmails() {
let inbox = GmailApp.getInboxThreads(0, 50);
// Inbox Threads
for (i=0; i < inbox.length; i++){
let threadMessages = inbox[i].getMessages();
// Thread Messages
for (j=0; j < threadMessages.length; j++){
let message = threadMessages[j].getBody();
let subject = threadMessages[j].getSubject();
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify({"message": message, "subject": subject})
};
UrlFetchApp.fetch('YOUR_FUNCTION_TRIGGER_URL', options);
}
}
}