this is quite common on the internet. the other side may be trying some other
protocol, e.g. http, or some common vulnerability. we don't want to spam our
own logs with multiple invalid lines. if the first command is valid, but later
are not, we'll keep trying to process them. so this only affects protocol
sessions that are very likely not smtp/imap.
also remove a few more sleeps during tests, making imapserver and smtpserver tests a bit faster.
current behaviour isn't intuitive. it's not great to have to attempt parsing
the strings as both localpart and email address. so we deprecate the
localpart-only behaviour. when we load the config file, and it has
localpart-only Destinations keys, we'll change them to full addresses in
memory. when an admin causes a write of domains.conf, it'll automatically be
fixed. we log an error with a deprecated notice for each localpart-only
destinations key.
sometime in the future, we can remove the old localpart-only destination
support. will be in the release notes then.
also start keeping track of update notes that need to make it in the release
notes of the next release.
for issue #18
the idea is to make it clear from the logging if non-ascii characters are used.
this is implemented by making mlog recognize if a field value that will be
logged has a LogString method. if so, that value is logged. dns.Domain,
smtp.Address, smtp.Localpart, smtp.Path now have a LogString method.
some explicit calls to String have been replaced to LogString, and some %q
formatting have been replaced with %s, because the escaped localpart would
already have double quotes, and double doublequotes aren't easy to read.
if you watch for a release, you will get an email when a new release is created.
when a new tag is created, github does not notify you. so i will be creating
github releases for newly added tags, so it's easier to stay up to date with
that feature.
you can already get most http to https redirects through DontRedirectPlainHTTP
in WebHandler, but that needs handlers for all paths.
now you can just set up a redirect for a domain and all its path to baseurl
https://domain (leaving other webdirect fields empty). when the request comes
in with plain http, the redirect to https is done. that next request will also
evaluate the same redirect rule. but it will not cause a match because it would
redirect to the same scheme,host,path. so next webhandlers get a chance to
serve.
also clarify in webhandlers docs that also account & admin built-in handlers
run first.
related to issue #16
- 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.
- make it easier to run with an existing webserver. the quickstart now has a new option for that, it generates a different mox.conf, and further instructions such as configuring the tls keys/certs and reverse proxy urls. and changes to make autoconfig work in that case too.
- when starting up, request a tls cert for the hostname and for the autoconfig endpoint. the first will be requested soon anyway, and the autoconfig cert is needed early so the first autoconfig request doesn't time out (without helpful message to the user by at least thunderbird). and don't request the certificate before the servers are online. the root process was now requesting the certs, before the child process was serving on the tls port.
- add examples of configs generated by the quickstart.
- enable debug logging in config from quickstart, to give user more info.
for issue #5
the idea of the rejects mailbox is to show messages that were rejected. you can
look there, and if you see a message that should have been delivered, you can
move it to your inbox or archive. next time a deliver attempt by that user is
attempted, they should be accepted, because you corrected the reject. but that
wasn't happening, because the reputation-calculation is per-delivery mailbox
(e.g. Inbox) and we look at MailboxOrigID when calculating the reputation. and
that was set to the Rejects mailbox id, so the message wasn't considered. the
same applies to moving messages from Rejects to Junk (to train your filter).
we now keep track of a MailboxDestinedID, that is set to the mailbox that we
would have delivered to if we would not have rejected the message. then, when a
message is moved out of the Rejects mailbox, we change MailboxOrigID to
MailboxDestinedID. this essentially makes the message look like it was
delivered normally.
the problem was that we only looked up either the ipv4 or ipv6 address when
evaluating spf directives, depending on the incoming smtp connection. for
example, for spf directive "a", we would lookup the requested domain. if that
domain has an ipv4 address but no ipv6 address, and the incoming connection is
ipv6, we would count a void lookup. but we shouldn't: there is a record for
that name, it just doesn't match the address (family).
- make builtin http handlers serve on specific domains, such as for mta-sts, so
e.g. /.well-known/mta-sts.txt isn't served on all domains.
- add logging of a few more fields in access logging.
- small tweaks/bug fixes in webserver request handling.
- add config option for redirecting entire domains to another (common enough).
- split httpserver metric into two: one for duration until writing header (i.e.
performance of server), another for duration until full response is sent to
client (i.e. performance as perceived by users).
- add admin ui, a new page for managing the configs. after making changes
and hitting "save", the changes take effect immediately. the page itself
doesn't look very well-designed (many input fields, makes it look messy). i
have an idea to improve it (explained in admin.html as todo) by making the
layout look just like the config file. not urgent though.
i've already changed my websites/webapps over.
the idea of adding a webserver is to take away a (the) reason for folks to want
to complicate their mox setup by running an other webserver on the same machine.
i think the current webserver implementation can already serve most common use
cases. with a few more tweaks (feedback needed!) we should be able to get to 95%
of the use cases. the reverse proxy can take care of the remaining 5%.
nevertheless, a next step is still to change the quickstart to make it easier
for folks to run with an existing webserver, with existing tls certs/keys.
that's how this relates to issue #5.
- serve static files, serving index.html or optionally listings for directories
- redirects
- reverse-proxy, forwarding requests to a backend
these are configurable through the config file. a domain and path regexp have to
be configured. path prefixes can be stripped. configured domains are added to
the autotls allowlist, so acme automatically fetches certificates for them.
all webserver requests now have (access) logging, metrics, rate limiting.
on http errors, the error message prints an encrypted cid for relating with log files.
this also adds a new mechanism for example config files.
- CAP_FSETID looks needed to make accessing setgid dirs work.
- CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH are needed to access the existing config/mox.conf.
- CAP_FOWNER seems needed to chmod the config/ and data/ files.
- RestrictSUIDSGID=yes has to be off for chmod to work
because users may run this on their local machine, then copy the binary the
their server. there is a good chance that binary won't start on linux/amd64 when
compiled with cgo due to missing glibc symbols.
binaries for linux/amd64 were build for each target platform. apparently the
--platform in the first-stage overrides the $TARGET* variables of the build.
docker behaviour always manages to surprise me...
makes it easier to run on bsd's, where you cannot (easily?) let non-root users
bind to ports <1024. starting as root also paves the way for future improvements
with privilege separation.
unfortunately, this requires changes to how you start mox. though mox will help
by automatically fix up dir/file permissions/ownership.
if you start mox from the systemd unit file, you should update it so it starts
as root and adds a few additional capabilities:
# first update the mox binary, then, as root:
./mox config printservice >mox.service
systemctl daemon-reload
systemctl restart mox
journalctl -f -u mox &
# you should see mox start up, with messages about fixing permissions on dirs/files.
if you used the recommended config/ and data/ directory, in a directory just for
mox, and with the mox user called "mox", this should be enough.
if you don't want mox to modify dir/file permissions, set "NoFixPermissions:
true" in mox.conf.
if you named the mox user something else than mox, e.g. "_mox", add "User: _mox"
to mox.conf.
if you created a shared service user as originally suggested, you may want to
get rid of that as it is no longer useful and may get in the way. e.g. if you
had /home/service/mox with a "service" user, that service user can no longer
access any files: only mox and root can.
this also adds scripts for building mox docker images for alpine-supported
platforms.
the "restart" subcommand has been removed. it wasn't all that useful and got in
the way.
and another change: when adding a domain while mtasts isn't enabled, don't add
the per-domain mtasts config, as it would cause failure to add the domain.
based on report from setting up mox on openbsd from mteege.
and based on issue #3. thanks for the feedback!
import does its own batched junkfilter training, so the deliver function
doesn't have to do it one message at a time, writing the updated filter each
time. however, if the message cannot be parsed, it isn't trained during import,
and deliver would try to train it again. it would try to open the junk filter
to do so, but that would fail because the import function already has the
junkfilter open (and the timeout is reached). a missing error check would
continue with a nil junkfilter, resulting in the nil pointer deref.
this adds the missing error check, and makes sure the deliver function does not
also try to train unparseable imported messages.
report from Jens Hilligsøe