mirror of
https://github.com/axllent/mailpit.git
synced 2025-08-15 20:13:16 +02:00
Feature: Add TLS relay support and refactor relay function (#471)
* Feature: Add TLS relay support and refactoring the relay function * Fix: Prevent simultaneous use of TLS and STARTTLS in relay configuration validation
This commit is contained in:
@@ -292,6 +292,7 @@ func initConfigFromEnv() {
|
|||||||
config.SMTPRelayConfig.Port, _ = strconv.Atoi(os.Getenv("MP_SMTP_RELAY_PORT"))
|
config.SMTPRelayConfig.Port, _ = strconv.Atoi(os.Getenv("MP_SMTP_RELAY_PORT"))
|
||||||
}
|
}
|
||||||
config.SMTPRelayConfig.STARTTLS = getEnabledFromEnv("MP_SMTP_RELAY_STARTTLS")
|
config.SMTPRelayConfig.STARTTLS = getEnabledFromEnv("MP_SMTP_RELAY_STARTTLS")
|
||||||
|
config.SMTPRelayConfig.TLS = getEnabledFromEnv("MP_SMTP_RELAY_TLS")
|
||||||
config.SMTPRelayConfig.AllowInsecure = getEnabledFromEnv("MP_SMTP_RELAY_ALLOW_INSECURE")
|
config.SMTPRelayConfig.AllowInsecure = getEnabledFromEnv("MP_SMTP_RELAY_ALLOW_INSECURE")
|
||||||
config.SMTPRelayConfig.Auth = os.Getenv("MP_SMTP_RELAY_AUTH")
|
config.SMTPRelayConfig.Auth = os.Getenv("MP_SMTP_RELAY_AUTH")
|
||||||
config.SMTPRelayConfig.Username = os.Getenv("MP_SMTP_RELAY_USERNAME")
|
config.SMTPRelayConfig.Username = os.Getenv("MP_SMTP_RELAY_USERNAME")
|
||||||
|
@@ -212,6 +212,7 @@ type SMTPRelayConfigStruct struct {
|
|||||||
Host string `yaml:"host"`
|
Host string `yaml:"host"`
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port"`
|
||||||
STARTTLS bool `yaml:"starttls"`
|
STARTTLS bool `yaml:"starttls"`
|
||||||
|
TLS bool `yaml:"tls"`
|
||||||
AllowInsecure bool `yaml:"allow-insecure"`
|
AllowInsecure bool `yaml:"allow-insecure"`
|
||||||
Auth string `yaml:"auth"` // none, plain, login, cram-md5
|
Auth string `yaml:"auth"` // none, plain, login, cram-md5
|
||||||
Username string `yaml:"username"` // plain & cram-md5
|
Username string `yaml:"username"` // plain & cram-md5
|
||||||
|
@@ -94,6 +94,10 @@ func validateRelayConfig() error {
|
|||||||
SMTPRelayConfig.Port = 25 // default
|
SMTPRelayConfig.Port = 25 // default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if SMTPRelayConfig.STARTTLS && SMTPRelayConfig.TLS {
|
||||||
|
return fmt.Errorf("[relay] TLS & STARTTLS cannot be required together")
|
||||||
|
}
|
||||||
|
|
||||||
SMTPRelayConfig.Auth = strings.ToLower(SMTPRelayConfig.Auth)
|
SMTPRelayConfig.Auth = strings.ToLower(SMTPRelayConfig.Auth)
|
||||||
|
|
||||||
if SMTPRelayConfig.Auth == "" || SMTPRelayConfig.Auth == "none" || SMTPRelayConfig.Auth == "false" {
|
if SMTPRelayConfig.Auth == "" || SMTPRelayConfig.Auth == "none" || SMTPRelayConfig.Auth == "false" {
|
||||||
|
@@ -59,27 +59,55 @@ func autoRelayMessage(from string, to []string, data *[]byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createSMTPClient(config config.SMTPRelayConfigStruct, addr string) (*smtp.Client, error) {
|
||||||
|
if config.TLS {
|
||||||
|
tlsConf := &tls.Config{ServerName: config.Host} // #nosec
|
||||||
|
tlsConf.InsecureSkipVerify = config.AllowInsecure
|
||||||
|
|
||||||
|
conn, err := tls.Dial("tcp", addr, tlsConf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("TLS Dial error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := smtp.NewClient(conn, tlsConf.ServerName)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, fmt.Errorf("SMTP client error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: The caller is responsible for closing the client
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := smtp.Dial(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error connecting to %s: %v", addr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.STARTTLS {
|
||||||
|
tlsConf := &tls.Config{ServerName: config.Host} // #nosec
|
||||||
|
tlsConf.InsecureSkipVerify = config.AllowInsecure
|
||||||
|
|
||||||
|
if err = client.StartTLS(tlsConf); err != nil {
|
||||||
|
client.Close()
|
||||||
|
return nil, fmt.Errorf("error creating StartTLS config: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: The caller is responsible for closing the client
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Relay will connect to a pre-configured SMTP server and send a message to one or more recipients.
|
// Relay will connect to a pre-configured SMTP server and send a message to one or more recipients.
|
||||||
func Relay(from string, to []string, msg []byte) error {
|
func Relay(from string, to []string, msg []byte) error {
|
||||||
addr := fmt.Sprintf("%s:%d", config.SMTPRelayConfig.Host, config.SMTPRelayConfig.Port)
|
addr := fmt.Sprintf("%s:%d", config.SMTPRelayConfig.Host, config.SMTPRelayConfig.Port)
|
||||||
|
|
||||||
c, err := smtp.Dial(addr)
|
c, err := createSMTPClient(config.SMTPRelayConfig, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error connecting to %s: %s", addr, err.Error())
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
if config.SMTPRelayConfig.STARTTLS {
|
|
||||||
conf := &tls.Config{ServerName: config.SMTPRelayConfig.Host} // #nosec
|
|
||||||
|
|
||||||
conf.InsecureSkipVerify = config.SMTPRelayConfig.AllowInsecure
|
|
||||||
|
|
||||||
if err = c.StartTLS(conf); err != nil {
|
|
||||||
return fmt.Errorf("error creating StartTLS config: %s", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auth := relayAuthFromConfig()
|
auth := relayAuthFromConfig()
|
||||||
|
|
||||||
if auth != nil {
|
if auth != nil {
|
||||||
|
Reference in New Issue
Block a user