How to send an email project using Google Apps script

I am working with Google script applications and would like to create a script that collects mail from drafts and sends them if they have a send-tomorrow label. Finding drafts with a specific label is pretty simple:

var threads = GmailApp.search('in:draft label:send-tomorrow'); 

However, I do not see the API for sending a message! The only option I see is: - open a message - pull out the body / attachments / name / from / to / cc / bcc - send a new message with the specified parameters - destroy the previous draft

which seems pretty annoying, and I'm not sure if it will work well with embedded images, multiple attachments, etc.

any clue?

+6
source share
6 answers

The only option I see is: - open the message - extract the body / attachments / header / from / to / cc / bcc - send a new message with the above parameters - destroy the previous draft

This is the exact theme of this blog from Amit Agarawal. His script does only what you describe, but does not process inline images. For them, you can adapt the code from this article .

But you're right - what's the point of even having a draft message if you can't just send a stupid thing ?!

We can use the GMail Users.drafts API : send from Google Apps script to send a draft. The following stand-alone script does this and processes the necessary authorization.

Script

A full script is available in this value .

 /* * Send all drafts labeled "send-tomorrow". */ function sendDayOldDrafts() { var threads = GmailApp.search('in:draft label:send-tomorrow'); for (var i=0; i<threads.length; i++) { var msgId = threads[0].getMessages()[0].getId(); sendDraftMsg( msgId ); } } /** * Sends a draft message that matches the given message ID. * Throws if unsuccessful. * See https://developers.google.com/gmail/api/v1/reference/users/drafts/send. * * @param {String} messageId Immutable Gmail Message ID to send * * @returns {Object} Response object if successful, see * https://developers.google.com/gmail/api/v1/reference/users/drafts/send#response */ function sendDraftMsg( msgId ) { // Get draft message. var draftMsg = getDraftMsg(msgId,"json"); if (!getDraftMsg(msgId)) throw new Error( "Unable to get draft with msgId '"+msgId+"'" ); // see https://developers.google.com/gmail/api/v1/reference/users/drafts/send var url = 'https://www.googleapis.com/gmail/v1/users/me/drafts/send' var headers = { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }; var params = { method: "post", contentType: "application/json", headers: headers, muteHttpExceptions: true, payload: JSON.stringify(draftMsg) }; var check = UrlFetchApp.getRequest(url, params) var response = UrlFetchApp.fetch(url, params); var result = response.getResponseCode(); if (result == '200') { // OK return JSON.parse(response.getContentText()); } else { // This is only needed when muteHttpExceptions == true var err = JSON.parse(response.getContentText()); throw new Error( 'Error (' + result + ") " + err.error.message ); } } /** * Gets the current user draft messages. * Throws if unsuccessful. * See https://developers.google.com/gmail/api/v1/reference/users/drafts/list. * * @returns {Object[]} If successful, returns an array of * Users.drafts resources. */ function getDrafts() { var url = 'https://www.googleapis.com/gmail/v1/users/me/drafts'; var headers = { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }; var params = { headers: headers, muteHttpExceptions: true }; var check = UrlFetchApp.getRequest(url, params) var response = UrlFetchApp.fetch(url, params); var result = response.getResponseCode(); if (result == '200') { // OK return JSON.parse(response.getContentText()).drafts; } else { // This is only needed when muteHttpExceptions == true var error = JSON.parse(response.getContentText()); throw new Error( 'Error (' + result + ") " + error.message ); } } /** * Gets the draft message ID that corresponds to a given Gmail Message ID. * * @param {String} messageId Immutable Gmail Message ID to search for * * @returns {String} Immutable Gmail Draft ID, or null if not found */ function getDraftId( messageId ) { if (messageId) { var drafts = getDrafts(); for (var i=0; i<drafts.length; i++) { if (drafts[i].message.id === messageId) { return drafts[i].id; } } } // Didn't find the requested message return null; } /** * Gets the draft message content that corresponds to a given Gmail Message ID. * Throws if unsuccessful. * See https://developers.google.com/gmail/api/v1/reference/users/drafts/get. * * @param {String} messageId Immutable Gmail Message ID to search for * @param {String} optFormat Optional format; "object" (default) or "json" * * @returns {Object or String} If successful, returns a Users.drafts resource. */ function getDraftMsg( messageId, optFormat ) { var draftId = getDraftId( messageId ); var url = 'https://www.googleapis.com/gmail/v1/users/me/drafts'+"/"+draftId; var headers = { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }; var params = { headers: headers, muteHttpExceptions: true }; var check = UrlFetchApp.getRequest(url, params) var response = UrlFetchApp.fetch(url, params); var result = response.getResponseCode(); if (result == '200') { // OK if (optFormat && optFormat == "JSON") { return response.getContentText(); } else { return JSON.parse(response.getContentText()); } } else { // This is only needed when muteHttpExceptions == true var error = JSON.parse(response.getContentText()); throw new Error( 'Error (' + result + ") " + error.message ); } } 

Login

To use the Google API, we need the OAuth2 token for the current user - just like for Advanced Services. This is done using ScriptApp.getOAuthToken() .

After copying the code to your own script, go to Resources> Advanced Google Services, open the link for the Google Developer Console, and enable the Gmail API for your project.

As long as the script contains at least one GMailApp method that requires user privileges, the authentication scope will be set correctly for the OAuthToken. In this example, GmailApp.search() sendDayOldDrafts() ; but for insurance, you can include calling an unavailable function directly in the function using the API.

+10
source

I did this using the GmailMessage.forward method.

It works with uploading images and attachments, but I had to set the theme to avoid the “Fwd:” prefix and username because it only displayed the user's email to recipients.

I did not find a way to recycle the draft, so I just deleted the shortcut to prevent it from being resent.

Script writer:

 function getUserFullName(){ var email = Session.getActiveUser().getEmail(); var contact = ContactsApp.getContact(email); return contact.getFullName(); } function testSendTomorrow(){ var threads = GmailApp.search('in:draft label:send-tomorrow'); if(threads.length == 0){ return; } var labelSendTomorrow = GmailApp.getUserLabelByName("send-tomorrow"); for(var i = 0; i < threads.length; i++){ var messages = threads[i].getMessages(); for(var j = 0; j < messages.length; j++){ var mssg = messages[j]; if(mssg.isDraft()){ mssg.forward(mssg.getTo(), { cc: mssg.getCc(), bcc: mssg.getBcc(), subject: mssg.getSubject(), name: getUserFullName() }); } } threads[i].removeLabel(labelSendTomorrow); } } 
+4
source

You can search all drafts and then send this particular draft without any problems.

 function sendMessage(id){ GmailApp.getDrafts().forEach(function (draft) { mes = draft.getMessage() if (mes.getId() == id) { draft.send() } }) } 
+1
source

A simpler alternative is to use gmail api instead of gmailApp:

 function sendtestDraft(draftId){ var request = Gmail.Users.Drafts.send({id : draftId},'me'); Logger.log(request); } 

the above function example is used in the gs script at https://script.google.com . He needs a draftId (not an Id message) and the project will be sent. Images and attachments are all right! Info: https://developers.google.com/gmail/api/v1/reference/users/drafts/send

0
source

I am new here and I don’t have enough “reputation” to comment, so I couldn’t comment on the original Mogsdad answer, so I need to create a new answer:

I adapted the Mogsdad solution to support replying / forwarding existing threads, not just new messages.

To use it in existing streams, you must first create a response / forwarding and only then mark the stream. My code also supports multiple tags and their customization.

I created a new entity for him, branching Mogsdad, here: https://gist.github.com/hadasfester/81bfc5668cb7b666b4fd6eeb6db804c3

I still need to add a few screenshot links to the document, but otherwise it is ready for use, and I used it myself. Hope you find it useful.

You can also specify here:

 /** * This script allows you to mark threads/drafts with a predetermined label and have them get sent the next time your trigger * sets off. * * Setup instructions: * 1. Make a copy of this script (File -> Make a copy) * 2. Follow the "Authorization" instructions on https://stackoverflow.com/a/27215474. (If later during setup/testing you get * another permissions approval dialog, approve there as well). * 2. I created two default labels, you can edit/add your own. See "TODO(user):" below. After that, to create them in gmail, * choose "setUpLabel" function above and click the play button (TODO: screenshot). Refresh your gmail tab, you should see * the new labels. * 3. Click the clock icon above (TODO: screenshot) and set time triggers, eg like so: (TODO: screenshot) * 4. I recommend also setting up error notifications: (TODO: screenshot). * * Testing setup: * When you're first setting this up, if you want to test it, create a couple * of drafts and label them. Then, in this * script, select "sendWeekStartDrafts" or "sendTomorrowDrafts" in the function dropdown * and press play. This manually triggers the script (instead of relying on the * timer) so you can see how it works. * * Usage instructions: * 1. To get a draft sent out on the next trigger, mark your draft with the label you chose. * NOTE: If your draft is a reply to a thread, make sure you first create the draft and only then set the label on the * thread, not the other way around. * That it! Upon trigger your draft will be sent and the label will get removed from the thread. * * Some credits and explanation of differences/improvements from other existing solutions: * 1. This script was adapted from https://stackoverflow.com/a/27215474 to also support replying existing threads, not only * sending brand new messages. * 2. Other solutions I've run into are based on creating a new message, copying it field-by-field, and sending the new one, * but those have many issues, some of which are that they also don't handle replies and forwards very elegantly. * * Enjoy! **/ var TOMORROW_LABEL = '!send-tomorrow'; var WEEK_START_LABEL = '!send-week-start'; // TODO(user): add more labels here. /** * Set up the label for delayed send! **/ function setUpLabels() { GmailApp.createLabel(TOMORROW_LABEL); GmailApp.createLabel(WEEK_START_LABEL); // TODO(user): add more labels here. } function sendTomorrowDrafts() { sendLabeledDrafts(TOMORROW_LABEL); } function sendWeekStartDrafts() { sendLabeledDrafts(WEEK_START_LABEL); } // TODO(user): add more sendXDrafts() functions for your additional labels here. /* * Send all drafts labeled $MY_LABEL. * @param {String} label The label for which to send drafts. */ function sendLabeledDrafts(label) { var threads = GmailApp.search('in:draft label:' + label); for (var i=0; i<threads.length; i++) { var thread = threads[i]; var messages = thread.getMessages(); var success = false; for (var j=messages.length-1; j>=0; j--) { var msgId = messages[j].getId(); if (sendDraftMsg( msgId )) { success = true; } } if (!success) { throw Error( "Failed sending msg" ) }; if (success) { var myLabel = GmailApp.getUserLabelByName(label); thread.removeLabel(myLabel); } } } /** * Sends a draft message that matches the given message ID. * See https://developers.google.com/gmail/api/v1/reference/users/drafts/send. * * @param {String} messageId Immutable Gmail Message ID to send * * @returns {Object} Response object if successful, see * https://developers.google.com/gmail/api/v1/reference/users/drafts/send#response */ function sendDraftMsg( msgId ) { // Get draft message. var draftMsg = getDraftMsg(msgId,"json"); if (!getDraftMsg(msgId)) return null; // see https://developers.google.com/gmail/api/v1/reference/users/drafts/send var url = 'https://www.googleapis.com/gmail/v1/users/me/drafts/send' var headers = { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }; var params = { method: "post", contentType: "application/json", headers: headers, muteHttpExceptions: true, payload: JSON.stringify(draftMsg) }; var check = UrlFetchApp.getRequest(url, params) var response = UrlFetchApp.fetch(url, params); var result = response.getResponseCode(); if (result == '200') { // OK return JSON.parse(response.getContentText()); } else { // This is only needed when muteHttpExceptions == true return null; } } /** * Gets the current user draft messages. * Throws if unsuccessful. * See https://developers.google.com/gmail/api/v1/reference/users/drafts/list. * * @returns {Object[]} If successful, returns an array of * Users.drafts resources. */ function getDrafts() { var url = 'https://www.googleapis.com/gmail/v1/users/me/drafts'; var headers = { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }; var params = { headers: headers, muteHttpExceptions: true }; var check = UrlFetchApp.getRequest(url, params) var response = UrlFetchApp.fetch(url, params); var result = response.getResponseCode(); if (result == '200') { // OK return JSON.parse(response.getContentText()).drafts; } else { // This is only needed when muteHttpExceptions == true var error = JSON.parse(response.getContentText()); throw new Error( 'Error (' + result + ") " + error.message ); } } /** * Gets the draft message ID that corresponds to a given Gmail Message ID. * * @param {String} messageId Immutable Gmail Message ID to search for * * @returns {String} Immutable Gmail Draft ID, or null if not found */ function getDraftId( messageId ) { if (messageId) { var drafts = getDrafts(); for (var i=0; i<drafts.length; i++) { if (drafts[i].message.id === messageId) { return drafts[i].id; } } } // Didn't find the requested message return null; } /** * Gets the draft message content that corresponds to a given Gmail Message ID. * See https://developers.google.com/gmail/api/v1/reference/users/drafts/get. * * @param {String} messageId Immutable Gmail Message ID to search for * @param {String} optFormat Optional format; "object" (default) or "json" * * @returns {Object or String} If successful, returns a Users.drafts resource. */ function getDraftMsg( messageId, optFormat ) { var draftId = getDraftId( messageId ); var url = 'https://www.googleapis.com/gmail/v1/users/me/drafts'+"/"+draftId; var headers = { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }; var params = { headers: headers, muteHttpExceptions: true }; var check = UrlFetchApp.getRequest(url, params) var response = UrlFetchApp.fetch(url, params); var result = response.getResponseCode(); if (result == '200') { // OK if (optFormat && optFormat == "JSON") { return response.getContentText(); } else { return JSON.parse(response.getContentText()); } } else { // This is only needed when muteHttpExceptions == true return null; } } 
0
source

First, the send() function has appeared in GmailDraft , you can call it directly. See: https://developers.google.com/apps-script/reference/gmail/gmail-draft#send ().

An example of their code:

 var draft = GmailApp.getDrafts()[0]; // The first draft message in the drafts folder var msg = draft.send(); // Send it Logger.log(msg.getDate()); // Should be approximately the current timestamp 

Secondly, it may not even be necessary now that Google has released a scheduled dispatch.

  1. Click the arrow next to Send

Click the down arrow next to send.

  1. Choose your preferred time to send.

Select your preferred time.

0
source

Source: https://habr.com/ru/post/1207947/


All Articles