Towards first version.
This commit is contained in:
parent
ecf6948d93
commit
b42a3a8e29
@ -31,9 +31,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"flag"
|
"flag"
|
||||||
|
"time"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"bufio"
|
"bufio"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -108,7 +110,7 @@ func setAutoresponseViaEmail(recipient, sender, saslUser, clientIp string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ! fileExists(senderResponsePath) {
|
if ! fileExists(senderResponsePath) {
|
||||||
syslg.Info(fmt.Sprintf("Autoresponse disabled for address: %v by SASL authenticated user: %v from: %v",
|
syslg.Info(fmt.Sprintf("Autoresponse disabled for address %v by SASL authenticated user: %v from: %v",
|
||||||
sender, saslUser, clientIp))
|
sender, saslUser, clientIp))
|
||||||
// Send mail via sendmail
|
// Send mail via sendmail
|
||||||
sendMail(recipient, sender, func(sink io.WriteCloser) {
|
sendMail(recipient, sender, func(sink io.WriteCloser) {
|
||||||
@ -173,7 +175,20 @@ func setAutoresponseViaEmail(recipient, sender, saslUser, clientIp string) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//!!!
|
|
||||||
|
if fileExists(senderResponsePath) {
|
||||||
|
syslg.Info(fmt.Sprintf("Autoresponse enabled 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 enabled for %v by SASL authenticated user: %v from: %v\n",
|
||||||
|
recipient, sender, sender, saslUser, clientIp)))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Autoresponse could not be enabled for address %v", sender)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -186,23 +201,156 @@ func forwardEmailAndAutoresponse(recipient, sender, saslUser, clientIp string, r
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get text editor
|
||||||
|
func getTextEditor() string {
|
||||||
|
editor := os.Getenv("EDITOR")
|
||||||
|
if editor == "" {
|
||||||
|
editor = "vi"
|
||||||
|
}
|
||||||
|
|
||||||
|
return editor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file modification time
|
||||||
|
func getFileModTime(name string) (t time.Time, err error) {
|
||||||
|
st, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
return t, err
|
||||||
|
}
|
||||||
|
t = st.ModTime()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Enable autoresponse for email
|
// Enable autoresponse for email
|
||||||
func enableAutoresponse(email string) error {
|
func enableAutoresponse(email string) error {
|
||||||
//!!!
|
emailResponsePath := filepath.Join(RESPONSE_DIR, email)
|
||||||
|
editFilePath := emailResponsePath
|
||||||
|
|
||||||
|
// If editFilePath does not exist, also try to enable previosly disabled autoresponse
|
||||||
|
if ! fileExists(editFilePath) {
|
||||||
|
enableExAutoresponse(email, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If file does not exist yet, create template file as tmp file
|
||||||
|
var oldModTime, newModTime time.Time
|
||||||
|
if ! fileExists(editFilePath) {
|
||||||
|
editFile, err := ioutil.TempFile("", "autoresponder")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
editFilePath = editFile.Name()
|
||||||
|
defer os.Remove(editFilePath)
|
||||||
|
|
||||||
|
writer := bufio.NewWriter(editFile)
|
||||||
|
|
||||||
|
// Write template to file
|
||||||
|
writer.WriteString(fmt.Sprintf(`From: %v
|
||||||
|
To: THIS GETS REPLACED
|
||||||
|
Subject: Autoresponder
|
||||||
|
|
||||||
|
mail body`, email))
|
||||||
|
|
||||||
|
writer.Flush()
|
||||||
|
editFile.Close()
|
||||||
|
}
|
||||||
|
oldModTime, err := getFileModTime(editFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke either EDITOR environment or vi command
|
||||||
|
cmd := exec.Command(getTextEditor(), editFilePath)
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newModTime, err = getFileModTime(editFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldModTime != newModTime {
|
||||||
|
if emailResponsePath != editFilePath {
|
||||||
|
// Open editFilePath for reading and emailResponsePath for writing and Copy content over
|
||||||
|
tmpFl, err := os.Open(editFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tmpFl.Close()
|
||||||
|
|
||||||
|
resFl, err := os.OpenFile(emailResponsePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0660)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resFl.Chmod(0660)
|
||||||
|
defer resFl.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(resFl, tmpFl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf("Edited %v", emailResponsePath)
|
||||||
|
syslg.Info(msg)
|
||||||
|
fmt.Println(msg)
|
||||||
|
} else {
|
||||||
|
msg := fmt.Sprintf("Editing %v aborted!", emailResponsePath)
|
||||||
|
fmt.Println(msg)
|
||||||
|
return fmt.Errorf("%v", msg)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable autoresponse for email
|
// Disable autoresponse for email
|
||||||
func disableAutoresponse(email string) error {
|
func disableAutoresponse(email string) error {
|
||||||
//!!!
|
emailResponsePath := filepath.Join(RESPONSE_DIR, email)
|
||||||
|
|
||||||
|
if fileExists(emailResponsePath) {
|
||||||
|
disableEmailResponsePath := emailResponsePath + "_DISABLED"
|
||||||
|
os.Remove(disableEmailResponsePath)
|
||||||
|
err := os.Rename(emailResponsePath, disableEmailResponsePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf("Disabled %v", emailResponsePath)
|
||||||
|
syslg.Info(msg)
|
||||||
|
fmt.Println(msg)
|
||||||
|
} else {
|
||||||
|
msg := fmt.Sprintf("%v does not exist, thus it cannot be disabled!", emailResponsePath)
|
||||||
|
fmt.Println(msg)
|
||||||
|
return fmt.Errorf("%v", msg)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable existing autoresponse for email
|
// Enable existing autoresponse for email
|
||||||
func enableExAutoresponse(email string) error {
|
func enableExAutoresponse(email string, nostdout bool) error {
|
||||||
//!!!
|
emailResponsePath := filepath.Join(RESPONSE_DIR, email)
|
||||||
|
disableEmailResponsePath := emailResponsePath + "_DISABLED"
|
||||||
|
|
||||||
|
if fileExists(disableEmailResponsePath) {
|
||||||
|
os.Remove(emailResponsePath)
|
||||||
|
err := os.Rename(disableEmailResponsePath, emailResponsePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf("Enabled %v", emailResponsePath)
|
||||||
|
syslg.Info(msg)
|
||||||
|
fmt.Println(msg)
|
||||||
|
} else {
|
||||||
|
msg := fmt.Sprintf("%v does not exist, thus it cannot be enabled!", disableEmailResponsePath)
|
||||||
|
if ! nostdout {
|
||||||
|
fmt.Println(msg)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%v", msg)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -219,6 +367,11 @@ func deleteAutoresponse(email string, nostdout bool) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("%v", msg)
|
return fmt.Errorf("%v", msg)
|
||||||
}
|
}
|
||||||
|
msg := fmt.Sprintf("Delete %v done", deleteResponsePath)
|
||||||
|
if ! nostdout {
|
||||||
|
fmt.Println(msg)
|
||||||
|
}
|
||||||
|
syslg.Info(msg)
|
||||||
} else {
|
} else {
|
||||||
msg := fmt.Sprintf("%v does not exist, thus it cannot be deleted!", deleteResponsePath)
|
msg := fmt.Sprintf("%v does not exist, thus it cannot be deleted!", deleteResponsePath)
|
||||||
if ! nostdout {
|
if ! nostdout {
|
||||||
@ -319,11 +472,11 @@ func main() {
|
|||||||
*senderPtr = strings.Replace(*senderPtr, "/", "", -1)
|
*senderPtr = strings.Replace(*senderPtr, "/", "", -1)
|
||||||
recipientParts := strings.Split(*recipientPtr, "@")
|
recipientParts := strings.Split(*recipientPtr, "@")
|
||||||
senderParts := strings.Split(*senderPtr, "@")
|
senderParts := strings.Split(*senderPtr, "@")
|
||||||
if len(recipientParts) < 2 {
|
if *recipientPtr != "" && len(recipientParts) < 2 {
|
||||||
syslg.Err(fmt.Sprintf("Invalid recipient %v", *recipientPtr))
|
syslg.Err(fmt.Sprintf("Invalid recipient %v", *recipientPtr))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if len(senderParts) < 2 {
|
if *senderPtr != "" && len(senderParts) < 2 {
|
||||||
syslg.Err(fmt.Sprintf("Invalid sender %v", *senderPtr))
|
syslg.Err(fmt.Sprintf("Invalid sender %v", *senderPtr))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -343,7 +496,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := setAutoresponseViaEmail(*recipientPtr, *senderPtr, *saslUserPtr, *clientIpPtr)
|
err := setAutoresponseViaEmail(*recipientPtr, *senderPtr, *saslUserPtr, *clientIpPtr)
|
||||||
//!!!
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syslg.Err(err.Error())
|
syslg.Err(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -365,7 +517,6 @@ func main() {
|
|||||||
syslg.Info(fmt.Sprintf("Requested enable autoresponse for %v", *enableAutoResponsePtr))
|
syslg.Info(fmt.Sprintf("Requested enable autoresponse for %v", *enableAutoResponsePtr))
|
||||||
|
|
||||||
err := enableAutoresponse(*enableAutoResponsePtr)
|
err := enableAutoresponse(*enableAutoResponsePtr)
|
||||||
//!!!
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syslg.Err(err.Error())
|
syslg.Err(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -376,7 +527,6 @@ func main() {
|
|||||||
syslg.Info(fmt.Sprintf("Requested disable autoresponse for %v", *disableAutoResponsePtr))
|
syslg.Info(fmt.Sprintf("Requested disable autoresponse for %v", *disableAutoResponsePtr))
|
||||||
|
|
||||||
err := disableAutoresponse(*disableAutoResponsePtr)
|
err := disableAutoresponse(*disableAutoResponsePtr)
|
||||||
//!!!
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syslg.Err(err.Error())
|
syslg.Err(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -386,8 +536,7 @@ func main() {
|
|||||||
case mode == 1 && *enableExAutoResponsePtr != "":
|
case mode == 1 && *enableExAutoResponsePtr != "":
|
||||||
syslg.Info(fmt.Sprintf("Requested enable existing autoresponse for %v", *enableExAutoResponsePtr))
|
syslg.Info(fmt.Sprintf("Requested enable existing autoresponse for %v", *enableExAutoResponsePtr))
|
||||||
|
|
||||||
err := enableExAutoresponse(*enableExAutoResponsePtr)
|
err := enableExAutoresponse(*enableExAutoResponsePtr, false)
|
||||||
//!!!
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syslg.Err(err.Error())
|
syslg.Err(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -398,11 +547,9 @@ func main() {
|
|||||||
syslg.Info(fmt.Sprintf("Requested delete autoresponse for %v", *deleteAutoResponsePtr))
|
syslg.Info(fmt.Sprintf("Requested delete autoresponse for %v", *deleteAutoResponsePtr))
|
||||||
|
|
||||||
err := deleteAutoresponse(*deleteAutoResponsePtr, false)
|
err := deleteAutoresponse(*deleteAutoResponsePtr, false)
|
||||||
//!!!
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syslg.Err(err.Error())
|
syslg.Err(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//!!!
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user