mirror of
https://github.com/mjl-/mox.git
synced 2024-12-27 08:53:48 +03:00
in quickstart, add -hostname flag and check public ips with 2 dnsbl's
- if the guessed hostname is not correct, you can specify one yourself. useful if you generate a config locally and deploy to a different machine. - if explicit public ips are found, check them with spamhaus and spamcop DNSBLs and warn if they are listed, with links to check more DNSBLs. should prevent disappointment later on.
This commit is contained in:
parent
ce54c6f1db
commit
845a72d07a
5 changed files with 243 additions and 139 deletions
|
@ -88,7 +88,7 @@ type ACME struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
IPs []string `sconf-doc:"Use 0.0.0.0 to listen on all IPv4 and/or :: to listen on all IPv6 addresses."`
|
IPs []string `sconf-doc:"Use 0.0.0.0 to listen on all IPv4 and/or :: to listen on all IPv6 addresses, but it is better to explicitly specify the IPs you want to use for email, as mox will make sure outgoing connections will only be made from one of those IPs."`
|
||||||
Hostname string `sconf:"optional" sconf-doc:"If empty, the config global Hostname is used."`
|
Hostname string `sconf:"optional" sconf-doc:"If empty, the config global Hostname is used."`
|
||||||
HostnameDomain dns.Domain `sconf:"-" json:"-"` // Set when parsing config.
|
HostnameDomain dns.Domain `sconf:"-" json:"-"` // Set when parsing config.
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,9 @@ describe-static" and "mox config describe-domains":
|
||||||
Listeners:
|
Listeners:
|
||||||
x:
|
x:
|
||||||
|
|
||||||
# Use 0.0.0.0 to listen on all IPv4 and/or :: to listen on all IPv6 addresses.
|
# Use 0.0.0.0 to listen on all IPv4 and/or :: to listen on all IPv6 addresses, but
|
||||||
|
# it is better to explicitly specify the IPs you want to use for email, as mox
|
||||||
|
# will make sure outgoing connections will only be made from one of those IPs.
|
||||||
IPs:
|
IPs:
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|
14
doc.go
14
doc.go
|
@ -14,7 +14,7 @@ low-maintenance self-hosted email.
|
||||||
|
|
||||||
mox [-config config/mox.conf] ...
|
mox [-config config/mox.conf] ...
|
||||||
mox serve
|
mox serve
|
||||||
mox quickstart [-existing-webserver] user@domain [user | uid]
|
mox quickstart [-existing-webserver] [-hostname host] user@domain [user | uid]
|
||||||
mox stop
|
mox stop
|
||||||
mox setaccountpassword address
|
mox setaccountpassword address
|
||||||
mox setadminpassword
|
mox setadminpassword
|
||||||
|
@ -91,6 +91,14 @@ systemd service file and prints commands to enable and start mox as service.
|
||||||
The user or uid is optional, defaults to "mox", and is the user or uid/gid mox
|
The user or uid is optional, defaults to "mox", and is the user or uid/gid mox
|
||||||
will run as after initialization.
|
will run as after initialization.
|
||||||
|
|
||||||
|
Quickstart assumes mox will run on the machine you run quickstart on and uses
|
||||||
|
its host name and public IPs. On many systems the hostname is not a fully
|
||||||
|
qualified domain name, but only the first dns "label", e.g. "mail" in case of
|
||||||
|
"mail.example.org". If so, quickstart does a reverse DNS lookup to find the
|
||||||
|
hostname, and as fallback uses the label plus the domain of the email address
|
||||||
|
you specified. Use flag -hostname to explicitly specify the hostname mox will
|
||||||
|
run on.
|
||||||
|
|
||||||
Mox is by far easiest to operate if you let it listen on port 443 (HTTPS) and
|
Mox is by far easiest to operate if you let it listen on port 443 (HTTPS) and
|
||||||
80 (HTTP). TLS will be fully automatic with ACME with Let's Encrypt.
|
80 (HTTP). TLS will be fully automatic with ACME with Let's Encrypt.
|
||||||
|
|
||||||
|
@ -107,9 +115,11 @@ traffic to your existing backend applications. Look for "WebHandlers:" in the
|
||||||
output of "mox config describe-domains" and see the output of "mox example
|
output of "mox config describe-domains" and see the output of "mox example
|
||||||
webhandlers".
|
webhandlers".
|
||||||
|
|
||||||
usage: mox quickstart [-existing-webserver] user@domain [user | uid]
|
usage: mox quickstart [-existing-webserver] [-hostname host] user@domain [user | uid]
|
||||||
-existing-webserver
|
-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.
|
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
|
||||||
|
|
||||||
# mox stop
|
# mox stop
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# mkdir config data web
|
# mkdir config data web
|
||||||
# docker-compose run mox mox quickstart you@yourdomain.example $(id -u mox)
|
# docker-compose run mox mox quickstart you@yourdomain.example $(id -u mox)
|
||||||
#
|
#
|
||||||
|
# note: if you are running quickstart on a different machine than you will deploy
|
||||||
|
# mox to, use the "quickstart -hostname ..." flag.
|
||||||
|
#
|
||||||
# After following the quickstart instructions you can start mox:
|
# After following the quickstart instructions you can start mox:
|
||||||
#
|
#
|
||||||
# docker-compose up
|
# docker-compose up
|
||||||
|
|
159
quickstart.go
159
quickstart.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -22,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/mjl-/mox/config"
|
"github.com/mjl-/mox/config"
|
||||||
"github.com/mjl-/mox/dns"
|
"github.com/mjl-/mox/dns"
|
||||||
|
"github.com/mjl-/mox/dnsbl"
|
||||||
"github.com/mjl-/mox/mox-"
|
"github.com/mjl-/mox/mox-"
|
||||||
"github.com/mjl-/mox/smtp"
|
"github.com/mjl-/mox/smtp"
|
||||||
"github.com/mjl-/mox/store"
|
"github.com/mjl-/mox/store"
|
||||||
|
@ -41,7 +43,7 @@ func pwgen() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdQuickstart(c *cmd) {
|
func cmdQuickstart(c *cmd) {
|
||||||
c.params = "[-existing-webserver] user@domain [user | uid]"
|
c.params = "[-existing-webserver] [-hostname host] user@domain [user | uid]"
|
||||||
c.help = `Quickstart generates configuration files and prints instructions to quickly set up a mox instance.
|
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
|
Quickstart writes configuration files, prints initial admin and account
|
||||||
|
@ -51,6 +53,14 @@ systemd service file and prints commands to enable and start mox as service.
|
||||||
The user or uid is optional, defaults to "mox", and is the user or uid/gid mox
|
The user or uid is optional, defaults to "mox", and is the user or uid/gid mox
|
||||||
will run as after initialization.
|
will run as after initialization.
|
||||||
|
|
||||||
|
Quickstart assumes mox will run on the machine you run quickstart on and uses
|
||||||
|
its host name and public IPs. On many systems the hostname is not a fully
|
||||||
|
qualified domain name, but only the first dns "label", e.g. "mail" in case of
|
||||||
|
"mail.example.org". If so, quickstart does a reverse DNS lookup to find the
|
||||||
|
hostname, and as fallback uses the label plus the domain of the email address
|
||||||
|
you specified. Use flag -hostname to explicitly specify the hostname mox will
|
||||||
|
run on.
|
||||||
|
|
||||||
Mox is by far easiest to operate if you let it listen on port 443 (HTTPS) and
|
Mox is by far easiest to operate if you let it listen on port 443 (HTTPS) and
|
||||||
80 (HTTP). TLS will be fully automatic with ACME with Let's Encrypt.
|
80 (HTTP). TLS will be fully automatic with ACME with Let's Encrypt.
|
||||||
|
|
||||||
|
@ -68,7 +78,9 @@ output of "mox config describe-domains" and see the output of "mox example
|
||||||
webhandlers".
|
webhandlers".
|
||||||
`
|
`
|
||||||
var existingWebserver bool
|
var existingWebserver bool
|
||||||
|
var hostname string
|
||||||
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.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")
|
||||||
args := c.Parse()
|
args := c.Parse()
|
||||||
if len(args) != 1 && len(args) != 2 {
|
if len(args) != 1 && len(args) != 2 {
|
||||||
c.Usage()
|
c.Usage()
|
||||||
|
@ -127,6 +139,25 @@ logging in with IMAP.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolver := dns.StrictResolver{}
|
||||||
|
// We don't want to spend too much total time on the DNS lookups. Because DNS may
|
||||||
|
// not work during quickstart, and we don't want to loop doing requests and having
|
||||||
|
// to wait for a timeout each time.
|
||||||
|
resolveCtx, resolveCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer resolveCancel()
|
||||||
|
|
||||||
|
// We are going to find the (public) IPs to listen on and possibly the host name.
|
||||||
|
|
||||||
|
// Start with reasonable defaults. We'll replace them specific IPs, if we can find them.
|
||||||
|
publicListenerIPs := []string{"0.0.0.0", "::"}
|
||||||
|
privateListenerIPs := []string{"127.0.0.1", "::1"}
|
||||||
|
|
||||||
|
// If we find IPs based on network interfaces, {public,private}ListenerIPs are set
|
||||||
|
// based on these values.
|
||||||
|
var privateIPs, publicIPs []string
|
||||||
|
|
||||||
|
var dnshostname dns.Domain
|
||||||
|
if hostname == "" {
|
||||||
// Gather IP addresses for public and private listeners.
|
// Gather IP addresses for public and private listeners.
|
||||||
// If we cannot find addresses for a category we fallback to all ips or localhost ips.
|
// If we cannot find addresses for a category we fallback to all ips or localhost ips.
|
||||||
// We look at each network interface. If an interface has a private address, we
|
// We look at each network interface. If an interface has a private address, we
|
||||||
|
@ -135,7 +166,6 @@ logging in with IMAP.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("listing network interfaces: %s", err)
|
fatalf("listing network interfaces: %s", err)
|
||||||
}
|
}
|
||||||
var privateIPs, publicIPs []string
|
|
||||||
parseAddrIP := func(s string) net.IP {
|
parseAddrIP := func(s string) net.IP {
|
||||||
if strings.HasPrefix(s, "[") && strings.HasSuffix(s, "]") {
|
if strings.HasPrefix(s, "[") && strings.HasSuffix(s, "]") {
|
||||||
s = s[1 : len(s)-1]
|
s = s[1 : len(s)-1]
|
||||||
|
@ -184,8 +214,6 @@ logging in with IMAP.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publicListenerIPs := []string{"0.0.0.0", "::"}
|
|
||||||
privateListenerIPs := []string{"127.0.0.1", "::1"}
|
|
||||||
if len(publicIPs) > 0 {
|
if len(publicIPs) > 0 {
|
||||||
publicListenerIPs = publicIPs
|
publicListenerIPs = publicIPs
|
||||||
}
|
}
|
||||||
|
@ -193,15 +221,12 @@ logging in with IMAP.
|
||||||
privateListenerIPs = privateIPs
|
privateListenerIPs = privateIPs
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver := dns.StrictResolver{}
|
|
||||||
|
|
||||||
var hostname dns.Domain
|
|
||||||
hostnameStr, err := os.Hostname()
|
hostnameStr, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("hostname: %s", err)
|
fatalf("hostname: %s", err)
|
||||||
}
|
}
|
||||||
if strings.Contains(hostnameStr, ".") {
|
if strings.Contains(hostnameStr, ".") {
|
||||||
hostname, err = dns.ParseDomain(hostnameStr)
|
dnshostname, err = dns.ParseDomain(hostnameStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("parsing hostname: %v", err)
|
fatalf("parsing hostname: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -219,9 +244,9 @@ logging in with IMAP.
|
||||||
fmt.Printf("\n%s", fmt.Sprintf(format, args...))
|
fmt.Printf("\n%s", fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
for _, ip := range publicIPs {
|
for _, ip := range publicIPs {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
revctx, revcancel := context.WithTimeout(resolveCtx, 5*time.Second)
|
||||||
defer cancel()
|
defer revcancel()
|
||||||
l, err := resolver.LookupAddr(ctx, ip)
|
l, err := resolver.LookupAddr(revctx, ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warnf("WARNING: looking up reverse name(s) for %s: %v", ip, err)
|
warnf("WARNING: looking up reverse name(s) for %s: %v", ip, err)
|
||||||
}
|
}
|
||||||
|
@ -239,23 +264,26 @@ logging in with IMAP.
|
||||||
return nameList[i] < nameList[j]
|
return nameList[i] < nameList[j]
|
||||||
})
|
})
|
||||||
if len(nameList) == 0 {
|
if len(nameList) == 0 {
|
||||||
hostname, err = dns.ParseDomain(hostnameStr + "." + domain.Name())
|
dnshostname, err = dns.ParseDomain(hostnameStr + "." + domain.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fatalf("parsing hostname: %v", err)
|
fatalf("parsing hostname: %v", err)
|
||||||
}
|
}
|
||||||
warnf(`WARNING: cannot determine hostname because the system name is not an FQDN and
|
warnf(`WARNING: cannot determine hostname because the system name is not an FQDN and
|
||||||
no public IPs resolving to an FQDN were found. Quickstart will continue with the
|
no public IPs resolving to an FQDN were found. Quickstart guessed the host name
|
||||||
following hostname, please replace it in the suggested DNS records and config
|
below. If it is not correct, please remove the generated config files and run
|
||||||
files if this is not correct:
|
quickstart again with the -hostname flag.
|
||||||
|
|
||||||
%s
|
%s
|
||||||
`, hostname)
|
`, dnshostname)
|
||||||
} else {
|
} else {
|
||||||
if len(nameList) > 1 {
|
if len(nameList) > 1 {
|
||||||
warnf("WARNING: multiple hostnames found for the public IPs, using the first of: %s", strings.Join(nameList, ", "))
|
warnf(`WARNING: multiple hostnames found for the public IPs, using the first of: %s
|
||||||
|
If this is not correct, remove the generated config files and run quickstart
|
||||||
|
again with the -hostname flag.
|
||||||
|
`, strings.Join(nameList, ", "))
|
||||||
}
|
}
|
||||||
hostname, err = dns.ParseDomain(nameList[0])
|
dnshostname, err = dns.ParseDomain(nameList[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fatalf("parsing hostname %s: %v", nameList[0], err)
|
fatalf("parsing hostname %s: %v", nameList[0], err)
|
||||||
|
@ -264,16 +292,27 @@ files if this is not correct:
|
||||||
if warned {
|
if warned {
|
||||||
fmt.Printf("\n\n")
|
fmt.Printf("\n\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(" found %s\n", hostname)
|
fmt.Printf(" found %s\n", dnshostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Host name was explicitly configured on command-line. We'll try to use its public
|
||||||
|
// IPs below.
|
||||||
|
var err error
|
||||||
|
dnshostname, err = dns.ParseDomain(hostname)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("parsing hostname: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: lookup without going through /etc/hosts, because a machine typically has its name configured there, and LookupIPAddr will return it, but we care about DNS settings that the rest of the world uses to find us. perhaps we should check if the address resolves to 127.0.0.0/8?
|
// todo: lookup without going through /etc/hosts, because a machine typically has its name configured there, and LookupIPAddr will return it, but we care about DNS settings that the rest of the world uses to find us. perhaps we should check if the address resolves to 127.0.0.0/8?
|
||||||
fmt.Printf("Looking up IPs for hostname %s...", hostname)
|
fmt.Printf("Looking up IPs for hostname %s...", dnshostname)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ipctx, ipcancel := context.WithTimeout(resolveCtx, 5*time.Second)
|
||||||
defer cancel()
|
defer ipcancel()
|
||||||
ips, err := resolver.LookupIPAddr(ctx, hostname.ASCII+".")
|
ips, err := resolver.LookupIPAddr(ipctx, dnshostname.ASCII+".")
|
||||||
|
ipcancel()
|
||||||
var xips []net.IPAddr
|
var xips []net.IPAddr
|
||||||
|
var xipstrs []string
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
// During linux install, you may get an alias for you full hostname in /etc/hosts
|
// During linux install, you may get an alias for you full hostname in /etc/hosts
|
||||||
// resolving to 127.0.1.1, which would result in a false positive about the
|
// resolving to 127.0.1.1, which would result in a false positive about the
|
||||||
|
@ -281,12 +320,18 @@ files if this is not correct:
|
||||||
// otherwise know their FQDN.
|
// otherwise know their FQDN.
|
||||||
if !ip.IP.IsLoopback() {
|
if !ip.IP.IsLoopback() {
|
||||||
xips = append(xips, ip)
|
xips = append(xips, ip)
|
||||||
|
xipstrs = append(xipstrs, ip.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil && len(xips) == 0 {
|
if err == nil && len(xips) == 0 {
|
||||||
err = errors.New("hostname not in dns, probably only in /etc/hosts")
|
err = errors.New("hostname not in dns, probably only in /etc/hosts")
|
||||||
}
|
}
|
||||||
ips = xips
|
ips = xips
|
||||||
|
if hostname != "" {
|
||||||
|
// Host name was specified, assume we will run on a machine with those IPs.
|
||||||
|
publicListenerIPs = xipstrs
|
||||||
|
publicIPs = xipstrs
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(`
|
fmt.Printf(`
|
||||||
|
|
||||||
|
@ -305,7 +350,7 @@ This likely means one of two things:
|
||||||
your public IPs resolve back (reverse) to your hostname.
|
your public IPs resolve back (reverse) to your hostname.
|
||||||
|
|
||||||
|
|
||||||
`, hostname, err)
|
`, dnshostname, err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(" OK\n")
|
fmt.Printf(" OK\n")
|
||||||
|
|
||||||
|
@ -320,7 +365,9 @@ This likely means one of two things:
|
||||||
s := ip.String()
|
s := ip.String()
|
||||||
l = append(l, s)
|
l = append(l, s)
|
||||||
go func() {
|
go func() {
|
||||||
addrs, err := resolver.LookupAddr(ctx, s)
|
revctx, revcancel := context.WithTimeout(resolveCtx, 5*time.Second)
|
||||||
|
defer revcancel()
|
||||||
|
addrs, err := resolver.LookupAddr(revctx, s)
|
||||||
results <- result{s, addrs, err}
|
results <- result{s, addrs, err}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -347,21 +394,61 @@ This likely means one of two things:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warnf("parsing reverse name %q for %s: %v", a, r.IP, err)
|
warnf("parsing reverse name %q for %s: %v", a, r.IP, err)
|
||||||
}
|
}
|
||||||
if d == hostname {
|
if d == dnshostname {
|
||||||
match = true
|
match = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !match {
|
if !match {
|
||||||
warnf("reverse name(s) %s for ip %s do not match hostname %s, which will cause other mail servers to reject incoming messages from this IP", strings.Join(r.Addrs, ","), r.IP, hostname)
|
warnf("reverse name(s) %s for ip %s do not match hostname %s, which will cause other mail servers to reject incoming messages from this IP", strings.Join(r.Addrs, ","), r.IP, dnshostname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if warned {
|
if warned {
|
||||||
fmt.Printf("\n\n\n")
|
fmt.Printf("\n\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(" OK\n\n")
|
fmt.Printf(" OK\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cancel()
|
|
||||||
|
zones := []dns.Domain{
|
||||||
|
{ASCII: "sbl.spamhaus.org"},
|
||||||
|
{ASCII: "bl.spamcop.net"},
|
||||||
|
}
|
||||||
|
if len(publicIPs) > 0 {
|
||||||
|
fmt.Printf("Checking whether your public IPs are listed in popular DNS block lists...")
|
||||||
|
var listed bool
|
||||||
|
for _, zone := range zones {
|
||||||
|
for _, ip := range publicIPs {
|
||||||
|
dnsblctx, dnsblcancel := context.WithTimeout(resolveCtx, 5*time.Second)
|
||||||
|
status, expl, err := dnsbl.Lookup(dnsblctx, resolver, zone, net.ParseIP(ip))
|
||||||
|
dnsblcancel()
|
||||||
|
if status == dnsbl.StatusPass {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
errstr := ""
|
||||||
|
if err != nil {
|
||||||
|
errstr = fmt.Sprintf(" (%s)", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("\nWARNING: checking your public IP %s in DNS block list %s: %v %s%s", ip, zone.Name(), status, expl, errstr)
|
||||||
|
listed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if listed {
|
||||||
|
log.Printf(`
|
||||||
|
Other mail servers are likely to reject email from IPs that are in a blocklist.
|
||||||
|
If all your IPs are in block lists, you will encounter problems delivering
|
||||||
|
email. Your IP may be in block lists only temporarily. To see if your IPs are
|
||||||
|
listed in more DNS block lists, visit:
|
||||||
|
|
||||||
|
`)
|
||||||
|
for _, ip := range publicIPs {
|
||||||
|
fmt.Printf("- https://multirbl.valli.org/lookup/%s.html\n", url.PathEscape(ip))
|
||||||
|
}
|
||||||
|
fmt.Printf("\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" OK\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("\n")
|
||||||
|
|
||||||
user := "mox"
|
user := "mox"
|
||||||
if len(args) == 2 {
|
if len(args) == 2 {
|
||||||
|
@ -373,7 +460,7 @@ This likely means one of two things:
|
||||||
DataDir: "../data",
|
DataDir: "../data",
|
||||||
User: user,
|
User: user,
|
||||||
LogLevel: "debug", // Help new users, they'll bring it back to info when it all works.
|
LogLevel: "debug", // Help new users, they'll bring it back to info when it all works.
|
||||||
Hostname: hostname.Name(),
|
Hostname: dnshostname.Name(),
|
||||||
AdminPasswordFile: "adminpasswd",
|
AdminPasswordFile: "adminpasswd",
|
||||||
}
|
}
|
||||||
if !existingWebserver {
|
if !existingWebserver {
|
||||||
|
@ -402,7 +489,7 @@ This likely means one of two things:
|
||||||
public.IMAPS.Enabled = true
|
public.IMAPS.Enabled = true
|
||||||
|
|
||||||
if existingWebserver {
|
if existingWebserver {
|
||||||
hostbase := fmt.Sprintf("path/to/%s", hostname.Name())
|
hostbase := fmt.Sprintf("path/to/%s", dnshostname.Name())
|
||||||
mtastsbase := fmt.Sprintf("path/to/mta-sts.%s", domain.Name())
|
mtastsbase := fmt.Sprintf("path/to/mta-sts.%s", domain.Name())
|
||||||
autoconfigbase := fmt.Sprintf("path/to/autoconfig.%s", domain.Name())
|
autoconfigbase := fmt.Sprintf("path/to/autoconfig.%s", domain.Name())
|
||||||
public.TLS = &config.TLS{
|
public.TLS = &config.TLS{
|
||||||
|
@ -423,7 +510,9 @@ This likely means one of two things:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suggest blocklists, but we'll comment them out after generating the config.
|
// Suggest blocklists, but we'll comment them out after generating the config.
|
||||||
public.SMTP.DNSBLs = []string{"sbl.spamhaus.org", "bl.spamcop.net"}
|
for _, zone := range zones {
|
||||||
|
public.SMTP.DNSBLs = append(public.SMTP.DNSBLs, zone.Name())
|
||||||
|
}
|
||||||
|
|
||||||
internal := config.Listener{
|
internal := config.Listener{
|
||||||
IPs: privateListenerIPs,
|
IPs: privateListenerIPs,
|
||||||
|
@ -459,7 +548,7 @@ This likely means one of two things:
|
||||||
|
|
||||||
accountConf := mox.MakeAccountConfig(addr)
|
accountConf := mox.MakeAccountConfig(addr)
|
||||||
const withMTASTS = true
|
const withMTASTS = true
|
||||||
confDomain, keyPaths, err := mox.MakeDomainConfig(context.Background(), domain, hostname, username, withMTASTS)
|
confDomain, keyPaths, err := mox.MakeDomainConfig(context.Background(), domain, dnshostname, username, withMTASTS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("making domain config: %s", err)
|
fatalf("making domain config: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -592,7 +681,7 @@ The paths are relative to config/ directory that holds mox.conf! To test if your
|
||||||
config is valid, run:
|
config is valid, run:
|
||||||
|
|
||||||
./mox config test
|
./mox config test
|
||||||
`, domain.ASCII, domain.ASCII, hostname.ASCII)
|
`, domain.ASCII, domain.ASCII, dnshostname.ASCII)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(`
|
fmt.Printf(`
|
||||||
Configuration files have been written to config/mox.conf and
|
Configuration files have been written to config/mox.conf and
|
||||||
|
|
Loading…
Reference in a new issue