package smtp import ( "crypto/tls" "dove/config" "dove/utils/logger" "fmt" "time" gosmtp "github.com/emersion/go-smtp" ) type ServerInstance struct { Server *gosmtp.Server Label string } var activeServers []ServerInstance func Start() { var tlsConfig *tls.Config if config.SMTP.TLSEnabled { tlsConfig = loadTLSConfig() } plainAddress := fmt.Sprintf("%s:%d", config.BindAddress, config.SmtpPort) plainServer := createServer(plainAddress) activeServers = append(activeServers, ServerInstance{Server: plainServer, Label: "SMTP"}) go startListener(plainServer, "SMTP", plainAddress) smtpsAddress := fmt.Sprintf("%s:%d", config.BindAddress, config.SmtpsPort) smtpsServer := createServer(smtpsAddress) activeServers = append(activeServers, ServerInstance{Server: smtpsServer, Label: "SMTPS"}) if tlsConfig != nil { smtpsServer.TLSConfig = tlsConfig go startTLSListener(smtpsServer, "SMTPS", smtpsAddress) } else { go startListener(smtpsServer, "SMTPS", smtpsAddress) } submissionAddress := fmt.Sprintf("%s:%d", config.BindAddress, config.SubmissionPort) submissionServer := createServer(submissionAddress) submissionServer.EnableSMTPUTF8 = true activeServers = append(activeServers, ServerInstance{Server: submissionServer, Label: "Submission"}) if tlsConfig != nil { submissionServer.TLSConfig = tlsConfig } go startListener(submissionServer, "Submission", submissionAddress) } func Shutdown() { for _, instance := range activeServers { if shutdownError := instance.Server.Close(); shutdownError != nil { logger.Errorf(LogPrefix, ShutdownFailed, instance.Label, shutdownError) } } logger.Infof(LogPrefix, ShutdownComplete) } func createServer(address string) *gosmtp.Server { smtpServer := gosmtp.NewServer(gosmtp.BackendFunc(func(connection *gosmtp.Conn) (gosmtp.Session, error) { logger.Debugf(LogPrefix, SessionStarted, connection.Hostname()) return &Session{}, nil })) smtpServer.Addr = address smtpServer.Domain = config.SMTP.Domain smtpServer.ReadTimeout = time.Duration(config.SMTP.ReadTimeout) * time.Second smtpServer.WriteTimeout = time.Duration(config.SMTP.WriteTimeout) * time.Second smtpServer.MaxMessageBytes = int64(config.SMTP.MaxMessageSize) smtpServer.AllowInsecureAuth = true return smtpServer } func loadTLSConfig() *tls.Config { certificate, loadError := tls.LoadX509KeyPair(config.SMTP.TLSCertPath, config.SMTP.TLSKeyPath) if loadError != nil { logger.Errorf(LogPrefix, TLSCertLoadFailed, loadError) return nil } return &tls.Config{ Certificates: []tls.Certificate{certificate}, } } func startListener(smtpServer *gosmtp.Server, label string, address string) { logger.Successf(LogPrefix, ServerStarting, label, address) if listenError := smtpServer.ListenAndServe(); listenError != nil { logger.Fatalf(LogPrefix, ListenFailed, label, listenError) } } func startTLSListener(smtpServer *gosmtp.Server, label string, address string) { logger.Successf(LogPrefix, ServerStarting, label, address) if listenError := smtpServer.ListenAndServeTLS(); listenError != nil { logger.Fatalf(LogPrefix, ListenFailed, label, listenError) } }