0

I found the following code online but can't remember where I got it from. The script will search for any emails with a specific label (in this case "GReminder") and add those emails into your calendar. I tried to set this up but I'm getting the error message:

TypeError: label.getThreads is not a function

I'm not familiar with Javascript and I'm not a software developer by any means. I've tried to modify it but couldn't get it to work. Hoping someone can help me here. Here is the code below:

function gMailReminder() {
  var reminderLabel = "GReminder", //Substitute your label here
      calendarName = "Mobile Calendar", ////Substitute your Calendar name here
      reminderDuration = 2, //duration in hours
      label = GmailApp.getUserLabelByName(reminderLabel),
      threads = label.getThreads();
  
  if (threads.length > 0) {
    //get calendar by name
    var cals = CalendarApp.getCalendarsByName(calendarName);
          
    var now = new Date().getTime();
    for (i in threads) {
      cals[0].createEvent(reminderLabel + '- '+threads[0].getFirstMessageSubject(),
        new Date(now+(60000*60*reminderDuration)),
          new Date(now+(60000*60*reminderDuration)), {description: threads[i].getPermalink()});
    }
    //Remove the label from the mails to avoid duplicate event creation on next run 
    label.removeFromThreads(threads);
  }
}

Furthermore, the code searches for the label "GReminder" and then removes that label at the end of the script. I'd like to modify this so that the script searches for GReminder in Gmail, then adds a new GReminder-Processed label to it (to show that those emails have been "processed") and then the next time it runs again, it will skip emails with GReminder-Processed. I've only gotten the part of creating the labels sorted (I think), but can't figure out the rest...

function getOrCreateLabel(labelName) {
  var label = GmailApp.getUserLabelByName(labelName);
  if (label == null) {
    label = GmailApp.createLabel(labelName);
  }
  return label;
}


  var label = getOrCreateLabel("Bill Reminder - processed"); 
  thread.addLabel(label);
shadowz1337
  • 710
  • 1
  • 8
  • 21
  • Strange question - are you signed in to multiple accounts in your browser? – Rafa Guillermo Aug 02 '21 at 07:25
  • Nope, I'm using incognito window just to be sure as well. Issue was to do with project automatically defaulting to use Chrome V8 and I unticked it and it seems to be working OK. I still need a bit of help with getting the label "Bill Reminder - processed" applied to the emails though. – shadowz1337 Aug 03 '21 at 08:37

2 Answers2

0
function gMailReminder() {
  const rlbl = "GReminder";
  const rdur = 2;
  const label = GmailApp.getUserLabelByName(rlbl);
  const threads = label.getThreads();
  const cal = CalendarApp.getCalendarsByName("Mobile Calendar")[0];
  if (threads.length > 0) {
    threads.forEach(t => {
      let now = new Date().getTime();
      cal.createEvent(rlbl + '- ' + t.getFirstMessageSubject(), new Date(now), new Date(now + (60000 * 60 * rdur)), { description: t.getPermalink() });
    });
    label.removeFromThreads(threads);
  }
}

I think probably your label name is wrong:

Here's a function to get your label names:

function getUserLabels() {
  const labels = GmailApp.getUserLabels();
  let html = '';
  labels.forEach(l => {
    html += `<br>Name: ${l.getName()}`
  });
  SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html),'Label Names');
 }

I modified your code to test the label names:

function gMailReminder() {
  const rlbl = "Qs/Services/Google";
  const label = GmailApp.getUserLabelByName(rlbl);
  const threads = label.getThreads();
  let html ='';
  if (threads.length > 0) {
    threads.forEach(t => {
      html += `<br>${t.getFirstMessageSubject()}`;
    });
    SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html),'Subjects');
  }
}

And this now works

Cooper
  • 59,616
  • 6
  • 23
  • 54
  • Thanks but I'm still getting pretty much the same error message for label.getThreads. Also, I'm getting this message for the 3rd line - "Syntax error: SyntaxError: Unexpected token 'const' line: 21 file: Bill_Reminder.gs" – shadowz1337 Jul 30 '21 at 05:47
  • Which is line 21 – Cooper Jul 30 '21 at 06:04
  • is you runtime V8 or Rhino? – Cooper Jul 30 '21 at 06:05
  • I'm not getting any syntax errors. I think you must be running Rhino. You need to switch to V8 – Cooper Jul 30 '21 at 06:10
  • I'm using v8, which I think is the default anyway – shadowz1337 Jul 31 '21 at 00:32
  • Line 21 for me is the label.getthreads, same issue as my original post – shadowz1337 Jul 31 '21 at 00:33
  • I think your variable label must be null because your label name is wrong. You can use one of the functions to get all of your user labels so that you can check your label name. – Cooper Jul 31 '21 at 01:11
  • Thanks but I still can't get your code to work. I'm getting this when I run getUserLabels() - "Exception: Invalid argument: name". If I use this, I can get the emails - var threads = GmailApp.search('(label:TestLabel)') – shadowz1337 Aug 01 '21 at 01:58
  • I'm also getting this - "Exception: Cannot call SpreadsheetApp.getUi() from this context.". If I run debug, I can see a list of my labels found in the debug right-side pane, but I don't get a spreadsheet due to the error message. – shadowz1337 Aug 01 '21 at 02:03
  • I tested both of them by running them from script editor they both work. – Cooper Aug 01 '21 at 02:09
  • hmm I'm really not sure what I'm doing wrong. I'm running v8 (which I can confirm in project settings). Here is what my output looks like. I'm just testing your getuserlabel function at this point. I can see the labels in the debug right-side pane, but then I get this error - https://imgur.com/rZxB6Hc – shadowz1337 Aug 01 '21 at 11:43
  • I don't see what you are doing wrong either. Are you logged into two different accounts? – Cooper Aug 01 '21 at 15:51
  • Nope, I'm logged into the same account. I have other Google App Scripts that are working fine, so I'm not sure why the script in my new Google App Script project isn't working.....as a workaround, would you mind sharing your project with me? I should be able to clone it and test it. – shadowz1337 Aug 01 '21 at 22:38
  • There's no chance of that ever happening. – Cooper Aug 01 '21 at 22:51
  • Sorry, but may I ask why? You're just sharing a test project with the code that you've already posted. The only difference here is that if your code has been confirmed to work fine for yourself, then if I make a copy of that test project into my own account, I should be able to just run it without modifying anything. The problem at this point is I can't even run some of the functions you wrote. Some lines work up until a certain point. – shadowz1337 Aug 01 '21 at 23:20
  • I got the original code posted in OP working. All I had to do was untick V8 from the project setting, which I presume means it will run using "Rhino". This is completely opposite to what you advised. – shadowz1337 Aug 02 '21 at 02:57
  • I tried. If I didn't help then I apologize. Debugging code is often difficult in the best of circumstances but when one has to do it remotely with someone that's not very good at it, it can be very challenging and easy to make mistakes. – Cooper Aug 02 '21 at 04:38
  • You've been helpful, as I wouldn't have known about the Chrome V8 or Rhino if you hadn't mention it. I appreciate it. I'm still trying to get your script for checking the label working, as I found that if I use a label that has spaces or characters in another language (Chinese characters for example), then the script will fail "getThreads", which I presume means getting all the emails based on the label. – shadowz1337 Aug 04 '21 at 04:18
  • Yes in a lot of C like languages spaces are considered defacto delimiters in strings and can result in unexpected results. That's why a lot of old guys like me use underscores or camel code in all of our names and parameters. This is especially important in command line parameters. – Cooper Aug 04 '21 at 14:41
  • But using an _ in my Gmail label would make it less readable. It's only natural for a Gmail label to have spaces in the name. These labels are automatically applied via Gmail filters and when you have more than 100+ emails with the same label, making it readable is really important. Especially when you take label colours and nesting etc into consideration as well.....also, I played around with this code and it has no problems getting my label with Chinese characters? var threads = GmailApp.search('label:測試-測試'); – shadowz1337 Aug 05 '21 at 21:28
0

Came up with the solution myself.

As you can see, my label has Chinese characters and GmailApp.Search has no problem with this.

However, LABEL_DONE requires you to put in I guess the unicode (or whatever it's called) of the Chinese characters. Again, I don't know anything about Javascript and so a lot of my code is just copying and pasting code from somewhere else and modifying them to the best of my extent. I had to do a bit of debugging to find out what my Chinese label looks like in the Logger. The result provided by the Logger is the unicode that you see for LABEL_DONE. If you also use non-English characters for your labels, you'll need to test it yourself and find what the corresponding unicode string is.

Anyway, the code below will use GmailApp.Search to search for specific labels (you can mix and match search conditions in there and can test this easily in Gmail search itself). It will then add the emails for those specific labels into Google Calendar, then apply a "Bill Reminder - Processed" label. The next time the Google App Script trigger runs, it will skip these emails, because of the Processed label.

// https://stackoverflow.com/questions/12377640/printing-to-the-console-in-google-apps-script

function testLog(){
  Logger.log("Logger.log");
  console.log("console.log")
}



function BillReminder_Rates() {

  if (!GmailApp) return; // Skip script execution if GMail is currently not available (yes this happens from time to time and triggers spam emails!)
  
  var reminderLabel = "電費,-水費,-垃圾袋,-網路-bill-reminder---processed", //Substitute your label here
      calendarName = "Reminders", ////Substitute your Calendar name here
      reminderDuration27Days = 648; //duration in hours;

  
  var threads = GmailApp.search('(label:電費,-水費,-垃圾袋,-網路-council-rates---me) AND (-label:電費,-水費,-垃圾袋,-網路-bill-reminder---processed)');

  
  if (threads.length > 0) {
    //get calendar by name
    var cals = CalendarApp.getCalendarsByName(calendarName);
          
    var now = new Date().getTime();
    for (i in threads) {
      //cals[0].createEvent(reminderLabel + ' - '+threads[i].getFirstMessageSubject(),
      cals[0].createEvent(threads[i].getFirstMessageSubject(),
        new Date(now+(60000*60*reminderDuration27Days)),
          new Date(now+(60000*60*reminderDuration27Days)), {description: threads[i].getPermalink()});
    }

 
    LABEL_DONE = "\u96fb\u8cbb, \u6c34\u8cbb, \u5783\u573e\u888b, \u7db2\u8def/Bill Reminder - Processed";
    var label_done = GmailApp.getUserLabelByName(LABEL_DONE);


    for (var t in threads) {
      var threadblah = threads[t];

      // Grab the task data
      var taskTitle = threadblah.getFirstMessageSubject();

      // Insert the task
      //addTask_(taskTitle, TASKLIST);

      // Set to 'done' by exchanging labels
      //threadblah.removeLabel(label_pending);
      threadblah.addLabel(label_done);  
    }
  
  }
  
}







function BillReminder_Power_Gas() {

  if (!GmailApp) return; // Skip script execution if GMail is currently not available (yes this happens from time to time and triggers spam emails!)


  var reminderLabel = "電費,-水費,-垃圾袋,-網路-bill-reminder---processed", //Substitute your label here
      calendarName = "Reminders", ////Substitute your Calendar name here
      reminderDuration12Days = 288; //duration in hours;

  
  var threads = GmailApp.search('(label:電費,-水費,-垃圾袋,-網路-power -OR label:電費,-水費,-垃圾袋,-網路-gas) AND (-label:電費,-水費,-垃圾袋,-網路-bill-reminder---processed)');

  if (threads.length > 0) {
    //get calendar by name
    var cals = CalendarApp.getCalendarsByName(calendarName);
          
    var now = new Date().getTime();
    for (i in threads) {
      //cals[0].createEvent(reminderLabel + ' - '+threads[i].getFirstMessageSubject(),
      cals[0].createEvent(threads[i].getFirstMessageSubject(),
        new Date(now+(60000*60*reminderDuration12Days)),
          new Date(now+(60000*60*reminderDuration12Days)), {description: threads[i].getPermalink()});
    }

    LABEL_DONE = "\u96fb\u8cbb, \u6c34\u8cbb, \u5783\u573e\u888b, \u7db2\u8def/Bill Reminder - Processed";

    var label_done = GmailApp.getUserLabelByName(LABEL_DONE);

    for (var t in threads) {
      var threadblah = threads[t];

      // Grab the task data
      var taskTitle = threadblah.getFirstMessageSubject();

      // Insert the task
      //addTask_(taskTitle, TASKLIST);

      // Set to 'done' by exchanging labels
      //threadblah.removeLabel(label_pending);
      threadblah.addLabel(label_done);  
    }
  
  }
  
}





function BillReminder_Water() {

  if (!GmailApp) return; // Skip script execution if GMail is currently not available (yes this happens from time to time and triggers spam emails!)


  var reminderLabel = "電費,-水費,-垃圾袋,-網路-bill-reminder---processed", //Substitute your label here
      calendarName = "Reminders", ////Substitute your Calendar name here
      reminderDuration15Days = 360; //duration in hours;
  
  var threads = GmailApp.search('(label:電費,-水費,-垃圾袋,-網路-watercare---me) AND (-label:電費,-水費,-垃圾袋,-網路-bill-reminder---processed)');


  if (threads.length > 0) {
    //get calendar by name
    var cals = CalendarApp.getCalendarsByName(calendarName);
          
    var now = new Date().getTime();
    for (i in threads) {
      //cals[0].createEvent(reminderLabel + ' - '+threads[i].getFirstMessageSubject(),
      cals[0].createEvent(threads[i].getFirstMessageSubject(),
        new Date(now+(60000*60*reminderDuration15Days)),
          new Date(now+(60000*60*reminderDuration15Days)), {description: threads[i].getPermalink()});
    }
 

    LABEL_DONE = "\u96fb\u8cbb, \u6c34\u8cbb, \u5783\u573e\u888b, \u7db2\u8def/Bill Reminder - Processed";
    var label_done = GmailApp.getUserLabelByName(LABEL_DONE);

    for (var t in threads) {
      var threadblah = threads[t];

      // Grab the task data
      var taskTitle = threadblah.getFirstMessageSubject();

      // Insert the task
      //addTask_(taskTitle, TASKLIST);

      // Set to 'done' by exchanging labels
      //threadblah.removeLabel(label_pending);
      threadblah.addLabel(label_done);  
    }
  
  }
  
}





function delete_events()
{
  //take care: Date function starts at 0 for the month (January=0)
  //{search: 'cycle'+"*"+'Checkpoint'} hier zijn de search terms
  var fromDate = new Date(2021,6,1,0,0,0); //This is July 1, 2021
  var toDate = new Date(2021,11,1,0,0,0);   //This is September 1, 2021 at 00h00'00"
  var calendarName = 'Reminders';
  var toRemove = 'title_of_the_events';

  var calendar = CalendarApp.getCalendarsByName(calendarName)[0];
  var events = calendar.getEvents(fromDate, toDate,{search: toRemove});
  for(var i=0; i<events.length;i++)
  {
    var ev = events[i];
    if(ev.getTitle()==toRemove) //check if the title matches
    {
      Logger.log('Item '+ev.getTitle()+' found on '+ev.getStartTime()); // show event name and date in log
      ev.deleteEvent(); //uncomment this line to actually do the delete !
    }
  }
}


function delete_events2()
{
    var fromDate = new Date(2021,8,1,0,0,0); 
    var toDate = new Date(2021,11,27,0,0,0);
    var calendarName = 'Reminders';

    // delete from Jan 1 to end of Jan 4, 2013 (for month 0 = Jan, 1 = Feb...)

    var calendar = CalendarApp.getCalendarsByName(calendarName)[0];
    var events = calendar.getEvents(fromDate, toDate);
    for(var i=0; i<events.length;i++){
      var ev = events[i];
      Logger.log(ev.getTitle()); // show event name in log
      ev.deleteEvent();
    }
 }
Dharman
  • 30,962
  • 25
  • 85
  • 135
shadowz1337
  • 710
  • 1
  • 8
  • 21