Send an email to a gmail contact group (label)

I want to send an email to a group of people notifying them that an event has occurred. I’ve successfully set up gmail to do this and can send emails.

However, I want to manage the recipients email addresses in gmail in a contacts group (now called a label).

If I try to send the email from Home Assistant and use the Label as the target I get an error. (It works fine from within gmail itself).

I suspect the answer here is “not possible” but thought I’d check.

Can Home Assistant send a gmail email to a contact label target?

The e-mail service likely uses SMTP which is a protocol that is universal. Googles SMTP server needs to respect the specifications for that. So it cannot be anything other than that Google expands the label in (the API of their) app.

So if you want this too, you’d need to do something similar in HA to expand the label to e-mail adresses before putting it into the SMTP server.

I doubt Google Contacts has been integrated enough to do this.

OK, I’ve found a solution, thought I’d share it here with you all.

Basically, I wrote some scripts in google backend - one to allow someone to subscribe or unsubscribe, and one for me to send an email.

The subscribe/unsubscribe script runs every 5 minutes and looks for an email in the inbox with a “Subscribe” subject. It then takes the users email address and looks in a spreadsheet on Google Drive for the user. If the user isn’t there, the script adds the user to the spreadsheet and sends them an acknowledgement email telling them they are not subscribed. If it receives an “unsubscribe” email, it looks for the user in the spreadsheet and removes them, then sends them an acknowledgement email that they are unsubscribed.

When I want to send an email to everyone, I send an email to my mailbox and the second script (that runs every minute) looks for an email with a subject of “Send email”. It takes the body of that email and create a new one, and sends it to everyone (bcc) who’s in the spreadsheet…

I’ve been using this now for a couple of weeks and it’s brilliant, never failed. (Famous last words).

Here’s the code if you want to create your own version. By the way, the subject of the email is a little more complex than subscribe, unsubscribe and send email, you can make it anything you want.

Hope this is helpful to others who want to do something similar:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// setTriggerForSendEmail
//
// Create a trigger that runs every minute
// This trigger is looking for an email telling google to send a notification to the contact list
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function setTriggerForSendEmail() {
  ScriptApp
  .newTrigger('sendNotificationEmail')
  .timeBased()
  .everyMinutes(1)
  .create()
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// setTriggerJoinLeaveGroup
//
// Create a trigger that runs every 5 minutes
// This trigger is looking for an email asking to either subscribe or unsubscribe to the notifications email list
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function setTriggerJoinLeaveGroup() {
  ScriptApp
  .newTrigger('joinLeaveEmailList')
  .timeBased()
  .everyMinutes(5)
  .create()
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// joinLeaveEmailList
//
// This function is called every 5 minutes and looks for any new emails that want to either join or leave the  
// notification group
// If they ask to join we will do the following:
//    1. Get the email address from the sender
//    2. Add the email to the spreadsheet list
//    3. Move the email out of the Inbox to the Service folder
//    4. Send the requester a conformation email
// If they ask to leave we will do the following:
//    1. Get the email address from the sender
//    2. Remove the email from the spreadsheet list
//    3. Move the email out of the Inbox to the Service folder
//    4. Send the requester a conformation email
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function joinLeaveEmailList() {
  // Define some variables
  var search = ""
  var threads = ""
  var messages = ""
  var senderAddr = ""
  var senderName = ""
  var senderEmail = ""
  var senderArray = ""

  // Look for emails with a request to join the group
  search = 'in:inbox subject:"<<Your Service>> Notifications - Subscribe"'    
  threads = GmailApp.search(search)

  console.log("Found "+threads.length+" subscribe emails")
  // Loop through all the threads, processing each email in turn
  threads.forEach(thread => {
    // Get the messages
    messages = thread.getMessages()

    // 1. Get the email address
    senderAddr = messages[0].getFrom()
    senderArray = senderAddr.split(" <");
    senderName = senderArray[0]
    senderEmail = senderArray[1].substring(0, senderArray[1].length-1).toLowerCase()
    console.log(senderAddr)

    // Open a Google Sheet containing notification emails
    var sheet = SpreadsheetApp.openById("<<Spreadsheet ID>>")
    var searchRange = sheet.getRange("A:A").createTextFinder(senderEmail).findNext()
    if (searchRange == null) {
      // If we don't find it, add the email address
      // 2. Add email to list
      sheet.appendRow([senderEmail, senderName]); 
    }

    // 3. Move the email out of the Inbox to the your service folder
    var folderLabel = GmailApp.getUserLabelByName("<<Service folder name>>");
    thread.markRead()
    thread.addLabel(folderLabel)
    thread.moveToArchive();

    // 4. Send the requester a conformation email
    GmailApp.sendEmail(senderName+" <"+senderEmail+">", "<<Your service>> Notifications", "You are now subscribed to <<Your service>> Notifications")
  })

  // Look for emails with a request to leave the group
  search = 'in:inbox subject:"<<Your Service>> Notifications - Unsubscribe"'    
  threads = GmailApp.search(search)

  console.log("Found "+threads.length+" unsubscribe emails")
  // Loop through all the threads, processing each email in turn
  threads.forEach(thread => {
    // Get the messages
    messages = thread.getMessages()

    // 1. Get the email address
    senderAddr = messages[0].getFrom()
    senderArray = senderAddr.split(" <");
    senderName = senderArray[0]
    senderEmail = senderArray[1].substring(0, senderArray[1].length-1).toLowerCase()
    console.log(senderAddr)

    // Open a Google Sheet containing notification emails
    var sheet = SpreadsheetApp.openById("<<Spreadsheet ID>>")
    // Search for the email address so we can remove it
    var searchRange = sheet.getRange("A:A").createTextFinder(senderEmail).findNext()
    if (searchRange != null) {
      var searchRow = searchRange.getRow()
      // If we find it, delete the row
      // 2. Remove email from list
      sheet.deleteRow(searchRow);
    }

    // 3. Move the email out of the Inbox to your service folder
    var folderLabel = GmailApp.getUserLabelByName("<<Service folder name>>");    
    thread.markRead()
    thread.addLabel(folderLabel)
    thread.moveToArchive();

    // 4. Send the requester a conformation email
    GmailApp.sendEmail(senderName+" <"+senderEmail+">", "<<Your Service>> Notifications", "You are now unsubscribed from <<Your Service>> Notifications")
  })
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// sendNotificationEmail
//
// This function is called every 1 minute and looks for a email telling google to send to the notification list.
// The function gets the BODY of the sent email and deletes the email
// It then opens the email list and reads in all emails and sends the body to all recipients.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sendNotificationEmail() {
  var search = 'in:inbox subject:"<<Your Service>> Notifications - Send Request"'    
  var threads = GmailApp.search(search)
  var emailBody = ""

  console.log("Found "+threads.length+" send email request")
  threads.forEach(thread => {
    var messages = thread.getMessages()

    // Get the email body
    emailBody = messages[0].getBody()

    // Delete the email
    thread.markRead()
    thread.moveToTrash();

    // Open a Google Sheet containing notification emails
    var sheet = SpreadsheetApp.openById("Spreadsheet ID")

    // Get all the data in the sheet
    var data = sheet.getDataRange().getValues();

    var emailList = ""
    // Loop through each row getting email addresses
    for (var row = 0; row < data.length; row++) {
      if (emailList.length > 0) {
        emailList = emailList + ";"
      }
      emailList = emailList + data[row][1]+" <"+data[row][0]+">"
    }

    // Colsole out what we have
    console.log("Sending to: "+emailList)
    console.log("Email body: "+emailBody)

    // Define options to bcc the recipients, set the name of the sender and include the body of the email
    var options = {
      bcc: emailList,
      name: "<<Your service>> Notifier",
      htmlBody: emailBody
    }

    // Send the email
    GmailApp.sendEmail("<<Your gmail email address>>", "<<Your service>> Notifications", "", options)
  })
}

In the above code, you need to create a folder to store sub/unsub requests (keeps the inbox tidy), a spreadsheet and have a service name.
The parts you need to change are in <<>> brackets.

1 Like