]>
src.bluestatic.org Git - mailpopbox.git/blob - smtp.go
2 // Copyright 2020 Blue Static <https://www.bluestatic.org>
3 // This program is free software licensed under the GNU General Public License,
4 // version 3.0. The full text of the license can be found in LICENSE.txt.
5 // SPDX-License-Identifier: GPL-3.0-only
19 "src.bluestatic.org/mailpopbox/smtp"
22 func runSMTPServer(config Config
, log
*zap
.Logger
) <-chan ServerControlMessage
{
25 controlChan
: make(chan ServerControlMessage
),
26 log
: log
.With(zap
.String("server", "smtp")),
29 return server
.controlChan
32 type smtpServer
struct {
38 controlChan
chan ServerControlMessage
41 func (server
*smtpServer
) run() {
42 if !server
.loadTLSConfig() {
46 addr
:= fmt
.Sprintf(":%d", server
.config
.SMTPPort
)
47 server
.log
.Info("starting server", zap
.String("address", addr
))
49 l
, err
:= net
.Listen("tcp", addr
)
51 server
.log
.Error("listen", zap
.Error(err
))
52 server
.controlChan
<- ServerControlFatalError
56 connChan
:= make(chan net
.Conn
)
57 go RunAcceptLoop(l
, connChan
, server
.log
)
59 reloadChan
:= CreateReloadSignal()
64 if !server
.loadTLSConfig() {
67 case conn
, ok
:= <-connChan
:
69 go smtp
.AcceptConnection(conn
, server
, server
.log
)
77 func (server
*smtpServer
) loadTLSConfig() bool {
79 server
.tlsConfig
, err
= server
.config
.GetTLSConfig()
81 server
.log
.Error("failed to configure TLS", zap
.Error(err
))
82 server
.controlChan
<- ServerControlFatalError
85 server
.log
.Info("loaded TLS config")
89 func (server
*smtpServer
) Name() string {
90 return server
.config
.Hostname
93 func (server
*smtpServer
) TLSConfig() *tls
.Config
{
94 return server
.tlsConfig
97 func (server
*smtpServer
) VerifyAddress(addr mail
.Address
) smtp
.ReplyLine
{
98 if server
.maildropForAddress(addr
) == "" {
99 return smtp
.ReplyBadMailbox
104 func (server
*smtpServer
) Authenticate(authz
, authc
, passwd
string) bool {
105 authcAddr
, err
:= mail
.ParseAddress(authc
)
110 authzAddr
, err
:= mail
.ParseAddress(authz
)
111 if authz
!= "" && err
!= nil {
115 domain
:= smtp
.DomainForAddress(*authcAddr
)
116 for _
, s
:= range server
.config
.Servers
{
117 if domain
== s
.Domain
{
118 authOk
:= authc
== MailboxAccount
+s
.Domain
&& passwd
== s
.MailboxPassword
119 if authzAddr
!= nil {
120 authOk
= authOk
&& smtp
.DomainForAddress(*authzAddr
) == domain
128 func (server
*smtpServer
) DeliverMessage(en smtp
.Envelope
) *smtp
.ReplyLine
{
129 maildrop
:= server
.maildropForAddress(en
.RcptTo
[0])
131 server
.log
.Error("faild to open maildrop to deliver message", zap
.String("id", en
.ID
))
132 return &smtp
.ReplyBadMailbox
135 f
, err
:= os
.Create(path
.Join(maildrop
, en
.ID
+".msg"))
137 server
.log
.Error("failed to create message file", zap
.String("id", en
.ID
), zap
.Error(err
))
138 return &smtp
.ReplyBadMailbox
141 smtp
.WriteEnvelopeForDelivery(f
, en
)
146 func (server
*smtpServer
) RelayMessage(en smtp
.Envelope
) {
147 log
:= server
.log
.With(zap
.String("id", en
.ID
))
148 go smtp
.RelayMessage(server
, en
, log
)
151 func (server
*smtpServer
) maildropForAddress(addr mail
.Address
) string {
152 domain
:= smtp
.DomainForAddress(addr
)
153 for _
, s
:= range server
.config
.Servers
{
154 if domain
== s
.Domain
{
155 return s
.MaildropPath