Sendmail - Send email and text notifications, (notification device) no local server needed

@kahn-hubitat I just tested this in my app and it works. Message sent would be:
{Subject:Email Subject , Message:Email body, To:name@example.com}

Only difference is my Gmail notification won't accept a From since that is defaulted by the API.

I tried to convert the string to a JSON object but ran into issues since it would require quotes around the key and value so came up with a different method. Hopefully this works in your app:

if (message.startsWith("{") && message.endsWith("}")) {
	message = message.replace("{", "")
	message = message.replace("}", "")
	def messageSplit = message.split(",")
	def messageObject = [:]
	for (int i = 0; i < messageSplit.size(); i++) {
		def messagePart = messageSplit[i]
		def messagePartSplit = messagePart.split(":")
		if (messagePartSplit.size() == 2) {
			messageObject[messagePartSplit[0]] = messagePartSplit[1].trim()
		}
	}

	toEmail = (messageObject.containsKey("To")) ? messageObject.To : toEmail
	subject = (messageObject.containsKey("Subject")) ? messageObject.Subject : subject
	message = (messageObject.containsKey("Message")) ? messageObject.Message : message
	fromEmail = (messageObject.containsKey("From")) ? messageObject.From : fromEmail
}
1 Like

That's not gonna work for me as i said it would break all existing stuff to have the closing bracket at the end and the message inside.

Also would break messages with commas in them which is why i.didnt use.split. i could modify it to isolate the begin and end bracket leaving the message after it and then call your code.

crap already had this code in and it breaks the brackets.. not sure what i was trying to do i think pull out the message if passed som xml

if(msgData.substring(0,1) == "{") {

	        def slurper = new groovy.json.JsonSlurper()
	        def result = slurper.parseText(msgData)	      
            emlBody = result.Body
	        emlSubject = (result.Subject != null ? result.Subject : "")
        } else {
           	emlBody = msgData
        	emlSubject = (Subject != null ? "${Subject}" : "")
        }

ya already had this code to parse the subject out of straight xml.. weird. so brackets are not going to work or it will break anyone using this feature.. must have added it for a reason.

1 Like

contains key is not working correctly.. will look at alternate solution..

ie


3 Likes
  • v 4.92
    the original header replacement above still works
  • but added an alternative message based on ritchierich pseudo xml at the start of the message
    ie
    {header: value, header: value}, this is the message
    or
    {header: value, header: value. Message: this is the message}
    both work.
    Legal header values for replacement are: Subject: From: To: CC: Message:
    order is not important.
    example:
    {Subject: new subject, CC:kahn-zzspam@lgk.com, Message:newmessage here,To: kahn-saved@lgk.com, From: kahn@lgk.com}, this is a test
    or
    {Subject: new subject, CC:kahn-zzspam@lgk.com, Message:newmessage here,To: kahn-saved@lgk.com, From: kahn@lgk.com}

caveat: just notice if you use the message: replacement option the message itself cannot have a colon : in it or it will truncate past the colon.

4 Likes

here is the bulk of the code change

// handle bracket case for ehader replacement
if (emlBody.startsWith("{"))
{

               def newFrom = ""
               def newTo = ""
               def newCC = ""
               def newSubject = ""
               def newMessage = ""
               def headers = ""
               def body = ""
               
               if (state.debug) log.debug "found header directive start {."     
               // now find end and separate
               def sMsg = emlBody.split("}")
               emlBody = emlBody.replace("{", "")
               if (state.debug) log.debug "size = ${sMsg.size()}"
               
               if (sMsg.size() == 2)
               {
                   // now strip out comma on message
                   def cMsg = sMsg[1].split(",")
                   headers = sMsg[0]
                   body = cMsg[1]
                   if (state.debug) log.debug "left side (headers) = $headers, right side (msg} = ${cMsg[1]}, body = $body"
               }
               else 
               {
                   // message must be inside
                   headers = sMsg[0]
                   if (state.debug) log.debug "left side (headers) = $headers, right side blank (message must be in options)!"                     
               }                     
                   //emlBody = cMSg[1]
                   headers = headers.replace("}", "")
                   headers = headers.replace("{", "")
                   def headerSplit = headers.split(",")

                   if (state.debug) log.debug "header split = ${headerSplit} size = ${headerSplit.size()}"
                   for (int i = 0; i < headerSplit.size(); i++) 
                   {                          
	                  def headerPart = headerSplit[i]
	                  def headerPartSplit = headerPart.split(":")
                       
                       if (state.debug) log.debug "part = ${headerPart}"
                    
                    if (headerPart.contains("To")) 
                     {
                         def dh = headerPart.split(":")
                         if (dh.size() == 2) newTo = dh[1].trim() 
                     }
                        
                    if (headerPart.contains("Subject")) 
                     {
                         def dh = headerPart.split(":")
                         if (dh.size() == 2) newSubject = dh[1].trim()
                     }
                     
                    if (headerPart.contains("From")) 
                     {
                       def dh = headerPart.split(":")
                       if (dh.size() == 2) newFrom = dh[1].trim()
                     } 
                       
                     if (headerPart.contains("CC")) 
                     {
                       def dh = headerPart.split(":")
                       if (dh.size() == 2) newCC = dh[1].trim()
                     } 
                       
                     if (headerPart.contains("Message")) 
                     {
                       def dh = headerPart.split(":")
                       if (dh.size() == 2) newMessage = dh[1].trim()
                     }     
                   } // loop
                   
                    if (state.debug) log.debug "newFrom = *${newFrom}*, newTo = *${newTo}*, newSubject = *${newSubject}* newCC = *${newCC}* newMessage = *${newMessage}*"
                   // now handle using the new fields if there
                   if (newFrom != "") From = newFrom
                   if (newTo != "") To = newTo
                   if (newSubject != "") emlSubject = newSubject
                   if (newMessage != "") emlBody = newMessage
                     else emlBody = body
                   if (newCC != "") 
                     {
                       cc = newCC
                       ccFound = true
                     }
                     
           } // starts with }
2 Likes

Just tested changing the Subject of an email and it works great! Thanks.

Here is what I did using this in WebCore:

4 Likes

This project is a great idea. Couple of questions...

Is it attachment capable (local files) or is it just text?

Can you use global varialbes on the driver page instead of header directives?

no for attachments .. where would you get the file anyway from the file manager..

too complicated to pull a file in and start uuencoding it anyway.

second, there is no way to know even what global variable you would want to use nor access. so no to that as well.

1 Like

Not really sure I follow your use case but the stock Notifications app supports Global Variables to be included in the message as of v2.3.4 and Rule Machine does as well. So if the notification you are trying to send comes from one of those apps you can include the GV values within the notification as they get sent to the notification devices and from there to whatever device it is set to send it to Email vs Push vs SMS vs etc...

1 Like

Thanks.. I ended up creating a webcore template to take care of associating gv's and applying them to the directives. Now I can just set them and call it from all my other instances.

1 Like

Hi, I am looking to do SMTP notifications to an internal email server. There will be no need for authentication.

This is a very long thread going back several years so I was wondering if someone could point me to the correct spot to just install the latest version of the app and then the process for just sending over to a local email server. Thanks!

Easiest methos is to use Hubitat Package Manager and search for "sendmail" and install it from there. Otherwise list most community solutions the code links are in the very first post.

3 Likes

As noted, install it from Hubitat Package Manager.

The process/setup is documented above - you create a new device on the Device tab in HE, and then complete the setup of the parent,which then creates the child devices.

Example setup:


Once you save preferences on the parent device it will create the necessary number of children matching the "concurrent messages" setting:
2023-02-01 08_42_38-Chrome Main
2023-02-01 08_43_04-Chrome Main

3 Likes

Thank you!

Thank you for the response!

1 Like

NP...now you're prepared to handle the next initial setup question that gets posted here. :wink:

We'll see...

1 Like

I got SendMail installed and got it connected to my email server. I was able to send test messages successfully but I had some questions. I got 6 test messages, I assume this is because there were 5 children and it was testing all of them? I won't get six messages each time, right?

After creating the Sendmail device, it had the parent device and 5 children (I left it at defaults). When i go into, for example, HSM for water alerts, I see "Sendmail Parent". So I would select this as the notification option, correct? What's the purpose of the child nodes?

And I can use this same Parent device for notifications for multiple different apps within Hubitat right? I am asking because I was reading over the forum and thought I saw somewhere that you had to create separate ones different apps but maybe I misread that.

Sendmail should not (and never has for me) duplicate indvidual messages. Not sure what happened. Can you repeat the duplication?

The children are there to ensure that messages queued up don't get lost...

Yes, you should use it anywhere you want to get notifications, in as many apps as you want to. I use it in all apps where I want text notifications.