diff --git a/doc.go b/doc.go index 5e1a66e..dd77620 100644 --- a/doc.go +++ b/doc.go @@ -20,7 +20,7 @@ any parameters. Followed by the help and usage information for each command. mox [-config config/mox.conf] [-pedantic] ... mox serve - mox quickstart [-existing-webserver] [-hostname host] user@domain [user | uid] + mox quickstart [-skipdial] [-existing-webserver] [-hostname host] user@domain [user | uid] mox stop mox setaccountpassword account mox setadminpassword @@ -146,11 +146,13 @@ traffic to your existing backend applications. Look for "WebHandlers:" in the output of "mox config describe-domains" and see the output of "mox example webhandlers". - usage: mox quickstart [-existing-webserver] [-hostname host] user@domain [user | uid] + usage: mox quickstart [-skipdial] [-existing-webserver] [-hostname host] user@domain [user | uid] -existing-webserver use if a webserver is already running, so mox won't listen on port 80 and 443; you'll have to provide tls certificates/keys, and configure the existing webserver as reverse proxy, forwarding requests to mox. -hostname string hostname mox will run on, by default the hostname of the machine quickstart runs on; if specified, the IPs for the hostname are configured for the public listener + -skipdial + skip check for outgoing smtp (port 25) connectivity # mox stop diff --git a/quickstart.go b/quickstart.go index b2bdddd..c519a24 100644 --- a/quickstart.go +++ b/quickstart.go @@ -59,7 +59,7 @@ func pwgen() string { } func cmdQuickstart(c *cmd) { - c.params = "[-existing-webserver] [-hostname host] user@domain [user | uid]" + c.params = "[-skipdial] [-existing-webserver] [-hostname host] user@domain [user | uid]" c.help = `Quickstart generates configuration files and prints instructions to quickly set up a mox instance. Quickstart writes configuration files, prints initial admin and account @@ -95,8 +95,10 @@ webhandlers". ` var existingWebserver bool var hostname string + var skipDial bool c.flag.BoolVar(&existingWebserver, "existing-webserver", false, "use if a webserver is already running, so mox won't listen on port 80 and 443; you'll have to provide tls certificates/keys, and configure the existing webserver as reverse proxy, forwarding requests to mox.") c.flag.StringVar(&hostname, "hostname", "", "hostname mox will run on, by default the hostname of the machine quickstart runs on; if specified, the IPs for the hostname are configured for the public listener") + c.flag.BoolVar(&skipDial, "skipdial", false, "skip check for outgoing smtp (port 25) connectivity") args := c.Parse() if len(args) != 1 && len(args) != 2 { c.Usage() @@ -529,6 +531,44 @@ messages over SMTP. } } + // Check outgoing SMTP connectivity. + if !skipDial { + fmt.Printf("Checking if outgoing smtp connections can be made by connecting to gmail.com mx on port 25...") + mxctx, mxcancel := context.WithTimeout(context.Background(), 5*time.Second) + mx, _, err := resolver.LookupMX(mxctx, "gmail.com.") + mxcancel() + if err == nil && len(mx) == 0 { + err = errors.New("no mx records") + } + var ok bool + if err != nil { + fmt.Printf("\n\nERROR: looking up gmail.com mx record: %s\n", err) + } else { + dialctx, dialcancel := context.WithTimeout(context.Background(), 10*time.Second) + d := net.Dialer{} + addr := net.JoinHostPort(mx[0].Host, "25") + conn, err := d.DialContext(dialctx, "tcp", addr) + dialcancel() + if err != nil { + fmt.Printf("\n\nERROR: connecting to %s: %s\n", addr, err) + } else { + conn.Close() + fmt.Printf(" OK\n") + ok = true + } + } + if !ok { + fmt.Printf(` +WARNING: Could not verify outgoing smtp connections can be made, outgoing +delivery may not be working. Many providers block outgoing smtp connections by +default, requiring an explicit request or a cooldown period before allowing +outgoing smtp connections. To send through a smarthost, configure a "Transport" +in mox.conf and use it in "Routes" in domains.conf. See "mox example transport". + +`) + } + } + zones := []dns.Domain{ {ASCII: "sbl.spamhaus.org"}, {ASCII: "bl.spamcop.net"}, @@ -538,7 +578,7 @@ messages over SMTP. var listed bool for _, zone := range zones { for _, ip := range hostIPs { - dnsblctx, dnsblcancel := context.WithTimeout(resolveCtx, 5*time.Second) + dnsblctx, dnsblcancel := context.WithTimeout(context.Background(), 5*time.Second) status, expl, err := dnsbl.Lookup(dnsblctx, c.log.Logger, resolver, zone, net.ParseIP(ip)) dnsblcancel() if status == dnsbl.StatusPass { diff --git a/testdata/integration/moxacmepebble.sh b/testdata/integration/moxacmepebble.sh index 9c564f0..e268f73 100755 --- a/testdata/integration/moxacmepebble.sh +++ b/testdata/integration/moxacmepebble.sh @@ -7,7 +7,7 @@ apk add unbound curl (rm -r /tmp/mox 2>/dev/null || exit 0) # clean slate mkdir /tmp/mox cd /tmp/mox -mox quickstart moxtest1@mox1.example "$MOX_UID" > output.txt +mox quickstart -skipdial moxtest1@mox1.example "$MOX_UID" > output.txt cp config/mox.conf config/mox.conf.orig sed -i -e 's/letsencrypt:/pebble:/g' -e 's/: letsencrypt/: pebble/g' -e 's,DirectoryURL: https://acme-v02.api.letsencrypt.org/directory,DirectoryURL: https://acmepebble.example:14000/dir,' -e 's/SMTP:$/SMTP:\n\t\t\tFirstTimeSenderDelay: 1s/' config/mox.conf diff --git a/testdata/integration/moxmail2.sh b/testdata/integration/moxmail2.sh index f8669e1..609d4a1 100755 --- a/testdata/integration/moxmail2.sh +++ b/testdata/integration/moxmail2.sh @@ -7,7 +7,7 @@ apk add unbound (rm -r /tmp/mox 2>/dev/null || exit 0) # clean slate mkdir /tmp/mox cd /tmp/mox -mox quickstart moxtest2@mox2.example "$MOX_UID" > output.txt +mox quickstart -skipdial moxtest2@mox2.example "$MOX_UID" > output.txt cp config/mox.conf config/mox.conf.orig sed -i -e 's,ACME: .*$,KeyCerts:\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/moxmail2.pem\n\t\t\t\t\tKeyFile: /integration/tls/moxmail2-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/mox2-autoconfig.pem\n\t\t\t\t\tKeyFile: /integration/tls/mox2-autoconfig-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/mox2-mtasts.pem\n\t\t\t\t\tKeyFile: /integration/tls/mox2-mtasts-key.pem\n,' -e 's/SMTP:$/SMTP:\n\t\t\tFirstTimeSenderDelay: 1s/' config/mox.conf