mirror of
https://github.com/decke/smtprelay.git
synced 2025-12-25 16:52:29 -07:00
feat: dynamic reread of aliases
This commit is contained in:
committed by
Bernhard Fröhlich
parent
381a9b334b
commit
b164ce1387
20
aliases.go
20
aliases.go
@@ -5,10 +5,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AliasMap map[string]string
|
type AliasMap map[string]string
|
||||||
|
|
||||||
|
var (
|
||||||
|
aliasesMutex sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
func AliasLoadFile(file string) (AliasMap, error) {
|
func AliasLoadFile(file string) (AliasMap, error) {
|
||||||
aliasMap := make(AliasMap)
|
aliasMap := make(AliasMap)
|
||||||
count := 0
|
count := 0
|
||||||
@@ -50,3 +55,18 @@ func AliasLoadFile(file string) (AliasMap, error) {
|
|||||||
}
|
}
|
||||||
return aliasMap, nil
|
return aliasMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadAliases(filename string) error {
|
||||||
|
newAliases, err := AliasLoadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
aliasesMutex.Lock()
|
||||||
|
defer aliasesMutex.Unlock()
|
||||||
|
|
||||||
|
// Update the aliases map
|
||||||
|
aliasesList = newAliases
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ var (
|
|||||||
allowedSenderStr = flagset.String("allowed_sender", "", "Regular expression for valid FROM EMail addresses")
|
allowedSenderStr = flagset.String("allowed_sender", "", "Regular expression for valid FROM EMail addresses")
|
||||||
allowedRecipStr = flagset.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses")
|
allowedRecipStr = flagset.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses")
|
||||||
allowedUsers = flagset.String("allowed_users", "", "Path to file with valid users/passwords")
|
allowedUsers = flagset.String("allowed_users", "", "Path to file with valid users/passwords")
|
||||||
aliasesFile = flagset.String("aliases_file", "", "Path to aliases file")
|
aliasFile = flagset.String("aliases_file", "", "Path to aliases file")
|
||||||
command = flagset.String("command", "", "Path to pipe command")
|
command = flagset.String("command", "", "Path to pipe command")
|
||||||
remotesStr = flagset.String("remotes", "", "Outgoing SMTP servers")
|
remotesStr = flagset.String("remotes", "", "Outgoing SMTP servers")
|
||||||
strictSender = flagset.Bool("strict_sender", false, "Use only SMTP servers with Sender matches to From")
|
strictSender = flagset.Bool("strict_sender", false, "Use only SMTP servers with Sender matches to From")
|
||||||
@@ -68,12 +68,12 @@ func localAuthRequired() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupAliases() {
|
func setupAliases() {
|
||||||
if *aliasesFile != "" {
|
if *aliasFile != "" {
|
||||||
aliases := make(AliasMap)
|
aliases := make(AliasMap)
|
||||||
aliases, err := AliasLoadFile(*aliasesFile)
|
aliases, err := AliasLoadFile(*aliasFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().
|
log.Fatal().
|
||||||
Str("file", *aliasesFile).
|
Str("file", *aliasFile).
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("cannot load aliases file")
|
Msg("cannot load aliases file")
|
||||||
}
|
}
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -3,6 +3,7 @@ module github.com/decke/smtprelay
|
|||||||
require (
|
require (
|
||||||
github.com/DeRuina/timberjack v1.3.9
|
github.com/DeRuina/timberjack v1.3.9
|
||||||
github.com/chrj/smtpd v0.3.1
|
github.com/chrj/smtpd v0.3.1
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/peterbourgon/ff/v3 v3.4.0
|
github.com/peterbourgon/ff/v3 v3.4.0
|
||||||
github.com/rs/zerolog v1.34.0
|
github.com/rs/zerolog v1.34.0
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -7,6 +7,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
|||||||
71
main.go
71
main.go
@@ -13,6 +13,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/chrj/smtpd"
|
"github.com/chrj/smtpd"
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -160,6 +161,7 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for aliases
|
// Check for aliases
|
||||||
|
aliasesMutex.RLock()
|
||||||
for i, recipient := range env.Recipients {
|
for i, recipient := range env.Recipients {
|
||||||
if alias, exists := aliasesList[recipient]; exists {
|
if alias, exists := aliasesList[recipient]; exists {
|
||||||
env.Recipients[i] = alias
|
env.Recipients[i] = alias
|
||||||
@@ -169,6 +171,7 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
|
|||||||
Msg("Recipient address aliased")
|
Msg("Recipient address aliased")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
aliasesMutex.RUnlock()
|
||||||
|
|
||||||
logger := log.With().
|
logger := log.With().
|
||||||
Str("from", env.Sender).
|
Str("from", env.Sender).
|
||||||
@@ -297,6 +300,71 @@ func getTLSConfig() *tls.Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func watchAliasFile() {
|
||||||
|
if *aliasFile == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Msg("failed to create file watcher for alias file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event, ok := <-watcher.Events:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Has(fsnotify.Write) || event.Has(fsnotify.Create) {
|
||||||
|
log.Info().
|
||||||
|
Str("file", event.Name).
|
||||||
|
Msg("alias file changed, reloading")
|
||||||
|
|
||||||
|
err := LoadAliases(*aliasFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().
|
||||||
|
Str("file", *aliasFile).
|
||||||
|
Err(err).
|
||||||
|
Msg("failed to reload alias file")
|
||||||
|
} else {
|
||||||
|
log.Info().
|
||||||
|
Int("count", len(aliasesList)).
|
||||||
|
Msg("alias file reloaded successfully")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case err, ok := <-watcher.Errors:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Msg("file watcher error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = watcher.Add(*aliasFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().
|
||||||
|
Str("file", *aliasFile).
|
||||||
|
Err(err).
|
||||||
|
Msg("failed to watch alias file")
|
||||||
|
} else {
|
||||||
|
log.Info().
|
||||||
|
Str("file", *aliasFile).
|
||||||
|
Msg("watching alias file for changes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ConfigLoad()
|
ConfigLoad()
|
||||||
|
|
||||||
@@ -315,6 +383,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start watching alias file for changes
|
||||||
|
watchAliasFile()
|
||||||
|
|
||||||
var servers []*smtpd.Server
|
var servers []*smtpd.Server
|
||||||
|
|
||||||
// Create a server for each desired listen address
|
// Create a server for each desired listen address
|
||||||
|
|||||||
Reference in New Issue
Block a user