Commit 13ee3ba4 authored by Alberto Bertogli's avatar Alberto Bertogli

courier: Use the hostname in SMTP HELO

The SMTP courier, which handles outgoing connections, uses the domain of
the envelope's from as the domain in the HELO/EHLO greeting.

This works fine in practice, but ideally the domain used in the greeting
should match the reverse DNS record. This used to be more relevant but
nowadays it is not really enforced; however, it sometimes comes up in
self checks, and might cause some confusion when troubleshooting.

So this patch makes it use the configured hostname instead, which is
under the users' control and more likely to be compliant. It also
simplifies the code.

The documentation of the hostname configuration option is also updated
to mention this behaviour.

Thanks to Jonas Seydel (thor77) for bringing this up.
parent 7b0703ea
Pipeline #145739643 passed with stages
in 8 minutes and 31 seconds
......@@ -160,7 +160,11 @@ func main() {
Args: conf.MailDeliveryAgentArgs,
Timeout: 30 * time.Second,
}
remoteC := &courier.SMTP{Dinfo: dinfo, STSCache: stsCache}
remoteC := &courier.SMTP{
HelloDomain: conf.Hostname,
Dinfo: dinfo,
STSCache: stsCache,
}
s.InitQueue(conf.DataDir+"/queue", localC, remoteC)
// Load the addresses and listeners.
......
.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35)
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
......@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "chasquid.conf 5"
.TH chasquid.conf 5 "2019-07-15" "" ""
.TH chasquid.conf 5 "2020-05-13" "" ""
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......@@ -157,7 +157,9 @@ Some values might be repeated, for example the listening addresses.
.IP "\fBhostname\fR (string):" 8
.IX Item "hostname (string):"
Default hostname to use when saying hello. This is used to say hello to
clients, for aesthetic purposes. Default: the system's hostname.
clients (for aesthetic purposes), and as the \s-1HELO/EHLO\s0 domain on outgoing \s-1SMTP\s0
connections (so ideally it would resolve back to the server, but it isn't a
big deal if it doesn't). Default: the system's hostname.
.IP "\fBmax_data_size_mb\fR (int):" 8
.IX Item "max_data_size_mb (int):"
Maximum email size, in megabytes. Default: 50.
......
......@@ -25,7 +25,9 @@ Some values might be repeated, for example the listening addresses.
=item B<hostname> (string):
Default hostname to use when saying hello. This is used to say hello to
clients, for aesthetic purposes. Default: the system's hostname.
clients (for aesthetic purposes), and as the HELO/EHLO domain on outgoing SMTP
connections (so ideally it would resolve back to the server, but it isn't a
big deal if it doesn't). Default: the system's hostname.
=item B<max_data_size_mb> (int):
......
# Default hostname to use when saying hello.
# This is used to say hello to clients, for aesthetic purposes.
# This is used to say hello to clients (for aesthetic purposes), and as the
# HELO/EHLO domain on outgoing SMTP connections (so ideally it would resolve
# back to the server, but it isn't a big deal if it doesn't).
# Default: the system's hostname.
#hostname: "mx.example.com"
......
......@@ -22,7 +22,11 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Config struct {
// Default hostname to use when saying hello.
// This is used to say hello to clients, for aesthetic purposes.
// This is used:
// 1) To say hello to clients, for aesthetic purposes.
// 2) As the HELO/EHLO domain on outgoing SMTP connections, so ideally
// it would resolve back to the server. In practice, it's not a big
// deal if it isn't, but it makes troubleshooting easier.
// Default: the system's hostname.
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
// Maximum email size, in megabytes.
......
......@@ -3,7 +3,11 @@ syntax = "proto3";
message Config {
// Default hostname to use when saying hello.
// This is used to say hello to clients, for aesthetic purposes.
// This is used:
// 1) To say hello to clients, for aesthetic purposes.
// 2) As the HELO/EHLO domain on outgoing SMTP connections, so ideally
// it would resolve back to the server. In practice, it's not a big
// deal if it isn't, but it makes troubleshooting easier.
// Default: the system's hostname.
string hostname = 1;
......
......@@ -6,7 +6,6 @@ import (
"expvar"
"flag"
"net"
"os"
"time"
"golang.org/x/net/idna"
......@@ -45,8 +44,9 @@ var (
// SMTP delivers remote mail via outgoing SMTP.
type SMTP struct {
Dinfo *domaininfo.DB
STSCache *sts.PolicyCache
HelloDomain string
Dinfo *domaininfo.DB
STSCache *sts.PolicyCache
}
// Deliver an email. On failures, returns an error, and whether or not it is
......@@ -77,17 +77,6 @@ func (s *SMTP) Deliver(from string, to string, data []byte) (error, bool) {
return a.tr.Errorf("Could not find mail server: %v", err), perm
}
// Issue an EHLO with a valid domain; otherwise, some servers like postfix
// will complain.
a.helloDomain, err = idna.ToASCII(envelope.DomainOf(from))
if err != nil {
return a.tr.Errorf("Sender domain not IDNA compliant: %v", err), true
}
if a.helloDomain == "" {
// This can happen when sending bounces. Last resort.
a.helloDomain, _ = os.Hostname()
}
a.stsPolicy = s.fetchSTSPolicy(a.tr, a.toDomain)
for _, mx := range mxs {
......@@ -118,8 +107,7 @@ type attempt struct {
to string
data []byte
toDomain string
helloDomain string
toDomain string
stsPolicy *sts.Policy
......@@ -145,7 +133,7 @@ retry:
return a.tr.Errorf("Error creating client: %v", err), false
}
if err = c.Hello(a.helloDomain); err != nil {
if err = c.Hello(a.courier.HelloDomain); err != nil {
return a.tr.Errorf("Error saying hello: %v", err), false
}
......
......@@ -36,7 +36,7 @@ func newSMTP(t *testing.T) (*SMTP, string) {
t.Fatal(err)
}
return &SMTP{dinfo, nil}, dir
return &SMTP{"hello", dinfo, nil}, dir
}
// Fake server, to test SMTP out.
......@@ -94,7 +94,7 @@ func TestSMTP(t *testing.T) {
responses := map[string]string{
"_welcome": "220 welcome\n",
"EHLO me": "250 ehlo ok\n",
"EHLO hello": "250 ehlo ok\n",
"MAIL FROM:<[email protected]>": "250 mail ok\n",
"RCPT TO:<[email protected]>": "250 rcpt ok\n",
"DATA": "354 send data\n",
......@@ -140,14 +140,14 @@ func TestSMTPErrors(t *testing.T) {
// MAIL FROM not allowed.
{
"_welcome": "220 mail from not allowed\n",
"EHLO me": "250 ehlo ok\n",
"EHLO hello": "250 ehlo ok\n",
"MAIL FROM:<[email protected]>": "501 mail error\n",
},
// RCPT TO not allowed.
{
"_welcome": "220 rcpt to not allowed\n",
"EHLO me": "250 ehlo ok\n",
"EHLO hello": "250 ehlo ok\n",
"MAIL FROM:<[email protected]>": "250 mail ok\n",
"RCPT TO:<[email protected]>": "501 rcpt error\n",
},
......@@ -155,7 +155,7 @@ func TestSMTPErrors(t *testing.T) {
// DATA error.
{
"_welcome": "220 data error\n",
"EHLO me": "250 ehlo ok\n",
"EHLO hello": "250 ehlo ok\n",
"MAIL FROM:<[email protected]>": "250 mail ok\n",
"RCPT TO:<[email protected]>": "250 rcpt ok\n",
"DATA": "554 data error\n",
......@@ -164,7 +164,7 @@ func TestSMTPErrors(t *testing.T) {
// DATA response error.
{
"_welcome": "220 data response error\n",
"EHLO me": "250 ehlo ok\n",
"EHLO hello": "250 ehlo ok\n",
"MAIL FROM:<[email protected]>": "250 mail ok\n",
"RCPT TO:<[email protected]>": "250 rcpt ok\n",
"DATA": "354 send data\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment