-
-
Save DiegoAscanio/89846f48e3ec61c0c974b98fe6351bad to your computer and use it in GitHub Desktop.
a smtp listener for zoneminder external record trigger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// IP Camera supports motion detection, which can be configured to send | |
// emails upon alarm is fired | |
// This go programme serve as a minimal smtp server, listening login requests | |
// from IP Camera, and triggers zmtrigger.pl through unix socket. | |
package main | |
import ( | |
"github.com/op/go-logging" | |
"net" | |
"github.com/siebenmann/smtpd" | |
"bytes" | |
"os" | |
) | |
var log = logging.MustGetLogger("ipc smtpd") | |
var format = logging.MustStringFormatter( | |
`%{color}%{time:15:04:05.000} %{shortfunc} | ${level:.4s} %{id:03x}%{color:reset} %{message}`, | |
) | |
var cfg = smtpd.Config{ | |
Auth: &smtpd.AuthConfig{ | |
Mechanisms: []string{"LOGIN",}, | |
}, | |
SayTime: true, | |
LocalName: "heimserver.heim.lan", | |
SftName: "ipcSmtpd", | |
} | |
func handleConnection(conn net.Conn) { | |
log.Infof("new connection from %v", conn.RemoteAddr()) | |
defer conn.Close() | |
c := smtpd.NewConn(conn, cfg, nil) | |
for { | |
evt := c.Next() | |
switch evt.What { | |
case smtpd.COMMAND: | |
switch evt.Cmd { | |
case smtpd.AUTH: | |
wantInput := [][]byte{ | |
{}, | |
[]byte("[email protected]"), | |
[]byte("thisispassword"), | |
} | |
challenges := [][]byte{ | |
[]byte("Username:"), | |
[]byte("Password:"), | |
nil, | |
} | |
i := 0 | |
success := c.Authenticate(func(c *smtpd.Conn, input []byte) { | |
if i >= len(wantInput) { | |
log.Warningf("AuthFunc called %d times, expected %d calls", i+1, len(wantInput)) | |
} | |
if !bytes.Equal(input, wantInput[i]) { | |
log.Errorf("invalid input: got %q, expected %q", input, wantInput[i]) | |
} | |
if i == len(wantInput)-1 { | |
c.Accept() | |
} else { | |
c.AuthChallenge(challenges[i]) | |
} | |
i++ | |
}) | |
if !success { | |
log.Errorf("Authentication failed from %v", conn.RemoteAddr()) | |
c.Reject() | |
return | |
} else { | |
log.Infof("Authentication success, triggering zoneminder...") | |
sockWrite("/var/run/zm/zmtrigger.sock", os.Args[1]) // "4|on+2|5|ExtTrigger|Motion Detection trigger from IP Camera" | |
return | |
} | |
default: | |
c.Accept() | |
} | |
case smtpd.DONE: | |
return | |
case smtpd.ABORT: | |
return | |
} | |
} | |
} | |
func sockWrite(addr, data string) { | |
typ := "unix" | |
conn, err := net.DialUnix(typ, nil, &net.UnixAddr{addr, typ}) | |
if err != nil { | |
log.Errorf("open socket failed: %e", err) | |
return | |
} | |
defer conn.Close() | |
_, err = conn.Write([]byte(data)) | |
if err != nil { | |
log.Errorf("write data failed: %e", err) | |
return | |
} | |
} | |
func main() { | |
// log.Debugf("args: %v", os.Args) | |
log.Infof("Starting IPC smtp daemon...") | |
ln, err := net.Listen("tcp", ":25") | |
if err != nil { | |
log.Fatal(err) | |
} | |
for { | |
conn, err := ln.Accept() | |
if err != nil { | |
log.Error(err) | |
} | |
go handleConnection(conn) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment