📮`MMailApp` for Google Apps Script: GmailApp+MailApp+Gmail API

Photo by Tim Mossholder on Unsplash

Problem

I had trouble with my project when I wanted to automatically send emails and suddenly for me we’ve reached the daily limit. This is why I’ve decided to make some research and be sure fewer bad things happen in the future.

MailApp OR GmailApp?

Apps Script native methods for sending emails are:

MailApp.sendEmail(...)
GmailApp.sendEmail(...)
var aliases = GmailApp.getAliases();

😭Emojis

If sending an email with emoji in a subject or body, it may show ugly question marks instead. This issue happens when you use GmailApp:

GmailApp.sendEmail(
'test.test@test.com',
'🎂Yammy',
'😍Eat my cake!'
);
/* =>
������Yammy ������Eat my cake!
*/

Quota

You can send ~100 emails/day and ~1500 for paid accounts. This quota has changed and may change in the future. The latest official quotas are here.

/**
* Get and log your daily mail quota
*/
function getRemainingMailQuota() {
var quota = MailApp.getRemainingDailyQuota();
console.log('You can send ~ ' + quota + ' emails this day.');
return quota;
}

Gmail API

What’s the limit for the use of Gmail API? I don’t know, really. I cannot believe my calculations. According to this:

Ok, how to use Gmail API in Apps Script?

The code sample of this was provided by 🦸Tanaike in this report. I’ve taken his code as a starting point.

  1. Installation is hard. You have to install the Gmail service into the script, and you may also need to install the API as an Advanced Service.
  2. Code is hard. If you see Tanaike’s report, you may notice it’s not easy to understand the correct syntax.
  3. Out of Control. I found no way to programmatically indicate what is my remaining quota for Gmail API.
raw RFC 2822
function getEmailRfc822() {
var emailId = '18312a64a8cf8746';
var rawContent = Gmail
.Users
.Messages
.get(
"me",
emailId,
{format: 'raw'}).raw;
var stringRfc822 = Utilities
.newBlob(
rawContent,
"message/rfc822").getDataAsString()
console.log(stringRfc822);
}
var messages = Gmail.Users.Messages.list(
"me", {q: "subject:Test Hatter", maxResults: 1}
).messages;
var emailId = messages[0].id;
console.log(emailId);

Solution

The idea was to have a simple way to send emails via Apps Script. Please think of this solution as one possible and indeed not a perfect one. I’ve decided to create a library called:

MMailApp
MMailApp.send(options);
{
to: 'test1@test.test,test2@test.test',
subject: '🥸Test Tets',
htmlbody: '<b>💪Bold Hello!</b>'
}
/**
* this function demonstrates
* how to get blobs by URL
* for your email
*/
function getTestBlobs_() {
var source = 'https://raw.githubusercontent.com/';
var options = {
urls: {
'coolTablesLogo':
source + 'cooltables/pics/main/logos/ct_logo_small.png',
'partyFace':
source + 'Max-Makhrov/myFiles/master/partyface.png'
},
html: "🔍 inline CoolTables Logo<img src='cid:coolTablesLogo'> image! <br>" +
"Hoooorrraaay! <img src='cid:partyFace'>"
}
var blobsArray = [], blobsObject = {};
var blob;
for (var k in options.urls) {
blob = UrlFetchApp
.fetch(options.urls[k])
.getBlob()
.setName(k);
blobsArray.push(blob);
blobsObject[k] = blob;
}
return {
array: blobsArray, // for attachments
object: blobsObject, // for inline images
htmlBody: options.html
};
}
"to" = "recipient" = "recipients"
"htmlbody" = "htmlBody" = "html_body"
etc.
var options = {
to: 'makhrov.max@gmail.com', // required
cc: 'max0637859167@gmail.com',
bcc: 'max0637859167@gmail.com,makhrov.max@gmail.com',
name: '🎩Mad Hatter',
from: 'max0637859167@gmail.com', // must owe alias
subject: '🥸Test Test Test',
body: '💪 body!',
htmlBody: '<b>🎸Bold Hello</b><br>How are you?',
noReply: 1,
replyTo: 'test@test.test',
replyToName: '🦸Stranger', // for Gmail API only
attachments: array, // [blob, blob]
inlineImages: object // {name: blob}
}

Gmail API Bonus

Learning how to use Gmail API was hard, but fun. I felt like I can control the process, and noticed some benefits.

{ "threadId":"18311c4fd396e1ad",
"id":"18311c4fd396e1ad",
"labelIds":["UNREAD","SENT","INBOX"]}
https://mail.google.com/mail/u/0/#inbox/18311c4fd396e1ad

Compatibility

The final task is to make the code compatible. Different methods may or may not work for all 3 methods:

GmailApp
MailApp
Gmail API
This email I’ve sent to myself with the help of Gmail API
noReply: 1, // will NOT work for Gmail API
from: test@mail.test // may only work if this email belongs to you
Reply-To: No Reply <noreply@test.test>
{
replyTo: test@mail.test,
replyToName: 🕷️Peter Parker // Hidden option! For Gmail API only
}

Final Words

I’ve finally resolved all the issues, and even had fun!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Max Makhrov

Max Makhrov

Google Sheets Developer, master of Online Accounting