mirror of
https://github.com/decke/smtprelay.git
synced 2025-12-24 23:32:34 -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"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type AliasMap map[string]string
|
||||
|
||||
var (
|
||||
aliasesMutex sync.RWMutex
|
||||
)
|
||||
|
||||
func AliasLoadFile(file string) (AliasMap, error) {
|
||||
aliasMap := make(AliasMap)
|
||||
count := 0
|
||||
@@ -50,3 +55,18 @@ func AliasLoadFile(file string) (AliasMap, error) {
|
||||
}
|
||||
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")
|
||||
allowedRecipStr = flagset.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses")
|
||||
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")
|
||||
remotesStr = flagset.String("remotes", "", "Outgoing SMTP servers")
|
||||
strictSender = flagset.Bool("strict_sender", false, "Use only SMTP servers with Sender matches to From")
|
||||
@@ -68,12 +68,12 @@ func localAuthRequired() bool {
|
||||
}
|
||||
|
||||
func setupAliases() {
|
||||
if *aliasesFile != "" {
|
||||
if *aliasFile != "" {
|
||||
aliases := make(AliasMap)
|
||||
aliases, err := AliasLoadFile(*aliasesFile)
|
||||
aliases, err := AliasLoadFile(*aliasFile)
|
||||
if err != nil {
|
||||
log.Fatal().
|
||||
Str("file", *aliasesFile).
|
||||
Str("file", *aliasFile).
|
||||
Err(err).
|
||||
Msg("cannot load aliases file")
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -3,6 +3,7 @@ module github.com/decke/smtprelay
|
||||
require (
|
||||
github.com/DeRuina/timberjack v1.3.9
|
||||
github.com/chrj/smtpd v0.3.1
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/peterbourgon/ff/v3 v3.4.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/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
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"
|
||||
|
||||
"github.com/chrj/smtpd"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -160,6 +161,7 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
|
||||
}
|
||||
|
||||
// Check for aliases
|
||||
aliasesMutex.RLock()
|
||||
for i, recipient := range env.Recipients {
|
||||
if alias, exists := aliasesList[recipient]; exists {
|
||||
env.Recipients[i] = alias
|
||||
@@ -169,6 +171,7 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
|
||||
Msg("Recipient address aliased")
|
||||
}
|
||||
}
|
||||
aliasesMutex.RUnlock()
|
||||
|
||||
logger := log.With().
|
||||
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() {
|
||||
ConfigLoad()
|
||||
|
||||
@@ -315,6 +383,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Start watching alias file for changes
|
||||
watchAliasFile()
|
||||
|
||||
var servers []*smtpd.Server
|
||||
|
||||
// Create a server for each desired listen address
|
||||
|
||||
Reference in New Issue
Block a user