Skip to content

Instantly share code, notes, and snippets.

@jceresearch
Last active July 6, 2020 06:51
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jceresearch/5755030 to your computer and use it in GitHub Desktop.
Save jceresearch/5755030 to your computer and use it in GitHub Desktop.
Google Apps Script to create a digest from a set of messages in Gmail. It does a bit more than that, filters by time, strips the html, trims legalese (or whatever) and tags messages so they are not processed again. Ideal to schedule it in gmail.
function GenerateDigest() {
//Function that goes through a search query based on time and optional label in gmail, strips html, collates into a single email, sends it to a desired address and then labels the emails as processed.
// Where the digest email is going
var to_emailAddress = "tomail@somedomain.com";
//We calculate the 24 hour range, I plan to run this every day at 9:00 to get last 24 hours of emails
var month = new Date().getMonth();
var date = new Date().getDate();
var year = new Date().getFullYear();
var time1 = new Date(year, month, date, 0, 0, 0).getTime();
//24 hours in miliseconds
var time2 = time1 - 86400000;
// Query to select the messages to digest, tweak to select labels or origins e.g. From:
var query = "newer:" + time2/1000 + " older:" + time1/1000 + " in:inbox" + " -label:Digested from:newsfeed@anotherdomain.com";
var threads = GmailApp.search(query);
var messages;
var message;
var date;
var date_formatted;
var subject;
var body_html;
var body_plain;
var body_plain_excerpt;
var digest_body;
try {
digest_body="";
for(var t in threads) {
// Get ALL the messages to each thread
messages = threads[t].getMessages();
startseparator = "----Start------";
endseparator = "------End------";
crlf = "\n";
for(var m in messages) {
message = messages[m].getBody();
date = messages[m].getDate();
date_formatted = Utilities.formatDate(date, "GMT", "yyyy-MM-dd'T'HH:mm")
subject = messages[m].getSubject();
body_html = messages[m].getBody();
//Google returns the body content in html, so we remove the html formatting
body_plain= getTextFromHtml (body_html);
body_plain_excerpt=body_plain
//Optional regexp to further trim the digest, remove signature or other legalese we dont want
var pattern= /^(.*?)The opinions expressed in the posted.*/igm;
var match;
while ( match = pattern.exec(body_plain)) {
//For some reason I cannot get the subgroup capture,
//but I do get the match.index so for the moment it works
//by doing a left(). To improve here.
body_plain_excerpt= body_plain.substring(0,match.index);
//End of optional section
}
//We append the excerpt to the main digest body string, plus some header information
digest_body = digest_body + startseparator + crlf + "Date:"+ date_formatted + crlf + "Subject:" + subject + crlf + body_plain_excerpt + crlf+ endseparator +crlf;
}
}
// We send the email
var digest_subject = "Digest of selected emails received in the last 24 hours" + Utilities.formatDate(new Date(), "GMT", "yyyy/M/d");
MailApp.sendEmail(to_emailAddress, digest_subject, digest_body);
//we label the results from the query as Digested to prevent reprocessing
//Given we rerun the exact query it shouldnt yield different, but have a look if this can be improved
var label = GmailApp.getUserLabelByName("Digested");
var threads = GmailApp.search(query);
for (var i = 0; i < threads.length; i++) {
label.addToThread(threads[i]);
}
//
} catch (err) {
Logger.log("[Error Generating] getMessage: " + err);
}
Logger.log("[Success] Digest created");
}
function getTextFromHtml(html) {
return getTextFromNode(Xml.parse(html, true).getElement());
}
function getTextFromNode(x) {
switch(x.toString()) {
case 'XmlText': return x.toXmlString();
case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
default: return '';
}
}
@overthepillsandfaraway
Copy link

Not sure where I'm messing this up - Apologies in advance, total noob :p!

I don't need mails specifically within the last 24 hours or any date range for that matter. I want a digest of all emails in a particular folder.

The code executes but I get no email :/

function GenerateDigest() {
//Function that goes through a search query based on time and optional label in gmail, strips html, collates into a single email, sends it to a desired address and then labels the emails as processed.

// Where the digest email is going
var to_emailAddress = "abc@gmail.com";

// Query to select the messages to digest, tweak to select labels or origins e.g. From:
var query = "label:pending-pending---it";
var threads = GmailApp.search(query);

var messages;
var message;
var date;
var date_formatted;
var subject;
var body_html;
var body_plain;
var body_plain_excerpt;
var digest_body;

try {
digest_body="";
for(var t in threads) {

  // Get ALL the messages to each thread
  messages = threads[t].getMessages();
  startseparator = "----Start------";
  endseparator =   "------End------";
  crlf = "\n";


  for(var m in messages) {        
    message = messages[m].getBody();
    date  = messages[m].getDate();
    date_formatted = Utilities.formatDate(date, "GMT", "yyyy-MM-dd'T'HH:mm")
    subject = messages[m].getSubject();

    body_html = messages[m].getBody();

    //Google returns the body content in html, so we remove the html formatting
    body_plain= getTextFromHtml (body_html);
    body_plain_excerpt=body_plain

   //Optional regexp to further trim the digest, remove signature or other legalese we dont want 
       var pattern= /^(.*?)The opinions expressed in the posted.*/igm;    
       var match;        
       while ( match = pattern.exec(body_plain)) {      
        //For some reason I cannot get the subgroup capture, but I do get the index so for the moment it works 
        //by doing a left() type
         body_plain_excerpt= body_plain.substring(0,match.index);
   //End of optional piece
 }

   //We append the excerpt to the main digest body string, plus some header information
   digest_body = digest_body + startseparator + crlf + "Date:"+ date_formatted  + crlf + "Subject:" + subject + crlf + body_plain_excerpt + crlf+  endseparator +crlf;

 }
}

// We send the email  
var digest_subject = "Digest Emails - Please read and action or delete";
MailApp.sendEmail(to_emailAddress, digest_subject, digest_body);    



} catch (err) {
Logger.log("[Error Generating] getMessage: " + err);

}

Logger.log("[Success] Digest created");

}

function getTextFromHtml(html) {
return getTextFromNode(Xml.parse(html, true).getElement());
}

function getTextFromNode(x) {
switch(x.toString()) {
case 'XmlText': return x.toXmlString();
case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
default: return '';
}
}

@jceresearch
Copy link
Author

hi there, this is a script I haven’t used in a long long time ago, so things may have been further restricted or changed.
I suggest you try the bare minimum and work your way from there. I am not precisely and expert on these things, I get them to work after loads of trial and error and googling :))

a) first a “hello world” email with no other content just to check you can send an email, you can easily put dummy text in the various variables that are needed to provide to the MailApp.sendEmail statement
b) It is supposed to save to an error log , try to find out there is that log going, maybe you can see it alongside the script and check what may have happened
c) you probably need to remove that optional pattern matching, just in case it is yielding some error there, add it later if you wish to trim the body (you can do just first X chars for simplicity)
d) obviously you need to configure your email address, I assume you put your own there and no typos :) Btw, in my case it was a different one from the one I was running the query... it was from an auxiliary account to my main account. I assume you should be allowed to send an automated email to yourself but who knows :)
e) your query statement looks odd with those dashes... are you sure that is the right syntax? I would start with labelling manually a couple of emails as “test” and then work your way to the full case.
f) for they life of me I cant remember if you could run it interactively, if that is the case, you may want to remove the try/catch to get the error in the right place it happens, for easier debugging.

As I said, it did work once upon a time, so it shouldn’t be that tricky to update... I strongly suggest you try with the simplest loop and google around the key component of sending an automated email, as that could have been limited/evolved due to security implications. Then add the query stuff and then the error handling etc etc.
Hope it helps
Best luck and feel free to post the solution to your problem here for someone needing it ...:)
Cheers!

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