Towards first version.

This commit is contained in:
urosj 2017-07-25 15:34:51 +02:00
parent 955de981d3
commit 9000b4a888
1 changed files with 131 additions and 5 deletions

View File

@ -32,6 +32,9 @@ import (
"fmt" "fmt"
"flag" "flag"
"os" "os"
"os/exec"
"io"
"path/filepath"
"strings" "strings"
"log/syslog" "log/syslog"
) )
@ -44,20 +47,78 @@ const RATE_LOG_DIR = "/var/spool/autoresponder/log"
const SENDMAIL_BIN = "/usr/sbin/sendmail" const SENDMAIL_BIN = "/usr/sbin/sendmail"
var syslg *syslog.Writer = nil
// Function using fmt.Printf for debug printing, but only if DEBUG is true // Function using fmt.Printf for debug printing, but only if DEBUG is true
func DebugFmtPrintf(format string, v ...interface{}) { func DebugFmtPrintf(format string, v ...interface{}) {
if DEBUG { if DEBUG {
fmt.Printf("DEBUG: " + format, v...) fmt.Printf("DEBUG: " + format, v...)
} }
} }
func DebugSyslogFmt(syslg *syslog.Writer, format string, v ...interface{}) { func DebugSyslogFmt(format string, v ...interface{}) {
if syslg == nil {
return
}
if DEBUG { if DEBUG {
syslg.Debug(fmt.Sprintf("DEBUG: " + format, v...)) syslg.Debug(fmt.Sprintf("DEBUG: " + format, v...))
} }
} }
// Return true if file exists and is regular file
func fileExists(name string) bool {
st, err := os.Lstat(name)
if err != nil || (st.Mode() & os.ModeType) != os.FileMode(0) {
return false
}
return true
}
// Send mail from address to address with given mail content being passed as function pointer
func sendMail(from, to string, populateStdin func(io.WriteCloser)) error {
cmd := exec.Command(SENDMAIL_BIN, "-i", "-f", from, to)
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
err = cmd.Start()
if err != nil {
return err
}
go func() {
populateStdin(stdin)
}()
err = cmd.Wait()
if err != nil {
return err
}
return nil
}
// Set autoresponse using supplied arguments and stdin (email body) // Set autoresponse using supplied arguments and stdin (email body)
func setAutoresponseViaEmail(recipient, sender, saslUser, clientIp string) error { func setAutoresponseViaEmail(recipient, sender, saslUser, clientIp string) error {
senderResponsePath := filepath.Join(RESPONSE_DIR, sender)
if fileExists(senderResponsePath) {
err := deleteAutoresponse(sender, true)
if err != nil {
return err
}
if ! fileExists(senderResponsePath) {
syslg.Info(fmt.Sprintf("Autoresponse disabled for address: %v by SASL authenticated user: %v from: %v",
sender,saslUser, clientIp))
//!!! Send mail via sendmail
sendMail(recipient, sender, func(sink io.WriteCloser) {
defer sink.Close()
sink.Write([]byte(fmt.Sprintf("From: %v\nTo: %v\nSubject: Autoresponder\n\n"+
"Autoresponse disabled for %v by SASL authenticated user: %v from: %v\n",
recipient, sender, sender, saslUser, clientIp)))
})
} else {
}
}
//!!! //!!!
return nil return nil
@ -70,10 +131,48 @@ func forwardEmailAndAutoresponse(recipient, sender, saslUser, clientIp string, r
return nil return nil
} }
// Enable autoresponse for email
func enableAutoresponse(email string) error {
//!!!
return nil
}
// Disable autoresponse for email
func disableAutoresponse(email string) error {
//!!!
return nil
}
// Enable existing autoresponse for email
func enableExAutoresponse(email string) error {
//!!!
return nil
}
// Delete autoresponse for email
func deleteAutoresponse(email string, nostdout bool) error {
deleteResponsePath := filepath.Join(RESPONSE_DIR, email)
if fileExists(deleteResponsePath) {
os.Remove(deleteResponsePath)
} else {
msg := fmt.Sprintf("%v does not exist, thus it cannot be deleted!", deleteResponsePath)
if ! nostdout {
fmt.Println(msg)
}
return fmt.Errorf("%v", msg)
}
return nil
}
func main() { func main() {
// Connect to syslog // Connect to syslog
syslg, err := syslog.New(syslog.LOG_MAIL, "autoresponder") syslg, err := syslog.New(syslog.LOG_MAIL, "autoresponder")
if err != nil { if err != nil {
fmt.Println(err.Error())
os.Exit(1) os.Exit(1)
} }
defer syslg.Close() defer syslg.Close()
@ -91,7 +190,7 @@ func main() {
responseRatePtr := flag.Uint("t", 86400, "Response rate in seconds (0 - send each time)") responseRatePtr := flag.Uint("t", 86400, "Response rate in seconds (0 - send each time)")
flag.Parse() flag.Parse()
DebugSyslogFmt(syslg, "Flags: Recipient: %v, Sender: %v, SASL authenticated username: %v, Client IP: %v, Enable autoresponse: %v, Disable autoresponse: %v, Enable existing autoresponse: %v, Delete autoresponse: %v, Setup instructions: %v, Response rate: %v", DebugSyslogFmt("Flags: Recipient: %v, Sender: %v, SASL authenticated username: %v, Client IP: %v, Enable autoresponse: %v, Disable autoresponse: %v, Enable existing autoresponse: %v, Delete autoresponse: %v, Setup instructions: %v, Response rate: %v",
*recipientPtr, *recipientPtr,
*senderPtr, *senderPtr,
*saslUserPtr, *saslUserPtr,
@ -149,7 +248,7 @@ func main() {
if *enableAutoResponsePtr != "" || *disableAutoResponsePtr != "" || *enableExAutoResponsePtr != "" || *deleteAutoResponsePtr != "" { if *enableAutoResponsePtr != "" || *disableAutoResponsePtr != "" || *enableExAutoResponsePtr != "" || *deleteAutoResponsePtr != "" {
mode = 1 mode = 1
} }
DebugSyslogFmt(syslg, "mode=%v, sendResponse=%v, authenticated=%v\n", mode, sendResponse, authenticated) DebugSyslogFmt("mode=%v, sendResponse=%v, authenticated=%v\n", mode, sendResponse, authenticated)
// Little more validation of recipient and sender // Little more validation of recipient and sender
// Remove path ('/') from both recipient and sender // Remove path ('/') from both recipient and sender
@ -167,7 +266,7 @@ func main() {
} }
// And now descision making // And now descision making
DebugSyslogFmt(syslg, "recipientUser=%v =? senderUser=%v\n", recipientParts[0], senderParts[0] + "+autoresponse") DebugSyslogFmt("recipientUser=%v =? senderUser=%v\n", recipientParts[0], senderParts[0] + "+autoresponse")
switch true { switch true {
// - (un)set autoresponse via email // - (un)set autoresponse via email
case mode == 0 && recipientParts[0] == senderParts[0] + "+autoresponse": case mode == 0 && recipientParts[0] == senderParts[0] + "+autoresponse":
@ -197,23 +296,50 @@ func main() {
syslg.Err(err.Error()) syslg.Err(err.Error())
os.Exit(1) os.Exit(1)
} }
//!!!
// - set autoresponse via cli // - set autoresponse via cli
case mode == 1 && *enableAutoResponsePtr != "": case mode == 1 && *enableAutoResponsePtr != "":
syslg.Info(fmt.Sprintf("Requested enable autoresponse for %v", *enableAutoResponsePtr))
err := enableAutoresponse(*enableAutoResponsePtr)
//!!! //!!!
if err != nil {
syslg.Err(err.Error())
os.Exit(1)
}
// - disable autoresponse via cli // - disable autoresponse via cli
case mode == 1 && *disableAutoResponsePtr != "": case mode == 1 && *disableAutoResponsePtr != "":
syslg.Info(fmt.Sprintf("Requested disable autoresponse for %v", *disableAutoResponsePtr))
err := disableAutoresponse(*disableAutoResponsePtr)
//!!! //!!!
if err != nil {
syslg.Err(err.Error())
os.Exit(1)
}
// - enable existing autoresponse via cli // - enable existing autoresponse via cli
case mode == 1 && *enableExAutoResponsePtr != "": case mode == 1 && *enableExAutoResponsePtr != "":
syslg.Info(fmt.Sprintf("Requested enable existing autoresponse for %v", *enableExAutoResponsePtr))
err := enableExAutoresponse(*enableExAutoResponsePtr)
//!!! //!!!
if err != nil {
syslg.Err(err.Error())
os.Exit(1)
}
// - delete existing autoresponse via cli // - delete existing autoresponse via cli
case mode == 1 && *deleteAutoResponsePtr != "": case mode == 1 && *deleteAutoResponsePtr != "":
syslg.Info(fmt.Sprintf("Requested delete autoresponse for %v", *deleteAutoResponsePtr))
err := deleteAutoresponse(*deleteAutoResponsePtr, false)
//!!! //!!!
if err != nil {
syslg.Err(err.Error())
os.Exit(1)
}
} }
//!!! //!!!
} }