2
0
forked from drew/smtprelay

feat: add alias file support

This commit is contained in:
Aivars Sterns
2025-10-29 11:50:30 +02:00
committed by Bernhard Fröhlich
parent 6e9c00e171
commit 7b6be95125
5 changed files with 88 additions and 4 deletions

52
aliases.go Normal file
View File

@@ -0,0 +1,52 @@
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type AliasMap map[string]string
func AliasLoadFile(file string) (AliasMap, error) {
aliasMap := make(AliasMap)
count := 0
log.Info().
Str("file", file).
Msg("Loading aliases file")
f, err := os.Open(file)
if err != nil {
log.Fatal().
Str("file", file).
Err(err).
Msg("cannot load aliases file")
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
parts := strings.Fields(line)
if len(parts) >= 2 {
aliasMap[parts[0]] = parts[1]
count++
}
}
log.Info().
Str("file", file).
Msg(fmt.Sprintf("Loaded %d aliases from file", count))
if err := scanner.Err(); err != nil {
log.Fatal().
Str("file", file).
Err(err).
Msg("cannot load aliases file")
}
return aliasMap, nil
}

View File

@@ -42,6 +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")
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")
@@ -59,12 +60,27 @@ var (
allowedSender *regexp.Regexp
allowedRecipients *regexp.Regexp
remotes = []*Remote{}
aliasesList = AliasMap{}
)
func localAuthRequired() bool {
return *allowedUsers != ""
}
func setupAliases() {
if *aliasesFile != "" {
aliases := make(AliasMap)
aliases, err := AliasLoadFile(*aliasesFile)
if err != nil {
log.Fatal().
Str("file", *aliasesFile).
Err(err).
Msg("cannot load aliases file")
}
aliasesList = aliases
}
}
func setupAllowedNetworks() {
for _, netstr := range splitstr(*allowedNetsStr, ' ') {
baseIP, allowedNet, err := net.ParseCIDR(netstr)
@@ -240,6 +256,7 @@ func ConfigLoad() {
setupAllowedNetworks()
setupAllowedPatterns()
setupAliases()
setupRemotes()
setupListeners()
setupTimeouts()

11
main.go
View File

@@ -159,6 +159,17 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
peerIP = addr.IP.String()
}
// Check for aliases
for i, recipient := range env.Recipients {
if alias, exists := aliasesList[recipient]; exists {
env.Recipients[i] = alias
log.Info().
Str("original_recipient", recipient).
Str("aliased_recipient", alias).
Msg("Recipient address aliased")
}
}
logger := log.With().
Str("from", env.Sender).
Strs("to", env.Recipients).

View File

@@ -200,7 +200,7 @@ func (c *Client) Auth(a smtp.Auth) error {
return err
}
encoding := base64.StdEncoding
mech, resp, err := a.Start(&smtp.ServerInfo{c.serverName, c.tls, c.auth})
mech, resp, err := a.Start(&smtp.ServerInfo{Name: c.serverName, TLS: c.tls, Auth: c.auth})
if err != nil {
c.Quit()
return err

View File

@@ -8,10 +8,13 @@
;logfile =
; Log format: default, plain (no timestamp), json
;log_format = default
log_format = default
; Log level: panic, fatal, error, warn, info, debug, trace
;log_level = info
log_level = info
; path to alias file
aliases_file = aliases.txt
; Hostname for this SMTP server
;hostname = localhost.localdomain
@@ -21,7 +24,8 @@
; Listen on the following addresses for incoming
; unencrypted connections.
;listen = 127.0.0.1:25 [::1]:25
listen = 127.0.0.1:8025
#[::1]:25
; STARTTLS and TLS are also supported but need a
; SSL certificate and key.