ソースを参照

Move SMTP auth setup to ConfigLoad()

This has several benefits:
- Configuration errors are caught at startup rather than upon a connection
- mailHandler() has less work to do for each connection

Rather than relying on remote_user and remote_pass to control whether
authentication is used, introduce an explicit "none" type for
remote_auth, and make that the default. (This is effectively the same
default behavior since remote_user and remote_pass default to empty.)

Also, we are in a better position to more thoroughly check for
configuration errors or mismatches:
- If remote_auth is given, remote_user and remote_pass are required.
- If remote_auth is given, remote_host is also required (because it
  makes no sense to say we're going to authenticate if we have no server
  to which to authenticate.)
- If remote_user or remote_pass are given, remote_auth cannot be "none".
Jonathon Reinhart 4 年 前
コミット
22ef0c2ee6
3 ファイル変更52 行追加19 行削除
  1. 49 1
      config.go
  2. 1 16
      main.go
  3. 2 2
      smtprelay.ini

+ 49 - 1
config.go

@@ -4,6 +4,7 @@ import (
 	"flag"
 	"net"
 	"regexp"
+	"net/smtp"
 
 	"github.com/vharitonsky/iniflags"
 	"github.com/sirupsen/logrus"
@@ -34,7 +35,8 @@ var (
 	remoteHost        = flag.String("remote_host", "", "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")
-	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")
 	versionInfo       = flag.Bool("version", false, "Show version information")
 )
@@ -84,6 +86,51 @@ func setupAllowedPatterns() {
 	}
 }
 
+
+func setupRemoteAuth() {
+	logger := log.WithField("remote_auth", *remoteAuthStr)
+
+	// Remote auth disabled?
+	switch *remoteAuthStr {
+	case "", "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() {
 	iniflags.Parse()
 
@@ -96,4 +143,5 @@ func ConfigLoad() {
 
 	setupAllowedNetworks()
 	setupAllowedPatterns()
+	setupRemoteAuth()
 }

+ 1 - 16
main.go

@@ -4,7 +4,6 @@ import (
 	"crypto/tls"
 	"fmt"
 	"net"
-	"net/smtp"
 	"net/textproto"
 	"os"
 	"strings"
@@ -170,20 +169,6 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
 
 	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)
 
 	var sender string
@@ -196,7 +181,7 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
 
 	err := SendMail(
 		*remoteHost,
-		auth,
+		remoteAuth,
 		sender,
 		env.Recipients,
 		env.Data,

+ 2 - 2
smtprelay.ini

@@ -73,8 +73,8 @@
 ;remote_pass =
 
 ; Authentication method on outgoing SMTP server
-; (plain, login)
-;remote_auth = plain
+; (none, plain, login)
+;remote_auth = none
 
 ; Sender e-mail address on outgoing SMTP server
 ;remote_sender =