So I want to use my own email server, and I want to use SSL/TLS. I'm not very concerned about my password being visible on my local machines, but it would be nice to not have it visible. Anyway, I managed to hack some things together and write my first ever Groovy driver, and it is working for me! My SMTP server supports SSL on port 465 with PLAIN authentication.
This is really not any kind of release. It doesn't check email address formats or server formats, and it uses nasty hacks to send a curl command over telnet to my NAS, and then disconnect when the command completes. I'd love to be able to use curl on the Hubitat, but can't figure out if that's possible. (Are there any ways to perform local shell commands from a driver?)
So anyway, here is the code. I don't have it on GitHub or anything. It's too fragile, and won't work generally, but maybe someone here could look at it and fix my silliness. I'm sure I don't understand the code flow correctly for this.
/**
*
* File: telnet-curl-email.groovy
* Platform: Hubitat
* Modification History:
* Date Time Who What
* v0.0.1 2020-04-02 21:21 @BrianP Initial test
* v0.0.2 2020-04-03 16:21 @BrianP Trying to disconnect when done
* v0.0.3 2020-04-03 16:30 @BrianP Fixed missing smtps://
* v0.1.0 2020-04-03 17:05 @BrianP Things seem to be working
* v0.1.1 2020-04-03 17:25 @BrianP Trying to get parse/disconnect working better
* v0.2.0 2020-04-03 18:30 @BrianP This is a real hack but it works for my setup
* v0.2.1 2020-04-03 20:15 @BrianP Alllow multiple comma-separated recipients
*
* Copyright 2020 @BrianP
*
* This software is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
def version() {"v0.2.1"}
preferences
{
section("Device Settings:")
{
input("telnetServer", "text", title: "Telnet server", description: "Enter address of Telnet server", required: true, displayDuringSetup: true)
input("telnetPort", "integer", title: "Telnet port", description: "Enter port number, default 23", required: false, defaultvalue: 23, displayDuringSetup: true)
input("telnetUsername", "text", title: "Telnet username", description: "User ID", required: false, displayDuringSetup: true)
input("telnetPassword", "text", title: "Telnet password", description: "Password", required: false, displayDuringSetup: true)
}
section("SMTP Server Settings:")
{
input("emlServer", "text", title: "Email server", description: "Enter SMTP server address", required: true, displayDuringSetup: true)
input("emlPort", "text", title: "Email port", description: "Enter SMTP server port (SSL required)", required: true, defaultvalue: 465, displayDuringSetup: true)
input("emlUsername", "text", title: "Email username", description: "Enter SMTP server username", required: true, displayDuringSetup: true)
input("emlPassword", "text", title: "Email password", description: "Enter SMTP server password", required: true, displayDuringSetup: true)
}
section("Email Settings:")
{
input("emlTo", "text", title:"To", description: "Enter email address(es) (comma-separated) to which notifications should be sent", required: true, displayDuringSetup: true)
input("emlFrom", "text", title:"From", description: "Enter email address from which notifications should be sent", required: true, displayDuringSetup: true)
input("emlSubject", "text", title:"Subject", description: "Enter email subject line", required: true, displayDuringSetup: true)
}
input("debugMode", "bool", title: "Enable logging", required: true, defaultValue: true, displayDuringSetup: true)
}
metadata
{
definition (name: "Telnet-curl-email", namespace: "BrianP", author: "BrianP")
{
capability "Notification"
capability "Actuator"
capability "Telnet"
}
}
def installed()
{
log.info('Telnet-curl-email: installed()')
initialize()
}
def updated()
{
log.info('Telnet-curl-email: updated()')
initialize()
}
def initialize()
{
state.version = version()
state.lastMsg = ""
state.LastCode = 0
state.EmailBody = ""
}
def deviceNotification(message) {
state.EmailBody = "${message}"
state.LastCode = 0
logDebug("Connecting to ${telnetServer}:${telnetPort}")
telnetClose()
telnetConnect(telnetServer, telnetPort.toInteger(), telnetUsername, telnetPassword)
}
def parse(String msg)
{
logDebug("Parse: " + msg)
if (msg.startsWith('sh: pts')){ // this is a hack that works on my systems
def emlRcpts = emlTo.split(', *') //support multiple comma-delimited recipients
String mailRcpts = ''
emlRcpts.each {
mailRcpts = mailRcpts + "--mail-rcpt '${it}' "
}
def sndCommand = "echo 'To: ${emlTo}\nSubject: ${emlSubject}\nFrom: ${emlFrom}\nContent-Type: text/plain;\n${state.EmailBody}' | curl --url 'smtps://${emlServer}:${emlPort}' --ssl-reqd --mail-from '${emlFrom}' ${mailRcpts}--upload-file '-' --user '${emlUsername}:${emlPassword}'"//WARNING: username and password on command line! >:(
logDebug("Sending email command")
hubCmd = sendHubCommand(new hubitat.device.HubAction(sndCommand, hubitat.device.Protocol.TELNET))
}
if (msg.startsWith('[~] #')){ // this is a hack that works on my systems
try {
telnetClose()
logDebug("Telnet connection to ${telnetServer} closed.")
} catch(e) {
logDebug("Connection already closed, No need to close connection again.")
}
}
}
def logDebug(txt) {
try {
if (debugMode) { log.debug("${txt}") }
} catch(ex) {
log.error("logDebug unable to output requested data!")
}
}
Any comments/help on this?
I'm happy that I have everything under my control, up to the secure transmission to my mail service. I'd really love for the command send and telnet close to not be such nasty hacks, but that's what I managed given my total lack of experience.