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
17 func RelayMessage(server Server, env Envelope, log *zap.Logger) {
18 for _, rcptTo := range env.RcptTo {
19 sendLog := log.With(zap.String("address", rcptTo.Address))
21 domain := DomainForAddress(rcptTo)
22 mx, err := net.LookupMX(domain)
23 if err != nil || len(mx) < 1 {
24 sendLog.Error("failed to lookup MX records",
26 deliverRelayFailure(env, err)
29 host := mx[0].Host + ":25"
30 relayMessageToHost(server, env, sendLog, rcptTo.Address, host)
34 func relayMessageToHost(server Server, env Envelope, log *zap.Logger, to, host string) {
35 from := env.MailFrom.Address
37 c, err := smtp.Dial(host)
39 // TODO - retry, or look at other MX records
40 log.Error("failed to dial host",
41 zap.String("host", host),
43 deliverRelayFailure(env, err)
48 log = log.With(zap.String("host", host))
50 if err = c.Hello(server.Name()); err != nil {
51 log.Error("failed to HELO", zap.Error(err))
52 deliverRelayFailure(env, err)
56 if hasTls, _ := c.Extension("STARTTLS"); hasTls {
57 config := &tls.Config{ServerName: host}
58 if err = c.StartTLS(config); err != nil {
59 log.Error("failed to STARTTLS", zap.Error(err))
60 deliverRelayFailure(env, err)
65 if err = c.Mail(from); err != nil {
66 log.Error("failed MAIL FROM", zap.Error(err))
67 deliverRelayFailure(env, err)
71 if err = c.Rcpt(to); err != nil {
72 log.Error("failed to RCPT TO", zap.Error(err))
73 deliverRelayFailure(env, err)
79 log.Error("failed to DATA", zap.Error(err))
80 deliverRelayFailure(env, err)
84 _, err = wc.Write(env.Data)
87 log.Error("failed to write DATA", zap.Error(err))
88 deliverRelayFailure(env, err)
92 if err = wc.Close(); err != nil {
93 log.Error("failed to close DATA", zap.Error(err))
94 deliverRelayFailure(env, err)
99 func deliverRelayFailure(env Envelope, err error) {
100 // TODO: constructo a delivery status notification