Adding attachment to Gmail draft with Google Apps Script and Gmail API - google-apps-script

I try to automatically attach a file from my Google Drive (so ideally with the file id) in my Gmail draft created with Google Apps Script and GMail API. I use the syntax below. Can I do that easily? Creating the draft works great by the way.
Thanks! Chris
function createDraft() {
var forScope = GmailApp.getInboxUnreadCount(); // needed for auth scope
var htmlBody = 'Howzit';
var raw =
'Subject: Howzit\n' +
'To: aa#bb.cc\n' +
'Content-Type: text/html; charset=UTF-8\r\n' +
'\r\n' + htmlBody;
var draftBody = Utilities.base64Encode(raw, Utilities.Charset.UTF_8).replace(/\//g,'_').replace(/\+/g,'-');
var params = {method:"post",
contentType: "application/json",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true,
payload:JSON.stringify({
"message": {
"raw": draftBody
}
})
};
var resp = UrlFetchApp.fetch("https://www.googleapis.com/gmail/v1/users/me/drafts", params);
}

How about following sample script? This is a very simple script for attaching a file to a draft. So please modify this to your environment.
In order to use this script, please enable Gmail API at API console. And please import file ID to fileId in the script.
Sample script :
function createDraft() {
var fileId = "### file id ###";
var file = DriveApp.getFileById(fileId);
var forScope = GmailApp.getInboxUnreadCount();
var htmlBody = 'Howzit';
var raw =
'Subject: Howzit\r\n' +
'To: aa#bb.cc\r\n' +
'Content-Type: multipart/mixed; boundary=##########\r\n\r\n' +
'--##########\r\n' +
'Content-Type: text/html; charset=UTF-8\r\n\r\n' + htmlBody + '\r\n' +
'--##########\r\n' +
'Content-Type: ' + file.getMimeType() + '; charset=UTF-8; name="' + file.getName() + '"\r\n' +
'Content-Disposition: attachment; filename="' + file.getName() + '"\r\n' +
'Content-Transfer-Encoding: base64\r\n\r\n' + Utilities.base64Encode(file.getBlob().getBytes()) +
'\r\n--##########\r\n';
var draftBody = Utilities.base64EncodeWebSafe(raw, Utilities.Charset.UTF_8);
var params = {
method:"post",
contentType: "application/json",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true,
payload: JSON.stringify({"message": {"raw": draftBody}})
};
var resp = UrlFetchApp.fetch("https://www.googleapis.com/gmail/v1/users/me/drafts", params);
Logger.log(resp)
}
Result :
{
"id": "#####",
"message": {
"id": "#####",
"threadId": "#####",
"labelIds": [
"DRAFT"
]
}
}
Image :

Related

Google App Script. Retrieve emails list from the sheet

In the following script I have to manually insert the email addresses. I rather get the list from the sheet to be able to update it without editing the script.
How do I retrieve a list of email addresses from the sheet (Sheet!A2:A)?
function sendReport() {
EMAIL = 'email'
URL = 'url'
+ '/export?'
+ 'format=pdf'
+ '&size=A4'
+ '&gid=id'
+ '&scale=4'
+ '&portrait=true';
SpreadsheetApp.getActive();
var response = UrlFetchApp.fetch(URL, {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
}
});
var message = {
to: EMAIL,
subject: "subject",
body: "body",
attachments: [response.getBlob().setName('file.pdf')]
}
MailApp.sendEmail(message);
}
Is the script you expect as follows?
Modified script:
function sendReport() {
URL = 'url'
+ '/export?'
+ 'format=pdf'
+ '&size=A4'
+ '&gid=id'
+ '&scale=4'
+ '&portrait=true';
var response = UrlFetchApp.fetch(URL, {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
}
});
// Retrieve values from Spreadsheet.
var sheet = SpreadsheetApp.getActiveSheet();
var values = sheet.getRange("A2:A" + sheet.getLastRow()).getDisplayValues();
// Send the email using the email addresses.
values.forEach(([email]) => {
if (email) {
var message = {
to: email,
subject: "subject",
body: "body",
attachments: [response.getBlob().setName('file.pdf')]
}
MailApp.sendEmail(message);
}
});
}
If you want to set the specific sheet, please modify var sheet = SpreadsheetApp.getActiveSheet(); to var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");.
Reference:
forEach()

Sending Email of Multiple Google Sheets as Excel Attachment (As 3 x Sheets or 1 with Sub Sheets) from App Script

I am trying to send 3 x Sheets from a Google Sheet using App Script. Following code is working perfectly for 1 Sheet, but when i try to sent 3 Sheets, it not working.
function sendExcel() {
var url = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getSheetId();
var url1 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getSheetId();
var url2 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getSheetId();
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
var blob = UrlFetchApp.fetch(url, url1, url2, params).getBlob().setName("Orders.xlsx");
var message = {
to: "email#domain.com",
cc: "email#domain.com",
subject: "My Email Subject",
body: "Hi Team, details....",
name: "My Name",
attachments: [blob]
}
MailApp.sendEmail(message);
}
Can someone please guide me on correct code for sending 3 / multiple sheets as attachment (As 1 Excel file or 3x Separate Attached Excel Files)?
The main problem with your code is that the UrlFetchApp.fetch() method doesn't take multiple URLs so you have to export each sheet separately.
There's probably a more elegant solution to combine the blobs into a single spreadsheet file but a quick fix to your code to send the three files separately would be the following:
var url = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getSheetId();
var url1 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getSheetId();
var url2 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getSheetId();
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
var blob = UrlFetchApp.fetch(url, params).getBlob().setName("Orders.xlsx");
var blob1 = UrlFetchApp.fetch(url1, params).getBlob().setName("Orders 2.xlsx");
var blob2 = UrlFetchApp.fetch(url2, params).getBlob().setName("Orders 3.xlsx");
var message = {
to: "email#domain.com",
cc: "email#domain.com",
subject: "My Email Subject",
body: "Hi Team, details....",
name: "My Name",
attachments: [blob, blob1, blob2]
}
MailApp.sendEmail(message);
}
I think this will send 3 separate messages each with one attachment:
function sendThree() {
var url0 = "https://docs.google.com/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export" + "?format=xlsx&" + "gid=" + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getSheetId();
var url1 = "https://docs.google.com/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export" + "?format=xlsx&" + "gid=" + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getSheetId();
var url2 = "https://docs.google.com/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export" + "?format=xlsx&" + "gid=" + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getSheetId();
[url0, url1, url2].forEach((url,i) => {
var params = { method: "GET", headers: { "authorization": "Bearer " + ScriptApp.getOAuthToken() } };
var blob = UrlFetchApp.fetch(url,params).getBlob().setName(`Orders${i+1}.xlsx`);
var message = {
to: "email#domain.com",
cc: "email#domain.com",
subject: "My Email Subject",
body: "Hi Team, details....",
name: "My Name",
attachments: [blob]
}
MailApp.sendEmail(message);
});
}
I think this will send one email with three attachmentments:
function sendOneEmailWithThreeAttachments() {
var url0 = "https://docs.google.com/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export" + "?format=xlsx&" + "gid=" + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getSheetId();
var url1 = "https://docs.google.com/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export" + "?format=xlsx&" + "gid=" + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getSheetId();
var url2 = "https://docs.google.com/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export" + "?format=xlsx&" + "gid=" + SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getSheetId();
var urlA = [];
[url0, url1, url2].forEach((url, i) => {
var params = { method: "GET", headers: { "authorization": "Bearer " + ScriptApp.getOAuthToken() } };
urlA.push(UrlFetchApp.fetch(url, params).getBlob().setName(`Orders${i + 1}.xlsx`));
});
var message = {
to: "email#domain.com",
cc: "email#domain.com",
subject: "My Email Subject",
body: "Hi Team, details....",
name: "My Name",
attachments: urlA
}
MailApp.sendEmail(message);
}

How to send the email from Google Apps Script using GMAIL API?

I am trying to automise sending of the Emails from my account using Gmail API in Google Apps Script.
Here is my code:
function email_checker() {
var yourEmailAddress = "####gmail.com";
var myEmailAddress = "support####.com";
var subject = "testing mail";
var forScope = GmailApp.getInboxUnreadCount();
var htmlBody = '<html><body>' + '<h1>HI</h1>' + '</body></html>';
var message = 'From: Me <' + myEmailAddress + '>\r\n' +
'To: Me <' + myEmailAddress + '>\r\n' +
'Subject: ' + subject + '\r\n' +
'Content-Type: text/html; charset=utf-8\r\n' +
'Content-Transfer-Encoding: quoted-printable\r\n\r\n' +
htmlBody;
var draftBody = Utilities.base64Encode(message);
draftBody = draftBody.replace(/\//g, '_').replace(/\+/g, '-');
var params = {
method: "post",
contentType: "application/json",
headers: {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: JSON.stringify({
"message": {
"raw": draftBody
}
})
};
var resp = UrlFetchApp.fetch("https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send", params);
Logger.log(resp.getContentText());
}
I am getting the following error: Media type 'application/json' is not supported.
Can anyone please advise on what I am doing wrong?
Thank you.
I believe your goal and your current situation as follows.
You want to send an email using Gmail API with UrlFetchApp.
You have already done the settings for sending the email.
Gmail API is enabled.
The scopes for sending emails can be included.
Modification points:
From your endtpoint, it is found that the media upload request is used.
In this case,
the request body is required to create with multipart/alternative.
It is not required to use the base64 encode with the web safe.
The content type is required to use message/rfc822.
The created request body can be directly used for payload.
When above points are reflected to your script, it becomes as follows.
Modified script:
function email_checker() {
var yourEmailAddress = "####gmail.com";
var myEmailAddress = "support####.com";
var subject = "testing mail";
var forScope = GmailApp.getInboxUnreadCount();
var htmlBody = '<html><body>' + '<h1>HI</h1>' + '</body></html>';
var message = 'MIME-Version: 1.0\r\n' +
'From: Me <' + myEmailAddress + '>\r\n' +
'To: Me <' + myEmailAddress + '>\r\n' +
'Subject: ' + subject + '\r\n' +
'Content-type: multipart/alternative; boundary=boundaryboundary\r\n\r\n' +
'--boundaryboundary\r\n' +
'Content-type: text/html; charset=UTF-8\r\n' +
'Content-Transfer-Encoding: quoted-printable\r\n\r\n' +
htmlBody + "\r\n\r\n" +
'--boundaryboundary--';
var params = {
method: "post",
contentType: "message/rfc822",
headers: {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: message
};
var resp = UrlFetchApp.fetch("https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send", params);
Logger.log(resp.getContentText());
}
Note:
If you want to use the endpoint of POST https://gmail.googleapis.com/gmail/v1/users/{userId}/messages/send, please modify your script as follows.
From
var params = {
method: "post",
contentType: "application/json",
headers: {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: JSON.stringify({
"message": {
"raw": draftBody
}
})
};
var resp = UrlFetchApp.fetch("https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send", params);
Logger.log(resp.getContentText());
To
var params = {
method: "post",
contentType: "application/json",
headers: {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: JSON.stringify({"raw": draftBody})
};
var resp = UrlFetchApp.fetch("https://gmail.googleapis.com/gmail/v1/users/me/messages/send", params);
Logger.log(resp.getContentText());
In this case, var draftBody = Utilities.base64Encode(message); draftBody = draftBody.replace(/\//g, '_').replace(/\+/g, '-'); can be also modified to var draftBody = Utilities.base64EncodeWebSafe(message);.
Reference:
Method: users.messages.send

How to update spreadsheet bound script using AppScript API?

I intend to update my bound script (destination) with contents from another script (source). I am trying the following code. It does not give any error, but do not modify the destination script either.
function getScriptSourceCode() {
var srcProjectId = "id of source project"; // Source project ID
var destProjectId = "id of destination project"
var baseUrl = "https://script.googleapis.com/v1/projects";
var accessToken = ScriptApp.getOAuthToken()
var srcName = JSON.parse(UrlFetchApp.fetch(baseUrl + "/" + srcProjectId, {
method: "get",
headers: {"Authorization": "Bearer " + accessToken}
}).getContentText()).title;
var content = UrlFetchApp.fetch(baseUrl + "/" + srcProjectId + "/content", {
method: "get",
headers: {"Authorization": "Bearer " + accessToken}
}).getContentText();
var url = "https://script.googleapis.com/v1/projects/" + destProjectId
+ "/content";
var options = {
followRedirects: true,
"method" : "PUT",
"muteHttpExceptions": true,
"headers": {
'Authorization': 'Bearer ' + accessToken
},
"contentType": "application/json",
"payload": JSON.stringify(content)
}
var response = UrlFetchApp.fetch(url, options);
}
}
Am i missing something?
Excuse me for the erroneous script. I modified the script little bit and now its working as desired. However it seems I have to run the script twice to get the desired result. Below is the working script.
function UpdateScript()
{
var destProjectId = "Destination project ID"
var srcProjectId = "Source Project ID"; // Source project ID
var baseUrl = "https://script.googleapis.com/v1/projects";
var accessToken = ScriptApp.getOAuthToken()
var content = UrlFetchApp.fetch(baseUrl + "/" + srcProjectId + "/content", {
method: "get",
headers: {"Authorization": "Bearer " + accessToken}
}).getContentText();
// Upload a project to bound-script project.
var response = JSON.parse(UrlFetchApp.fetch(baseUrl + "/" + destProjectId + "/content", {
method: "put",
contentType: 'application/json',
headers: {"Authorization": "Bearer " + accessToken},
payload: content
}).getContentText());
}

Storing Google Sheets in AppData Folder

There is a way to do that?. I'm using Drive REST API from client browser, even I´ve tryed to convert a csv file into application/vnd.google-apps.spreadsheet but using v2 the request throws a 403 error saying "Method not supported for appdata contents" and using v3 creates the spreadsheet but in root directory instead of appDataFolder.
And if it isn't possible, can I hide a Google Sheet from the user Drive root?
Here my code to upload (using v3)
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var metadata = {
'title': 'my title ',
'mimeType': 'application/vnd.google-apps.spreadsheet',
'parents': [{'id': 'appDataFolder'}]
};
var multipartRequestBody =
delimiter +
'Content-Type: application/json; charset=UTF-8\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: text/csv\r\n' +
'\r\n' +
'21/2/2017;prod1;22;33' +
close_delim;
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://content.googleapis.com/upload/drive/v3/files?uploadType=multipart&convert=true');
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.setRequestHeader('Content-Type', 'multipart/mixed; boundary="' + boundary + '"');
xhr.onerror=function(a,b,c){console.log('error',a,b,c)};
xhr.onload = function(a,b,c){console.log('success',a,b,c)};
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200){
console.log(xhr.response);
}
};
xhr.send(multipartRequestBody);