mirror of
https://github.com/decke/smtprelay.git
synced 2025-12-26 02:42:33 -07:00
Merge pull request #19 from decke/allow-any-sender-recipient
Move remaining config option parsing to ConfigLoad()
This commit is contained in:
79
config.go
79
config.go
@@ -3,6 +3,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"net/smtp"
|
||||||
|
|
||||||
"github.com/vharitonsky/iniflags"
|
"github.com/vharitonsky/iniflags"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -25,13 +27,16 @@ var (
|
|||||||
localForceTLS = flag.Bool("local_forcetls", false, "Force STARTTLS (needs local_cert and local_key)")
|
localForceTLS = flag.Bool("local_forcetls", false, "Force STARTTLS (needs local_cert and local_key)")
|
||||||
allowedNetsStr = flag.String("allowed_nets", "127.0.0.0/8 ::1/128", "Networks allowed to send mails")
|
allowedNetsStr = flag.String("allowed_nets", "127.0.0.0/8 ::1/128", "Networks allowed to send mails")
|
||||||
allowedNets = []*net.IPNet{}
|
allowedNets = []*net.IPNet{}
|
||||||
allowedSender = flag.String("allowed_sender", "", "Regular expression for valid FROM EMail addresses")
|
allowedSenderStr = flag.String("allowed_sender", "", "Regular expression for valid FROM EMail addresses")
|
||||||
allowedRecipients = flag.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses")
|
allowedSender *regexp.Regexp
|
||||||
|
allowedRecipStr = flag.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses")
|
||||||
|
allowedRecipients *regexp.Regexp
|
||||||
allowedUsers = flag.String("allowed_users", "", "Path to file with valid users/passwords")
|
allowedUsers = flag.String("allowed_users", "", "Path to file with valid users/passwords")
|
||||||
remoteHost = flag.String("remote_host", "", "Outgoing SMTP server")
|
remoteHost = flag.String("remote_host", "", "Outgoing SMTP server")
|
||||||
remoteUser = flag.String("remote_user", "", "Username for authentication on outgoing SMTP server")
|
remoteUser = flag.String("remote_user", "", "Username for authentication on outgoing SMTP server")
|
||||||
remotePass = flag.String("remote_pass", "", "Password for authentication on outgoing SMTP server")
|
remotePass = flag.String("remote_pass", "", "Password for authentication on outgoing SMTP server")
|
||||||
remoteAuth = flag.String("remote_auth", "plain", "Auth method on outgoing SMTP server (plain, login)")
|
remoteAuthStr = flag.String("remote_auth", "none", "Auth method on outgoing SMTP server (none, plain, login)")
|
||||||
|
remoteAuth smtp.Auth
|
||||||
remoteSender = flag.String("remote_sender", "", "Sender e-mail address on outgoing SMTP server")
|
remoteSender = flag.String("remote_sender", "", "Sender e-mail address on outgoing SMTP server")
|
||||||
versionInfo = flag.Bool("version", false, "Show version information")
|
versionInfo = flag.Bool("version", false, "Show version information")
|
||||||
)
|
)
|
||||||
@@ -59,6 +64,72 @@ func setupAllowedNetworks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupAllowedPatterns() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if (*allowedSenderStr != "") {
|
||||||
|
allowedSender, err = regexp.Compile(*allowedSenderStr)
|
||||||
|
if err != nil {
|
||||||
|
log.WithField("allowed_sender", *allowedSenderStr).
|
||||||
|
WithError(err).
|
||||||
|
Fatal("allowed_sender pattern invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*allowedRecipStr != "") {
|
||||||
|
allowedRecipients, err = regexp.Compile(*allowedRecipStr)
|
||||||
|
if err != nil {
|
||||||
|
log.WithField("allowed_recipients", *allowedRecipStr).
|
||||||
|
WithError(err).
|
||||||
|
Fatal("allowed_recipients pattern invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func setupRemoteAuth() {
|
||||||
|
logger := log.WithField("remote_auth", *remoteAuthStr)
|
||||||
|
|
||||||
|
// Remote auth disabled?
|
||||||
|
if *remoteAuthStr == "" || *remoteAuthStr == "none" {
|
||||||
|
if *remoteUser != "" {
|
||||||
|
logger.Fatal("remote_user given but not used")
|
||||||
|
}
|
||||||
|
if *remotePass != "" {
|
||||||
|
logger.Fatal("remote_pass given but not used")
|
||||||
|
}
|
||||||
|
|
||||||
|
// No auth; use empty default
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need a username, password, and remote host
|
||||||
|
if *remoteUser == "" {
|
||||||
|
logger.Fatal("remote_user required but empty")
|
||||||
|
}
|
||||||
|
if *remotePass == "" {
|
||||||
|
logger.Fatal("remote_pass required but empty")
|
||||||
|
}
|
||||||
|
if *remoteHost == "" {
|
||||||
|
logger.Fatal("remote_auth without remote_host is pointless")
|
||||||
|
}
|
||||||
|
|
||||||
|
host, _, err := net.SplitHostPort(*remoteHost)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithField("remote_host", *remoteHost).
|
||||||
|
Fatal("Invalid remote_host")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *remoteAuthStr {
|
||||||
|
case "plain":
|
||||||
|
remoteAuth = smtp.PlainAuth("", *remoteUser, *remotePass, host)
|
||||||
|
case "login":
|
||||||
|
remoteAuth = LoginAuth(*remoteUser, *remotePass)
|
||||||
|
default:
|
||||||
|
logger.Fatal("Invalid remote_auth type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ConfigLoad() {
|
func ConfigLoad() {
|
||||||
iniflags.Parse()
|
iniflags.Parse()
|
||||||
|
|
||||||
@@ -70,4 +141,6 @@ func ConfigLoad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupAllowedNetworks()
|
setupAllowedNetworks()
|
||||||
|
setupAllowedPatterns()
|
||||||
|
setupRemoteAuth()
|
||||||
}
|
}
|
||||||
|
|||||||
48
main.go
48
main.go
@@ -4,10 +4,8 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/smtp"
|
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -103,43 +101,31 @@ func senderChecker(peer smtpd.Peer, addr string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if *allowedSender == "" {
|
if allowedSender == nil {
|
||||||
|
// Any sender is permitted
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
re, err := regexp.Compile(*allowedSender)
|
if allowedSender.MatchString(addr) {
|
||||||
if err != nil {
|
// Permitted by regex
|
||||||
log.WithFields(logrus.Fields{
|
|
||||||
"allowed_sender": *allowedSender,
|
|
||||||
}).WithError(err).Warn("allowed_sender pattern invalid")
|
|
||||||
return smtpd.Error{Code: 451, Message: "Bad sender address"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if re.MatchString(addr) {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
"sender_address": addr,
|
"sender_address": addr,
|
||||||
"peer": peer.Addr,
|
"peer": peer.Addr,
|
||||||
}).Warn("Sender address not allowed by allowed_sender pattern")
|
}).Warn("sender address not allowed by allowed_sender pattern")
|
||||||
return smtpd.Error{Code: 451, Message: "Bad sender address"}
|
return smtpd.Error{Code: 451, Message: "Bad sender address"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func recipientChecker(peer smtpd.Peer, addr string) error {
|
func recipientChecker(peer smtpd.Peer, addr string) error {
|
||||||
if *allowedRecipients == "" {
|
if allowedRecipients == nil {
|
||||||
|
// Any recipient is permitted
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
re, err := regexp.Compile(*allowedRecipients)
|
if allowedRecipients.MatchString(addr) {
|
||||||
if err != nil {
|
// Permitted by regex
|
||||||
log.WithFields(logrus.Fields{
|
|
||||||
"allowed_recipients": *allowedRecipients,
|
|
||||||
}).WithError(err).Warn("allowed_recipients pattern invalid")
|
|
||||||
return smtpd.Error{Code: 451, Message: "Bad recipient address"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if re.MatchString(addr) {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,20 +169,6 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
|
|||||||
|
|
||||||
logger.Info("delivering mail from peer using smarthost")
|
logger.Info("delivering mail from peer using smarthost")
|
||||||
|
|
||||||
var auth smtp.Auth
|
|
||||||
host, _, _ := net.SplitHostPort(*remoteHost)
|
|
||||||
|
|
||||||
if *remoteUser != "" && *remotePass != "" {
|
|
||||||
switch *remoteAuth {
|
|
||||||
case "plain":
|
|
||||||
auth = smtp.PlainAuth("", *remoteUser, *remotePass, host)
|
|
||||||
case "login":
|
|
||||||
auth = LoginAuth(*remoteUser, *remotePass)
|
|
||||||
default:
|
|
||||||
return smtpd.Error{Code: 530, Message: "Authentication method not supported"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env.AddReceivedLine(peer)
|
env.AddReceivedLine(peer)
|
||||||
|
|
||||||
var sender string
|
var sender string
|
||||||
@@ -209,7 +181,7 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
|
|||||||
|
|
||||||
err := SendMail(
|
err := SendMail(
|
||||||
*remoteHost,
|
*remoteHost,
|
||||||
auth,
|
remoteAuth,
|
||||||
sender,
|
sender,
|
||||||
env.Recipients,
|
env.Recipients,
|
||||||
env.Data,
|
env.Data,
|
||||||
|
|||||||
@@ -35,10 +35,12 @@
|
|||||||
;allowed_nets = 127.0.0.0/8 ::1/128
|
;allowed_nets = 127.0.0.0/8 ::1/128
|
||||||
|
|
||||||
; Regular expression for valid FROM EMail addresses
|
; Regular expression for valid FROM EMail addresses
|
||||||
|
; If set to "", then any sender is permitted.
|
||||||
; Example: ^(.*)@localhost.localdomain$
|
; Example: ^(.*)@localhost.localdomain$
|
||||||
;allowed_sender =
|
;allowed_sender =
|
||||||
|
|
||||||
; Regular expression for valid TO EMail addresses
|
; Regular expression for valid TO EMail addresses
|
||||||
|
; If set to "", then any recipient is permitted.
|
||||||
; Example: ^(.*)@localhost.localdomain$
|
; Example: ^(.*)@localhost.localdomain$
|
||||||
;allowed_recipients =
|
;allowed_recipients =
|
||||||
|
|
||||||
@@ -71,8 +73,8 @@
|
|||||||
;remote_pass =
|
;remote_pass =
|
||||||
|
|
||||||
; Authentication method on outgoing SMTP server
|
; Authentication method on outgoing SMTP server
|
||||||
; (plain, login)
|
; (none, plain, login)
|
||||||
;remote_auth = plain
|
;remote_auth = none
|
||||||
|
|
||||||
; Sender e-mail address on outgoing SMTP server
|
; Sender e-mail address on outgoing SMTP server
|
||||||
;remote_sender =
|
;remote_sender =
|
||||||
|
|||||||
Reference in New Issue
Block a user