before, we would just say "session expired". now we say "session expired (after
12 hours inactivity)" (for admin) or "session expired (after 24 hours
inactivity)" for account/webmail. for unknown sessions in the admin interface,
we also explain that server restarts and 10 more new sessions can be the
reason.
for issue #202 by ally9335
for issue #186 by morki, thanks for reporting and providing sample favicons.
generated by the mentioned generator at favicon.io, with the ubuntu font and a
fuchsia-like color.
the favicon is served for listeners/domains that have the
admin/account/webmail/webapi endpoints enabled, i.e. user-facing. the mta-sts,
autoconfig, etc urls don't serve the favicon.
admins can create webhandler routes to serve another favicon. these webhandler
routes are evaluted before the favicon route (a "service handler").
before, the suggested records would show "v=spf1 mx ~all", while the dnscheck
page would suggest "v=spf1 ip4:... ip6:... -all".
the two places now show the same record: explicitly listing the configured ip's
(so the common case of a valid message is fast and doesn't require lookups of
mx hosts and their addresses), but still including "mx" (may prevent issues
while migrating to new ips in the future and doesn't hurt for legit messages),
and "~all" (for compatibility with some old systems that don't look at
dkim/dmarc when they evaluate spf and reach "-all")
based on #176 created by rdelaage, with record mismatch spotted by RobSlgm,
thanks!
if no host keys are configured, show as warning (yellow) that dane isn't
configured, and show instructions to enable it.
for issue #185 by morki, thanks for reporting!
the suggested dns records mention that these records are optional, but the
dnscheck makes it look serious. not helpful.
also remove unneeded whitespace in list of errors/warnings.
for issue #184 by morki, thanks for reporting!
the host tlsrpt record implied it was for the domain, but should have been for
the mail host.
some dns records were absolute, others weren't. now they all are for
consistency.
for issue #182 by mdavids, thanks for reporting!
per listener, you could enable the admin/account/webmail/webapi handlers. but
that would serve those services on their configured paths (/admin/, /,
/webmail/, /webapi/) on all domains mox would be webserving, including any
non-mail domains. so your www.example/admin/ would be serving the admin web
interface, with no way to disabled that.
with this change, the admin interface is only served on requests to (based on
Host header):
- ip addresses
- the listener host name (explicitly configured in the listener, with fallback
to global hostname)
- "localhost" (for ssh tunnel/forwarding scenario's)
the account/webmail/webapi interfaces are served on the same domains as the
admin interface, and additionally:
- the client settings domains, as optionally configured in each Domain in
domains.conf. typically "mail.<yourdomain>".
this means the internal services are no longer served on other domains
configured in the webserver, e.g. www.example.org/admin/ will not be handled
specially.
the order of evaluation of routes/services is also changed:
before this change, the internal handlers would always be evaluated first.
with this change, only the system handlers for
MTA-STS/autoconfig/ACME-validation will be evaluated first. then the webserver
handlers. and finally the internal services (admin/account/webmail/webapi).
this allows an admin to configure overrides for some of the domains (per
hostname-matching rules explained above) that would normally serve these
services.
webserver handlers can now be configured that pass the request to an internal
service: in addition to the existing static/redirect/forward config options,
there is now an "internal" config option, naming the service
(admin/account/webmail/webapi) for handling the request. this allows enabling
the internal services on custom domains.
for issue #160 by TragicLifeHu, thanks for reporting!
recreating the account would resurface the old messages, certainly not what you'ld expect.
it's about time to just remove the files. we do ask admins to confirm that when
removing through admin interface. it's also in the "mox config account rm" help
output now.
for issue #162 by RobSlgm with feedback from x8x, thanks!
several fields in dmarc and tls reports have known string values. we have a Go
string type for them. sherpats (through sherpadoc) turns those strings into
typescript enums, and sherpats generates runtime-typechecking code (to enforce
correct types for incoming json, to prevent failing deeper in the code when we
get invalid data (much harder to debug)). the Go not-really-enum types allow
other values, and real-world reports have unknown/unspecified/invalid values.
this uses the sherpadoc -rename flag to turn those enums into regular untyped
strings, so sherpats doesn't generate enum-enforcing runtime type checking
code.
this required an update to sherpadoc, to properly handling renaming a type to a
basic type instead of another named type.
for issue #161 by RobSlgm, thanks for reporting!
- the error wasn't caught because the parseInt() call wasn't evaluated inside the promise.
- we no longer require that the input (e.g. 2G) is the same as how we would format it (2g).
- tooltips and error message should now steer people to using these units.
feedback from pmarini-nc in #115, thanks!
unless the address is the last member, then the admin must either remove the
alias first, or add new members. we don't want to accidentally remove an alias
address.
in the admin page for removing addresses, we warn the admin that the address
will be removed from any aliases.
since email addresses can contain multiple consecutive spaces.
this is a valid address: " "@localhost
and this is a different valid address: " "@localhost
webmail still todo
the members must currently all be addresses of local accounts.
a message sent to an alias is accepted if at least one of the members accepts
it. if no members accepts it (e.g. due to bad reputation of sender), the
message is rejected.
if a message is submitted to both an alias addresses and to recipients that are
members of the alias in an smtp transaction, the message will be delivered to
such members only once. the same applies if the address in the message
from-header is the address of a member: that member won't receive the message
(they sent it). this prevents duplicate messages.
aliases have three configuration options:
- PostPublic: whether anyone can send through the alias, or only members.
members-only lists can be useful inside organizations for internal
communication. public lists can be useful for support addresses.
- ListMembers: whether members can see the addresses of other members. this can
be seen in the account web interface. in the future, we could export this in
other ways, so clients can expand the list.
- AllowMsgFrom: whether messages can be sent through the alias with the alias
address used in the message from-header. the webmail knows it can use that
address, and will use it as from-address when replying to a message sent to
that address.
ideas for the future:
- allow external addresses as members. still with some restrictions, such as
requiring a valid dkim-signature so delivery has a chance to succeed. will
also need configuration of an admin that can receive any bounces.
- allow specifying specific members who can sent through the list (instead of
all members).
for github issue #57 by hmfaysal.
also relevant for #99 by naturalethic.
thanks to damir & marin from sartura for discussing requirements/features.
if the message has a list-id header, we assume this is a (mailing) list
message, and we require a dkim/spf-verified domain (we prefer the shortest that
is a suffix of the list-id value). the rule we would add will mark such
messages as from a mailing list, changing filtering rules on incoming messages
(not enforcing dmarc policies). messages will be matched on list-id header and
will only match if they have the same dkim/spf-verified domain.
if the message doesn't have a list-id header, we'll ask to match based on
"message from" address.
we don't ask the user in several cases:
- if the destination/source mailbox is a special-use mailbox (e.g.
trash,archive,sent,junk; inbox isn't included)
- if the rule already exist (no point in adding it again).
- if the user said "no, not for this list-id/from-address" in the past.
- if the user said "no, not for messages moved to this mailbox" in the past.
we'll add the rule if the message was moved out of the inbox.
if the message was moved to the inbox, we check if there is a matching rule
that we can remove.
we now remember the "no" answers (for list-id, msg-from-addr and mailbox) in
the account database.
to implement the msgfrom rules, this adds support to rulesets for matching on
message "from" address. before, we could match on smtp from address (and other
fields). rulesets now also have a field for comments. webmail adds a note that
it created the rule, with the date.
manual editing of the rulesets is still in the webaccount page. this webmail
functionality is just a convenient way to add/remove common rules.
the stuttering was introduced to make the same type name declared in multiple
packages, and used in the admin sherpa api, unique. with sherpadoc's new
rename, we can make them unique when generating the api definition/docs, and
the Go code can use nicer names.
for dmarc reporting address, tls reporting address, mtasts policy, dkim keys/selectors.
should make it easier for webadmin-using admins to discover these settings.
the webadmin interface is now on par with functionality you would set through
the configuration file, let's keep it that way.
this simplifies some of the code that makes modifications to the config file. a
few protected functions can make changes to the dynamic config, which webadmin
can use. instead of having separate functions in mox-/admin.go for each type of
change.
this also exports the parsed full dynamic config to webadmin, so we need fewer
functions for specific config fields too.
for applications to compose/send messages, receive delivery feedback, and
maintain suppression lists.
this is an alternative to applications using a library to compose messages,
submitting those messages using smtp, and monitoring a mailbox with imap for
DSNs, which can be processed into the equivalent of suppression lists. but you
need to know about all these standards/protocols and find libraries. by using
the webapi & webhooks, you just need a http & json library.
unfortunately, there is no standard for these kinds of api, so mox has made up
yet another one...
matching incoming DSNs about deliveries to original outgoing messages requires
keeping history of "retired" messages (delivered from the queue, either
successfully or failed). this can be enabled per account. history is also
useful for debugging deliveries. we now also keep history of each delivery
attempt, accessible while still in the queue, and kept when a message is
retired. the queue webadmin pages now also have pagination, to show potentially
large history.
a queue of webhook calls is now managed too. failures are retried similar to
message deliveries. webhooks can also be saved to the retired list after
completing. also configurable per account.
messages can be sent with a "unique smtp mail from" address. this can only be
used if the domain is configured with a localpart catchall separator such as
"+". when enabled, a queued message gets assigned a random "fromid", which is
added after the separator when sending. when DSNs are returned, they can be
related to previously sent messages based on this fromid. in the future, we can
implement matching on the "envid" used in the smtp dsn extension, or on the
"message-id" of the message. using a fromid can be triggered by authenticating
with a login email address that is configured as enabling fromid.
suppression lists are automatically managed per account. if a delivery attempt
results in certain smtp errors, the destination address is added to the
suppression list. future messages queued for that recipient will immediately
fail without a delivery attempt. suppression lists protect your mail server
reputation.
submitted messages can carry "extra" data through the queue and webhooks for
outgoing deliveries. through webapi as a json object, through smtp submission
as message headers of the form "x-mox-extra-<key>: value".
to make it easy to test webapi/webhooks locally, the "localserve" mode actually
puts messages in the queue. when it's time to deliver, it still won't do a full
delivery attempt, but just delivers to the sender account. unless the recipient
address has a special form, simulating a failure to deliver.
admins now have more control over the queue. "hold rules" can be added to mark
newly queued messages as "on hold", pausing delivery. rules can be about
certain sender or recipient domains/addresses, or apply to all messages pausing
the entire queue. also useful for (local) testing.
new config options have been introduced. they are editable through the admin
and/or account web interfaces.
the webapi http endpoints are enabled for newly generated configs with the
quickstart, and in localserve. existing configurations must explicitly enable
the webapi in mox.conf.
gopherwatch.org was created to dogfood this code. it initially used just the
compose/smtpclient/imapclient mox packages to send messages and process
delivery feedback. it will get a config option to use the mox webapi/webhooks
instead. the gopherwatch code to use webapi/webhook is smaller and simpler, and
developing that shaped development of the mox webapi/webhooks.
for issue #31 by cuu508
typescript now knows the full types, not just "any" for account config.
inline structs previously in config.Account are given their own type definition
so sherpa can generate types.
also update to latest sherpa lib that knows about time.Duration, to be used soon.
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
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.
- 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.
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
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
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
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
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.
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
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!
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.
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.
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.