Commit Graph

70 Commits

Author SHA1 Message Date
73381d26ed Merge commit 'be570d1c7d3de0ddacb011b6411a302d7f7e9f9e'
from github PR #153
2024-04-13 13:31:02 +02:00
be570d1c7d add TransportDirect transport
The `TransportDirect` transport allows to tweak outgoing SMTP
connections to remote servers. Currently, it only allows to select
network IP family (ipv4, ipv6 or both).

For example, to disable ipv6 for all outgoing SMTP connections:
- add these lines in mox.conf to create a new transport named
"disableipv6":
```
Transports:
  disableipv6:
    Direct:
      DisableIpv6: true
```
- then add these lines in domains.conf to use this transport:
```
Routes:
  -
    Transport: disableipv6
```

fix #149
2024-04-12 17:27:39 +02:00
ad8c5616b1 do not use input type=email for email addresses
despite the name, it doesn't actually check for valid email addresses:
it doesn't allow non-ascii localparts, accepts various invalid localparts, and
rejects various valid localparts. no point in using it.
2024-04-11 23:45:47 +02:00
40ade995a5 improve queue management
- add option to put messages in the queue "on hold", preventing delivery
  attempts until taken off hold again.
- add "hold rules", to automatically mark some/all submitted messages as "on
  hold", e.g. from a specific account or to a specific domain.
- add operation to "fail" a message, causing a DSN to be delivered to the
  sender. previously we could only drop a message from the queue.
- update admin page & add new cli tools for these operations, with new
  filtering rules for selecting the messages to operate on. in the admin
  interface, add filtering and checkboxes to select a set of messages to operate
  on.
2024-03-18 08:50:42 +01:00
79f1054b64 factor common typescript api call code pattern into a function 2024-03-17 08:41:33 +01:00
79fb72f3cd don't show default domain on admin account page
it is a remnant from the time domains didn't have to be specific in
"Destination" addresses. we still use it for as default selection for adding a
new address to an account. but there's not much point in showing it so
prominently. that raises more questions than it is helpful.

for issue #142 by tabatinga0xffff
2024-03-17 07:39:00 +01:00
8b2c97808d add account option to skip the first-time sender delay
useful for accounts that automatically process messages and want to process quickly
2024-03-16 20:24:07 +01:00
281411c297 add styling for sticky table headers, for scrolling with long tables 2024-03-16 19:27:29 +01:00
fdee24f3bd in web interfaces, put crumbs path in document title, for more useful browser history 2024-03-16 19:13:44 +01:00
4dea2de343 implement imap quota extension (rfc 9208)
we only have a "storage" limit. for total disk usage. we don't have a limit on
messages (count) or mailboxes (count). also not on total annotation size, but
we don't have support annotations at all at the moment.

we don't implement setquota. with rfc 9208 that's allowed. with the previous
quota rfc 2087 it wasn't.

the status command can now return "DELETED-STORAGE". which should be the disk
space that can be reclaimed by removing messages with the \Deleted flags.
however, it's not very likely clients set the \Deleted flag without expunging
the message immediately. we don't want to go through all messages to calculate
the sum of message sizes with the deleted flag. we also don't currently track
that in MailboxCount. so we just respond with "0". not compliant, but let's
wait until someone complains.

when returning quota information, it is not possible to give the current usage
when no limit is configured. clients implementing rfc 9208 should probably
conclude from the presence of QUOTA=RES-* capabilities (only in rfc 9208, not
in 2087) and the absence of those limits in quota responses (or the absence of
an untagged quota response at all) that a resource type doesn't have a limit.
thunderbird will claim there is no quota information when no limit was
configured, so we can probably conclude that it implements rfc 2087, but not
rfc 9208.

we now also show the usage & limit on the account page.

for issue #115 by pmarini
2024-03-11 14:24:32 +01:00
4699504c9f show goversion and goos/goarch on admin page 2024-03-11 08:58:40 +01:00
a601814c3d fix build after previous commit 2024-03-09 15:52:28 +01:00
0c800f3d7e update to latest sherpats fixing typo in error message, handle absent dmarc "policy override" reason 2024-03-09 15:43:49 +01:00
7969cf002a allow zero configured addresses for an account
preventing writing out a domains.conf that is invalid and can't be parsed
again. this happens when the last address was removed from an account. just a
click in the admin web interface.

accounts without email address cannot log in.

for issue #133 by ally9335
2024-03-09 11:51:02 +01:00
92e0d2a682 webadmin: be more helpful when adding domains/accounts/addresses
by explaining (in the titles/hovers) what the concepts and requirements are, by
using selects/dropdowns or datalist suggestions where we have a known list, by
automatically suggesting a good account name, and putting the input fields in a
more sensible order.

based on issue #132 by ally9335
2024-03-09 11:11:52 +01:00
8e6fe7459b normalize localparts with unicode nfc when parsing
both when parsing our configs, and for incoming on smtp or in messages.
so we properly compare things like é and e+accent as equal, and accept the
different encodings of that same address.
2024-03-08 21:08:40 +01:00
b541646275 be more helpful about instructions for installing unbound and dnssec
by mentioning the dnssec root keys, mentioning which unbound version has EDE,
giving a "dig" invocation to check for dnssec results.

based on issue #131 by romner-set, thanks for reporting
2024-03-07 10:47:48 +01:00
4db1f5593c better check for dnssec-verifying resolver
check the authentic data bit for the NS records of "com.", not for ".": some
dnssec-verifying resolvers return unauthentic data for ".".

for issue #139 by triatic, thanks!
2024-03-07 10:34:13 +01:00
9e7d6b85b7 queue: deliver to multiple recipients in a single smtp transaction
transferring the data only once. we only do this when the recipient domains
are the same. when queuing, we now take care to set the same NextAttempt
timestamp, so queued messages are actually eligable for combined delivery.

this adds a DeliverMultiple to the smtp client. for pipelined requests, it will
send all RCPT TO (and MAIL and DATA) in one go, and handles the various
responses and error conditions, returning either an overal error, or per
recipient smtp responses. the results of the smtp LIMITS extension are also
available in the smtp client now.

this also takes the "LIMITS RCPTMAX" smtp extension into account: if the server
only accepts a single recipient, we won't send multiple.
if a server doesn't announce a RCPTMAX limit, but still has one (like mox does
for non-spf-verified transactions), we'll recognize code 452 and 552 (for
historic reasons) as temporary error, and try again in a separate transaction
immediately after. we don't yet implement "LIMITS MAILMAX", doesn't seem likely
in practice.
2024-03-07 10:07:53 +01:00
47ebfa8152 queue: implement adding a message to the queue that gets sent to multiple recipients
and in a way that allows us to send that message to multiple recipients in a
single smtp transaction.
2024-03-05 20:10:28 +01:00
15e450df61 implement only monitoring dns blocklists, without using them for incoming deliveries
so you can still know when someone has put you on their blocklist (which may
affect delivery), without using them.

also query dnsbls for our ips more often when we do more outgoing connections
for delivery: once every 100 messages, but at least 5 mins and at most 3 hours
since the previous check.
2024-03-05 19:37:48 +01:00
a9cb6f9d0a webadmin: add single-line form for looking up a cid for a received id 2024-03-05 10:50:56 +01:00
93c52b01a0 implement "future release"
the smtp extension, rfc 4865.
also implement in the webmail.
the queueing/delivery part hardly required changes: we just set the first
delivery time in the future instead of immediately.

still have to find the first client that implements it.
2024-02-10 17:55:56 +01:00
d1b87cdb0d replace packages slog and slices from golang.org/x/exp with stdlib
since we are now at go1.21 as minimum.
2024-02-08 14:49:01 +01:00
62be829df0 when sending tls reports, ensure we use ASCII A-labels, not U-labels in the policy-domain field 2024-01-24 10:36:20 +01:00
20812dcf62 add types for missing dmarc report values in reports
so admin frontend doesn't complain about invalid values (empty strings).
2024-01-23 16:51:05 +01:00
aea8740e65 quota: fix handling negative max size when configured for an account, and clarify value is in bytes in config file
for #115 by pmarini-nc
2024-01-12 15:02:16 +01:00
0bc3072944 new website for www.xmox.nl
most content is in markdown files in website/, some is taken out of the repo
README and rfc/index.txt. a Go file generates html. static files are kept in a
separate repo due to size.
2024-01-10 17:22:03 +01:00
dda0a4ced1 at "client config", mention clients should explicitly be configured with the most secure authentication mechanism supported
to prevent authentication mechanism downgrade attacks by MitM.
2024-01-09 10:50:42 +01:00
c348834ce9 prevent firefox from autocompleting the current password in the form/fields for changing password 2024-01-05 12:15:55 +01:00
0f8bf2f220 replace http basic auth for web interfaces with session cookie & csrf-based auth
the http basic auth we had was very simple to reason about, and to implement.
but it has a major downside:

there is no way to logout, browsers keep sending credentials. ideally, browsers
themselves would show a button to stop sending credentials.

a related downside: the http auth mechanism doesn't indicate for which server
paths the credentials are.

another downside: the original password is sent to the server with each
request. though sending original passwords to web servers seems to be
considered normal.

our new approach uses session cookies, along with csrf values when we can. the
sessions are server-side managed, automatically extended on each use. this
makes it easy to invalidate sessions and keeps the frontend simpler (than with
long- vs short-term sessions and refreshing). the cookies are httponly,
samesite=strict, scoped to the path of the web interface. cookies are set
"secure" when set over https. the cookie is set by a successful call to Login.
a call to Logout invalidates a session. changing a password invalidates all
sessions for a user, but keeps the session with which the password was changed
alive. the csrf value is also random, and associated with the session cookie.
the csrf must be sent as header for api calls, or as parameter for direct form
posts (where we cannot set a custom header). rest-like calls made directly by
the browser, e.g. for images, don't have a csrf protection. the csrf value is
returned by the Login api call and stored in localstorage.

api calls without credentials return code "user:noAuth", and with bad
credentials return "user:badAuth". the api client recognizes this and triggers
a login. after a login, all auth-failed api calls are automatically retried.
only for "user:badAuth" is an error message displayed in the login form (e.g.
session expired).

in an ideal world, browsers would take care of most session management. a
server would indicate authentication is needed (like http basic auth), and the
browsers uses trusted ui to request credentials for the server & path. the
browser could use safer mechanism than sending original passwords to the
server, such as scram, along with a standard way to create sessions.  for now,
web developers have to do authentication themselves: from showing the login
prompt, ensuring the right session/csrf cookies/localstorage/headers/etc are
sent with each request.

webauthn is a newer way to do authentication, perhaps we'll implement it in the
future. though hardware tokens aren't an attractive option for many users, and
it may be overkill as long as we still do old-fashioned authentication in smtp
& imap where passwords can be sent to the server.

for issue #58
2024-01-05 10:48:42 +01:00
a9940f9855 change javascript into typescript for webaccount and webadmin interface
all ui frontend code is now in typescript. we no longer need jshint, and we
build the frontend code during "make build".

this also changes tlsrpt types for a Report, not encoding field names with
dashes, but to keep them valid identifiers in javascript. this makes it more
conveniently to work with in the frontend, and works around a sherpats
limitation.
2023-12-31 12:05:31 +01:00
da3ed38a5c assume a dns cname record mail.<domain>, pointing to the hostname of the mail server, for clients to connect to
the autoconfig/autodiscover endpoints, and the printed client settings (in
quickstart, in the admin interface) now all point to the cname record (called
"client settings domain"). it is configurable per domain, and set to
"mail.<domain>" by default. for existing mox installs, the domain can be added
by editing the config file.

this makes it easier for a domain to migrate to another server in the future.
client settings don't have to be updated, the cname can just be changed.
before, the hostname of the mail server was configured in email clients.
migrating away would require changing settings in all clients.

if a client settings domain is configured, a TLS certificate for the name will
be requested through ACME, or must be configured manually.
2023-12-24 11:06:08 +01:00
db3fef4981 when suggesting CAA records for a domain, suggest variants that bind to the account id and with validation methods used by mox
should prevent potential mitm attacks. especially when done close to the
machine itself (where a http/tls challenge is intercepted to get a valid
certificate), as seen on the internet last month.
2023-12-21 15:53:32 +01:00
d73bda7511 add per-account quota for total message size disk usage
so a single user cannot fill up the disk.
by default, there is (still) no limit. a default can be set in the config file
for all accounts, and a per-account max size can be set that would override any
global setting.

this does not take into account disk usage of the index database. and also not
of any file system overhead.
2023-12-20 20:54:12 +01:00
e048d0962b small fixes
a typo, using ongoing tx instead of making a new one, don't pass literal string
to formatting function.

found while working on quota support.
2023-12-16 11:53:14 +01:00
dfddf0e874 for webapi requests, make canceled contexts a user instead of server error
no need to trigger alerts for user-initiated errors
2023-12-15 15:47:54 +01:00
1abadc5499 add "warn" log level
now that we are using slog, which has them.
and we already could use them for a deprecation warning.
2023-12-14 20:26:06 +01:00
d1b66035a9 add more documentation, examples with tests to illustrate reusable components 2023-12-14 20:20:17 +01:00
5b20cba50a switch to slog.Logger for logging, for easier reuse of packages by external software
we don't want external software to include internal details like mlog.
slog.Logger is/will be the standard.

we still have mlog for its helper functions, and its handler that logs in
concise logfmt used by mox.

packages that are not meant for reuse still pass around mlog.Log for
convenience.

we use golang.org/x/exp/slog because we also support the previous Go toolchain
version. with the next Go release, we'll switch to the builtin slog.
2023-12-14 13:45:52 +01:00
73a2a09711 better handling of outgoing tls reports to recipient domains vs hosts
based on discussion on uta mailing list. it seems the intention of the tlsrpt
is to only send reports to recipient domains. but i was able to interpret the
tlsrpt rfc as sending reports to mx hosts too ("policy domain", and because it
makes sense given how DANE works per MX host, not recipient domain). this
change makes the behaviour of outgoing reports to recipient domains work more
in line with expectations most folks may have about tls reporting (i.e. also
include per-mx host tlsa policies in the report). this also keeps reports to mx
hosts working, and makes them more useful by including the recipient domains of
affected deliveries.
2023-11-20 11:31:46 +01:00
651fa68067 webadmin: in list with dmarc evaluations, add the dispositions applied
to easily spot rejects
2023-11-13 14:44:40 +01:00
e24e1bee19 add suppression list for outgoing dmarc and tls reports
for reporting addresses that cause DSNs to be returned. that just adds noise.
the admin can add/remove/extend addresses through the webadmin.

in the future, we could send reports with a smtp mail from of
"postmaster+<signed-encoded-recipient>@...", and add the reporting recipient
on the suppression list automatically when a DSN comes in on that address, but
for now this will probably do.
2023-11-13 13:48:52 +01:00
ae37b3ed4d webadmin: don't on queue page when there are no transports and the queue is non-empty (typical case) 2023-11-12 22:04:48 +01:00
2265769b8e webadmin: allow accessing tls reports for mail host policy domain (tlsa)
instead of requiring policy domains to be configured recipient domains.
when accessing TLS reports, always do it under path #tlsrpt/reports, not under #domain/.../tlsrpt.
2023-11-12 14:58:46 +01:00
ff4237e88a tlsrpt improvements
- accept incoming tls reports for the host, with policy-domain the host name.
  instead of not storing the domain because it is not a configured (recipient)
  domain.
- in tlsrpt summaries, rename domain to policy domain for clarity.
- in webadmin, fix html for table that lists tls reports in case of multiple
  policies and/or multiple failure details.
2023-11-12 14:19:12 +01:00
f90b802d4b webadmin: add column with found policy types to table listing the results 2023-11-12 12:00:21 +01:00
a0bae5be55 for dns errors when looking up a tlsrpt record in the admin, don't make it a server error
but a user error. so we don't generate alerts through prometheus.
2023-11-12 11:53:39 +01:00
448879126d when listing incoming tls reports, don't show "(no policy)" for tlsa policies
that hint was meant for the mode of a sts policy. for tlsa (and
no-policy-found), there is not going to be a mode.
2023-11-12 11:50:48 +01:00
2073db194b when checking domain settings, check that dmarc & tls reporting addresses are present if there is a record 2023-11-10 20:25:06 +01:00