105 lines
3.0 KiB
Go
105 lines
3.0 KiB
Go
// Package smtp provides SMTP inbound (port 25) and submission (587/465) servers
|
|
// using github.com/emersion/go-smtp as the protocol layer.
|
|
package smtp
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
gosmtp "github.com/emersion/go-smtp"
|
|
|
|
"ghb.freebede.com/nahakubuilder/mailgosend/internal/auth"
|
|
"ghb.freebede.com/nahakubuilder/mailgosend/internal/config"
|
|
"ghb.freebede.com/nahakubuilder/mailgosend/internal/crypto"
|
|
"ghb.freebede.com/nahakubuilder/mailgosend/internal/db"
|
|
"ghb.freebede.com/nahakubuilder/mailgosend/internal/spam"
|
|
"ghb.freebede.com/nahakubuilder/mailgosend/internal/storage"
|
|
)
|
|
|
|
// Deps groups all dependencies shared by SMTP servers.
|
|
type Deps struct {
|
|
DB *db.DB
|
|
Crypt *crypto.Crypto
|
|
Store *storage.Store
|
|
Scorer *spam.Scorer
|
|
Brute *auth.BruteGuard
|
|
Cfg *config.Config
|
|
}
|
|
|
|
// NewInboundServer creates the SMTP server for port 25 (inbound MTA).
|
|
// Accepts mail for local domains from any sender. STARTTLS offered but not required.
|
|
func NewInboundServer(d *Deps, tlsCfg *tls.Config) *gosmtp.Server {
|
|
be := &InboundBackend{deps: d}
|
|
|
|
s := gosmtp.NewServer(be)
|
|
s.Addr = fmt.Sprintf("%s:%d", d.Cfg.SMTPIface, d.Cfg.SMTPPort)
|
|
s.Domain = d.Cfg.SMTPHostname
|
|
s.MaxMessageBytes = d.Cfg.MaxMessageSize
|
|
s.MaxRecipients = d.Cfg.MaxRcptPer
|
|
s.WriteTimeout = 5 * time.Minute
|
|
s.ReadTimeout = 5 * time.Minute
|
|
s.AllowInsecureAuth = false // AUTH not offered on port 25
|
|
|
|
if tlsCfg != nil {
|
|
// Setting TLSConfig enables STARTTLS automatically in go-smtp v0.24+.
|
|
s.TLSConfig = tlsCfg
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// NewSubmissionServer creates the SMTP server for port 587 (STARTTLS submission).
|
|
// Auth required. STARTTLS mandatory before AUTH.
|
|
func NewSubmissionServer(d *Deps, tlsCfg *tls.Config) *gosmtp.Server {
|
|
be := &SubmissionBackend{deps: d}
|
|
|
|
s := gosmtp.NewServer(be)
|
|
s.Addr = fmt.Sprintf("%s:%d", d.Cfg.SubmitIface, d.Cfg.SubmitPort)
|
|
s.Domain = d.Cfg.SMTPHostname
|
|
s.MaxMessageBytes = d.Cfg.MaxMessageSize
|
|
s.MaxRecipients = d.Cfg.MaxRcptPer
|
|
s.WriteTimeout = 5 * time.Minute
|
|
s.ReadTimeout = 5 * time.Minute
|
|
s.AllowInsecureAuth = false // auth only after STARTTLS
|
|
|
|
if tlsCfg != nil {
|
|
s.TLSConfig = tlsCfg
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// NewSMTPSServer creates the SMTP server for port 465 (implicit TLS submission).
|
|
func NewSMTPSServer(d *Deps, tlsCfg *tls.Config) *gosmtp.Server {
|
|
be := &SubmissionBackend{deps: d}
|
|
|
|
s := gosmtp.NewServer(be)
|
|
s.Addr = fmt.Sprintf("%s:%d", d.Cfg.SMTPIface, d.Cfg.SMTPSPort)
|
|
s.Domain = d.Cfg.SMTPHostname
|
|
s.MaxMessageBytes = d.Cfg.MaxMessageSize
|
|
s.MaxRecipients = d.Cfg.MaxRcptPer
|
|
s.WriteTimeout = 5 * time.Minute
|
|
s.ReadTimeout = 5 * time.Minute
|
|
s.AllowInsecureAuth = false
|
|
|
|
if tlsCfg != nil {
|
|
s.TLSConfig = tlsCfg
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// ListenAndServe starts a server and logs errors.
|
|
func ListenAndServe(s *gosmtp.Server, name string) error {
|
|
log.Printf("[%s] listening on %s", name, s.Addr)
|
|
return s.ListenAndServe()
|
|
}
|
|
|
|
// ListenAndServeTLS starts a server with implicit TLS (port 465).
|
|
func ListenAndServeTLS(s *gosmtp.Server, name string) error {
|
|
log.Printf("[%s] listening on %s (TLS)", name, s.Addr)
|
|
return s.ListenAndServeTLS()
|
|
}
|