From 4dff7adc1d8a42ef57f43993919c00a90d9a922f Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Fri, 30 May 2025 11:03:30 +1200 Subject: [PATCH] Reorder send API CLI flags --- cmd/root.go | 22 +++++++++------ config/config.go | 65 ++++++++++++++++++++++++------------------- internal/auth/auth.go | 42 ++++++++++++++-------------- 3 files changed, 70 insertions(+), 59 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 06ccbcd..b5b5dc6 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -108,12 +108,14 @@ func init() { rootCmd.Flags().BoolVar(&config.DisableHTTPCompression, "disable-http-compression", config.DisableHTTPCompression, "Disable HTTP compression support (web UI & API)") rootCmd.Flags().BoolVar(&config.HideDeleteAllButton, "hide-delete-all-button", config.HideDeleteAllButton, "Hide the \"Delete all\" button in the web UI") + // Send API + rootCmd.Flags().StringVar(&config.SendAPIAuthFile, "send-api-auth-file", config.SendAPIAuthFile, "A password file for Send API authentication") + rootCmd.Flags().BoolVar(&config.SendAPIAuthAcceptAny, "send-api-auth-accept-any", config.SendAPIAuthAcceptAny, "Accept any username and password for the Send API endpoint, including none") + // SMTP server rootCmd.Flags().StringVarP(&config.SMTPListen, "smtp", "s", config.SMTPListen, "SMTP bind interface and port") rootCmd.Flags().StringVar(&config.SMTPAuthFile, "smtp-auth-file", config.SMTPAuthFile, "A password file for SMTP authentication") rootCmd.Flags().BoolVar(&config.SMTPAuthAcceptAny, "smtp-auth-accept-any", config.SMTPAuthAcceptAny, "Accept any SMTP username and password, including none") - rootCmd.Flags().StringVar(&config.SendAPIAuthFile, "send-api-auth-file", config.SendAPIAuthFile, "A password file for Send API authentication") - rootCmd.Flags().BoolVar(&config.SendAPIAuthAcceptAny, "send-api-auth-accept-any", config.SendAPIAuthAcceptAny, "Accept any username and password for the Send API endpoint, including none") rootCmd.Flags().StringVar(&config.SMTPTLSCert, "smtp-tls-cert", config.SMTPTLSCert, "TLS certificate for SMTP (STARTTLS) - requires smtp-tls-key") rootCmd.Flags().StringVar(&config.SMTPTLSKey, "smtp-tls-key", config.SMTPTLSKey, "TLS key for SMTP (STARTTLS) - requires smtp-tls-cert") rootCmd.Flags().BoolVar(&config.SMTPRequireSTARTTLS, "smtp-require-starttls", config.SMTPRequireSTARTTLS, "Require SMTP client use STARTTLS") @@ -251,6 +253,15 @@ func initConfigFromEnv() { config.HideDeleteAllButton = true } + // Send API + config.SendAPIAuthFile = os.Getenv("MP_SEND_API_AUTH_FILE") + if err := auth.SetSendAPIAuth(os.Getenv("MP_SEND_API_AUTH")); err != nil { + logger.Log().Error(err.Error()) + } + if getEnabledFromEnv("MP_SEND_API_AUTH_ACCEPT_ANY") { + config.SendAPIAuthAcceptAny = true + } + // SMTP server if len(os.Getenv("MP_SMTP_BIND_ADDR")) > 0 { config.SMTPListen = os.Getenv("MP_SMTP_BIND_ADDR") @@ -262,13 +273,6 @@ func initConfigFromEnv() { if getEnabledFromEnv("MP_SMTP_AUTH_ACCEPT_ANY") { config.SMTPAuthAcceptAny = true } - config.SendAPIAuthFile = os.Getenv("MP_SEND_API_AUTH_FILE") - if err := auth.SetSendAPIAuth(os.Getenv("MP_SEND_API_AUTH")); err != nil { - logger.Log().Error(err.Error()) - } - if getEnabledFromEnv("MP_SEND_API_AUTH_ACCEPT_ANY") { - config.SendAPIAuthAcceptAny = true - } config.SMTPTLSCert = os.Getenv("MP_SMTP_TLS_CERT") config.SMTPTLSKey = os.Getenv("MP_SMTP_TLS_KEY") if getEnabledFromEnv("MP_SMTP_REQUIRE_STARTTLS") { diff --git a/config/config.go b/config/config.go index 58b9897..dfd85ad 100644 --- a/config/config.go +++ b/config/config.go @@ -72,6 +72,12 @@ var ( // DisableHTTPCompression will explicitly disable HTTP compression in the web UI and API DisableHTTPCompression bool + // SendAPIAuthFile for Send API authentication + SendAPIAuthFile string + + // SendAPIAuthAcceptAny accepts any username/password for the send API endpoint, including none + SendAPIAuthAcceptAny bool + // SMTPTLSCert file SMTPTLSCert string @@ -96,12 +102,6 @@ var ( // SMTPAuthAcceptAny accepts any username/password including none SMTPAuthAcceptAny bool - // SendAPIAuthFile for Send API authentication - SendAPIAuthFile string - - // SendAPIAuthAcceptAny accepts any username/password for the send API endpoint, including none - SendAPIAuthAcceptAny bool - // SMTPMaxRecipients is the maximum number of recipients a message may have. // The SMTP RFC states that an server must handle a minimum of 100 recipients // however some servers accept more. @@ -295,6 +295,7 @@ func VerifyConfig() error { return errors.New("[ui] HTTP bind should be in the format of :") } + // Web UI & API if UIAuthFile != "" { UIAuthFile = filepath.Clean(UIAuthFile) @@ -329,6 +330,35 @@ func VerifyConfig() error { } } + // Send API + if SendAPIAuthFile != "" { + SendAPIAuthFile = filepath.Clean(SendAPIAuthFile) + + if !isFile(SendAPIAuthFile) { + return fmt.Errorf("[send-api] password file not found or readable: %s", SendAPIAuthFile) + } + + b, err := os.ReadFile(SendAPIAuthFile) + if err != nil { + return err + } + + if err := auth.SetSendAPIAuth(string(b)); err != nil { + return err + } + + logger.Log().Info("[send-api] enabling basic authentication") + } + + if auth.SendAPICredentials != nil && SendAPIAuthAcceptAny { + return errors.New("[send-api] authentication cannot use both credentials and --send-api-auth-accept-any") + } + + if SendAPIAuthAcceptAny && auth.UICredentials != nil { + logger.Log().Info("[send-api] disabling authentication") + } + + // SMTP server if SMTPTLSCert != "" && SMTPTLSKey == "" || SMTPTLSCert == "" && SMTPTLSKey != "" { return errors.New("[smtp] you must provide both an SMTP TLS certificate and a key") } @@ -389,29 +419,6 @@ func VerifyConfig() error { return errors.New("[smtp] authentication cannot use both credentials and --smtp-auth-accept-any") } - if SendAPIAuthFile != "" { - SendAPIAuthFile = filepath.Clean(SendAPIAuthFile) - - if !isFile(SendAPIAuthFile) { - return fmt.Errorf("[send-api] password file not found or readable: %s", SendAPIAuthFile) - } - - b, err := os.ReadFile(SendAPIAuthFile) - if err != nil { - return err - } - - if err := auth.SetSendAPIAuth(string(b)); err != nil { - return err - } - - logger.Log().Info("[send-api] enabling basic authentication") - } - - if auth.SendAPICredentials != nil && SendAPIAuthAcceptAny { - return errors.New("[send-api] authentication cannot use both credentials and --send-api-auth-accept-any") - } - if SMTPTLSCert == "" && (auth.SMTPCredentials != nil || SMTPAuthAcceptAny) && !SMTPAuthAllowInsecure { return errors.New("[smtp] authentication requires STARTTLS or TLS encryption, run with `--smtp-auth-allow-insecure` to allow insecure authentication") } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index a68e6a0..184b632 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -11,12 +11,12 @@ import ( var ( // UICredentials passwords UICredentials *htpasswd.File + // SendAPICredentials passwords + SendAPICredentials *htpasswd.File // SMTPCredentials passwords SMTPCredentials *htpasswd.File // POP3Credentials passwords POP3Credentials *htpasswd.File - // SendAPICredentials passwords - SendAPICredentials *htpasswd.File ) // SetUIAuth will set Basic Auth credentials required for the UI & API @@ -38,6 +38,25 @@ func SetUIAuth(s string) error { return nil } +// SetSendAPIAuth will set Send API credentials +func SetSendAPIAuth(s string) error { + var err error + + credentials := credentialsFromString(s) + if len(credentials) == 0 { + return nil + } + + r := strings.NewReader(strings.Join(credentials, "\n")) + + SendAPICredentials, err = htpasswd.NewFromReader(r, htpasswd.DefaultSystems, nil) + if err != nil { + return err + } + + return nil +} + // SetSMTPAuth will set SMTP credentials func SetSMTPAuth(s string) error { var err error @@ -76,25 +95,6 @@ func SetPOP3Auth(s string) error { return nil } -// SetSendAPIAuth will set Send API credentials -func SetSendAPIAuth(s string) error { - var err error - - credentials := credentialsFromString(s) - if len(credentials) == 0 { - return nil - } - - r := strings.NewReader(strings.Join(credentials, "\n")) - - SendAPICredentials, err = htpasswd.NewFromReader(r, htpasswd.DefaultSystems, nil) - if err != nil { - return err - } - - return nil -} - func credentialsFromString(s string) []string { // split string by any whitespace character re := regexp.MustCompile(`\s+`)