aboutsummaryrefslogtreecommitdiff
path: root/utils/smtp/server.go
blob: 5260d2004c8d039da9f25f67a32e4d1c30c71dae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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() {
	plainAddress := fmt.Sprintf("%s:%d", config.SMTP.Host, config.SMTP.Port)
	plainServer := createServer(plainAddress)
	activeServers = append(activeServers, ServerInstance{Server: plainServer, Label: "SMTP"})
	go startListener(plainServer, "SMTP", plainAddress)

	if config.SMTP.TLSEnabled {
		tlsConfig := loadTLSConfig()
		if tlsConfig != nil {
			smtpsAddress := fmt.Sprintf("%s:%d", config.SMTP.Host, config.SMTP.SMTPSPort)
			smtpsServer := createServer(smtpsAddress)
			smtpsServer.TLSConfig = tlsConfig
			activeServers = append(activeServers, ServerInstance{Server: smtpsServer, Label: "SMTPS"})
			go startTLSListener(smtpsServer, "SMTPS", smtpsAddress)

			starttlsAddress := fmt.Sprintf("%s:%d", config.SMTP.Host, config.SMTP.StartTLSPort)
			starttlsServer := createServer(starttlsAddress)
			starttlsServer.TLSConfig = tlsConfig
			starttlsServer.EnableSMTPUTF8 = true
			activeServers = append(activeServers, ServerInstance{Server: starttlsServer, Label: "STARTTLS"})
			go startListener(starttlsServer, "STARTTLS", starttlsAddress)
		}
	}
}

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)
	}
}