From d8860fc91779819aca3ce77683d68e7bcd18309a Mon Sep 17 00:00:00 2001 From: Ben Ubois Date: Fri, 7 May 2021 14:08:10 -0700 Subject: [PATCH 1/2] Added external command support. --- config.go | 5 +++-- main.go | 28 +++++++++++++++++++++++++++- smtprelay.ini | 3 +++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 40bf13d..3d32766 100644 --- a/config.go +++ b/config.go @@ -34,6 +34,7 @@ var ( allowedRecipStr = flag.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses") allowedRecipients *regexp.Regexp allowedUsers = flag.String("allowed_users", "", "Path to file with valid users/passwords") + command = flag.String("command", "", "Path to pipe command") remoteHost = flag.String("remote_host", "", "Outgoing SMTP server") remoteUser = flag.String("remote_user", "", "Username for authentication on outgoing SMTP server") remotePass = flag.String("remote_pass", "", "Password for authentication on outgoing SMTP server") @@ -172,8 +173,8 @@ func ConfigLoad() { // Set up logging as soon as possible setupLogger() - if *remoteHost == "" { - log.Warn("remote_host not set; mail will not be forwarded!") + if *remoteHost == "" && *command == "" { + log.Warn("no remote_host or command set; mail will not be forwarded!") } setupAllowedNetworks() diff --git a/main.go b/main.go index 8e239eb..185a977 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,13 @@ package main import ( + "bytes" "crypto/tls" "fmt" "net" "net/textproto" "os" + "os/exec" "os/signal" "strings" "syscall" @@ -163,8 +165,32 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { "uuid": generateUUID(), }) + if *remoteHost == "" && *command == "" { + logger.Warning("no remote_host or command set; discarding mail") + return nil + } + + if *command != "" { + cmdLogger := logger.WithField("command", *command) + + var stdout bytes.Buffer + var stderr bytes.Buffer + + cmd := exec.Command(*command) + cmd.Stdin = bytes.NewReader(env.Data) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err := cmd.Run() + if err != nil { + cmdLogger.WithError(err).Error(stderr.String()) + return nil + } + + cmdLogger.Info("pipe command successful: " + stdout.String()) + } + if *remoteHost == "" { - logger.Warning("remote_host not set; discarding mail") return nil } diff --git a/smtprelay.ini b/smtprelay.ini index b47f103..5fb682b 100644 --- a/smtprelay.ini +++ b/smtprelay.ini @@ -78,3 +78,6 @@ ; Sender e-mail address on outgoing SMTP server ;remote_sender = + +; Pipe messages to external command +;command = /usr/local/bin/script \ No newline at end of file From 3f627d3281e2b6e4313222d07b55758e4bfdadc1 Mon Sep 17 00:00:00 2001 From: Ben Ubois Date: Sat, 8 May 2021 11:56:28 -0700 Subject: [PATCH 2/2] Move AddReceivedLine before further processing. --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 185a977..d83493c 100644 --- a/main.go +++ b/main.go @@ -170,6 +170,8 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { return nil } + env.AddReceivedLine(peer) + if *command != "" { cmdLogger := logger.WithField("command", *command) @@ -196,8 +198,6 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error { logger.Info("delivering mail from peer using smarthost") - env.AddReceivedLine(peer) - var sender string if *remoteSender == "" {