Towards first version.

This commit is contained in:
urosj 2017-07-25 11:51:03 +02:00
parent 13a5afb5fc
commit 70713c71d8

View File

@ -2,24 +2,75 @@ package main
// This is postfix autoresponder, which is rewrite of the autoresponder bash script V1.6.3, written by Charles Hamilton - musashi@nefaria.com // This is postfix autoresponder, which is rewrite of the autoresponder bash script V1.6.3, written by Charles Hamilton - musashi@nefaria.com
// //
// How to make it work on a server with postfix installed:
// =======================================================
// Create autoresponse username:
// useradd -d /var/spool/autoresponse -s `which nologin` autoresponse
//
// Copy autoresponse binary to /usr/local/sbin
// cp autoresponse /usr/local/sbin/
//
// RESPONSE_DIR, RATE_LOG_DIR must be created:
// mkdir -p /var/spool/autoresponse/log /var/spool/autoresponse/responses
// chown -R autoresponse:autoresponse /var/spool/autoresponse
// chmod -R 0770 /var/spool/autoresponse
//
// Edit /etc/postfix/master.cf:
// Replace line:
// smtp inet n - - - - smtpd
// with these two lines (second must begin with at least one space or tab):
// smtp inet n - - - - smtpd
// -o content_filter=autoresponder:dummy
// At the end of file append the following two lines:
// autoresponder unix - n n - - pipe
// flags=Fq user=autoresponse argv=/usr/local/sbin/autoresponse -s ${sender} -r ${recipient} -S ${sasl_username} -C ${client_address}
//
//
// Written by Uros Juvan <asmpro@gmail.com> 2017 // Written by Uros Juvan <asmpro@gmail.com> 2017
import ( import (
"fmt" "fmt"
"flag" "flag"
"os" "os"
"strings"
"log/syslog"
) )
const VERSION = "1.0.0001" const VERSION = "1.0.0001"
const DEBUG = true const DEBUG = true
const RESPONSE_DIR = "/var/spool/autoresponse/responses"
const RATE_LOG_DIR = "/var/spool/autoresponse/log"
const SENDMAIL_BIN = "/usr/sbin/sendmail"
// 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{}) {
if DEBUG {
syslg.Debug(fmt.Sprintf("DEBUG: " + format, v...))
}
}
// Set autoresponse using supplied arguments and stdin (email body)
func setAutoresponseViaEmail(recipient, sender, saslUser, clientIp string) error {
//!!!
return nil
}
func main() { func main() {
// Connect to syslog
syslg, err := syslog.New(syslog.LOG_MAIL, "autoresponder")
if err != nil {
os.Exit(1)
}
defer syslg.Close()
// Parse command line arguments // Parse command line arguments
recipientPtr := flag.String("r", "", "Recipient e-mail") recipientPtr := flag.String("r", "", "Recipient e-mail")
senderPtr := flag.String("s", "", "Sender e-mail") senderPtr := flag.String("s", "", "Sender e-mail")
@ -29,27 +80,47 @@ func main() {
disableAutoResponsePtr := flag.String("d", "", "Disable autoresponse") disableAutoResponsePtr := flag.String("d", "", "Disable autoresponse")
enableExAutoResponsePtr := flag.String("E", "", "Enable existing autoresponse") enableExAutoResponsePtr := flag.String("E", "", "Enable existing autoresponse")
deleteAutoResponsePtr := flag.String("D", "", "Delete autoresponse") deleteAutoResponsePtr := flag.String("D", "", "Delete autoresponse")
instructions := flag.Bool("i", false, "Setup instructions")
flag.Parse() flag.Parse()
if DEBUG { 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",
DebugFmtPrintf(`Flags: *recipientPtr,
Recipient: %v *senderPtr,
Sender: %v *saslUserPtr,
SASL authenticated username: %v *clientIpPtr,
Client IP: %v *enableAutoResponsePtr,
Enable autoresponse: %v *disableAutoResponsePtr,
Disable autoresponse: %v *enableExAutoResponsePtr,
Enable existing autoresponse: %v *deleteAutoResponsePtr,
Delete autoresponse: %v *instructions)
`,
*recipientPtr, // If setup instructions are requested, just print them to stdout and exit
*senderPtr, if *instructions {
*saslUserPtr, fmt.Print(`
*clientIpPtr, How to make it work on a server with postfix installed:
*enableAutoResponsePtr, =======================================================
*disableAutoResponsePtr, Create autoresponse username:
*enableExAutoResponsePtr, useradd -d /var/spool/autoresponse -s $(which nologin) autoresponse
*deleteAutoResponsePtr)
Copy autoresponse binary to /usr/local/sbin
cp autoresponse /usr/local/sbin/
RESPONSE_DIR, RATE_LOG_DIR must be created:
mkdir -p /var/spool/autoresponse/log /var/spool/autoresponse/responses
chown -R autoresponse:autoresponse /var/spool/autoresponse
chmod -R 0770 /var/spool/autoresponse
Edit /etc/postfix/master.cf:
Replace line:
smtp inet n - - - - smtpd
with these two lines (second must begin with at least one space or tab):
smtp inet n - - - - smtpd
-o content_filter=autoresponder:dummy
At the end of file append the following two lines:
autoresponder unix - n n - - pipe
flags=Fq user=autoresponse argv=/usr/local/sbin/autoresponse -s ${sender} -r ${recipient} -S ${sasl_username} -C ${client_address}
`)
os.Exit(0)
} }
// Do some logic on command line arguments // Do some logic on command line arguments
@ -63,11 +134,35 @@ func main() {
if *recipientPtr != "" && *senderPtr != "" { if *recipientPtr != "" && *senderPtr != "" {
sendResponse = true sendResponse = true
} }
if *saslUserPtr != "" && os.Getenv("SASL_USERNAME") != "" { if *saslUserPtr != "" {
authenticated = true authenticated = true
} }
if *enableAutoResponsePtr != "" || *disableAutoResponsePtr != "" || *enableExAutoResponsePtr != "" || *deleteAutoResponsePtr != "" { if *enableAutoResponsePtr != "" || *disableAutoResponsePtr != "" || *enableExAutoResponsePtr != "" || *deleteAutoResponsePtr != "" {
mode = 1 mode = 1
} }
DebugFmtPrintf("mode=%v, sendResponse=%v, authenticated=%v\n", mode, sendResponse, authenticated) DebugSyslogFmt(syslg, "mode=%v, sendResponse=%v, authenticated=%v\n", mode, sendResponse, authenticated)
recipientParts := strings.Split(*recipientPtr, "@")
senderParts := strings.Split(*senderPtr, "@")
// Little more validation of recipient and sender
if len(recipientParts) < 2 {
syslg.Err(fmt.Sprintf("Invalid recipient %v", *recipientPtr))
os.Exit(1)
}
if len(senderParts) < 2 {
syslg.Err(fmt.Sprintf("Invalid sender %v", *senderPtr))
os.Exit(1)
}
// And now descision making
DebugSyslogFmt(syslg, "recipientUser=%v =? senderUser=%v\n", recipientParts[0], senderParts[0] + "+autoresponse")
if mode == 0 && authenticated && recipientParts[0] == senderParts[0] + "+autoresponse" {
syslg.Info(fmt.Sprintf("Requested autoresponse (un)set via email for email %v", *senderPtr))
err := setAutoresponseViaEmail(*recipientPtr, *senderPtr, *saslUserPtr, *clientIpPtr)
if err != nil {
syslg.Err(err.Error())
os.Exit(1)
}
}
//!!!
} }