this allows setting per-mailbox and per-server annotations (metadata). we have
a fixed maximum for total number of annotations (1000) and their total size
(1000000 bytes). this size isn't held against the regular quota for simplicity.
we send unsolicited metadata responses when a connection is in the idle
command and a change to a metadata item is made.
we currently only implement the /private/ namespace. we should implement the
/shared/ namespace, for mox-global metadata annotations. only the admin should
be able to configure those, probably through the config file, cli, or admin web
interface.
for issue #290
and show them in the account and admin interfaces. this should help with
debugging, to find misconfigured clients, and potentially find attackers trying
to login.
we include details like login name, account name, protocol, authentication
mechanism, ip addresses, tls connection properties, user-agent. and of course
the result.
we group entries by their details. repeat connections don't cause new records
in the database, they just increase the count on the existing record.
we keep data for at most 30 days. and we keep at most 10k entries per account.
to prevent unbounded growth. for successful login attempts, we store them all
for 30d. if a bad user causes so many entries this becomes a problem, it will
be time to talk to the user...
there is no pagination/searching yet in the admin/account interfaces. so the
list may be long. we only show the 10 most recent login attempts by default.
the rest is only shown on a separate page.
there is no way yet to disable this. may come later, either as global setting
or per account.
broken in v0.0.14, probably when introducing the css variables.
i had noticed this issue at the time, and thought i fixed it, but clearly not.
for issue #278, reported by gdunstone
we were only properly parsing values of "<date>T<time>" or just "<time>".
so you could select a date in the form (or type it), but it would be treated as
just a word of text to search for in messages. so it would quietly do the wrong
thing.
before this, you could use the button at the top of the list of mailboxes to
create a submailbox somewhere, and you would have to specify the full path of
the new mailbox name. now you can just open up your Lists/.../ mailbox, and
create a mailbox below that hierarchy.
to facilitate migrations from/to other mail setups.
a domain can be added in "disabled" mode (or can be disabled/enabled later on).
you can configure a disabled domain, but incoming/outgoing messages involving
the domain are rejected with temporary error codes (as this may occur during a
migration, remote servers will try again, hopefully to the correct machine or
after this machine has been configured correctly). also, no acme tls certs will
be requested for disabled domains (the autoconfig/mta-sts dns records may still
point to the current/previous machine). accounts with addresses at disabled
domains can still login, unless logins are disabled for their accounts.
an account now has an option to disable logins. you can specify an error
message to show. this will be shown in smtp, imap and the web interfaces. it
could contain a message about migrations, and possibly a URL to a page with
information about how to migrate. incoming/outgoing email involving accounts
with login disabled are still accepted/delivered as normal (unless the domain
involved in the messages is disabled too). account operations by the admin,
such as importing/exporting messages still works.
in the admin web interface, listings of domains/accounts show if they are disabled.
domains & accounts can be enabled/disabled through the config file, cli
commands and admin web interface.
for issue #175 by RobSlgm
and mention in a tooltip too that "empty mailbox" only affects messages in the
mailbox, not submailboxes or their messages.
prompted by a question on matrix/irc
by not trying to parse the full message for the MessageItem, but only reading
headers when needed.
before previous commit, we wouldn't try reading such messages in full either.
i've seen the error a few times:
msgheaderElem.children[(msgheaderElem.children.length - 1)] is undefined
i've seen it happen after sending a reply (with the "answered" flag added).
the updateKeywords callback would render the message again, but the code for
rendering the "additional headers" table rows again was making invalid
assumptions.
the approach is now changed. the backend now just immediately sends the
additional headers to the frontend. before, the frontend would first render the
base message, then render again once the headers came in for the parsed
message. this also prevents a reflow for the (quite common) case that one of
the additional headers are present in the message.
these settings are applied anywhere the webmail is open. the settings are for
showing keyboard shortcuts in the lower right after a mouse interaction, and
showing additional headers. the shorcuts were configurable in the "help" popup
before. the additional headers were only configurable through the developer
console before.
the "mailto:" (un)register buttons are now in the settings popup too.
ctrl-l is commonly "focus on browser address bar".
ctrl-u is commonly "view source".
ctrl-I (shift i) is commonly "open developer console".
these keys are more useful to leave for the browser. ctrl-l and ctrl-u (moving
to a message without opening it) can still be had by using also pressing shift.
the previous ctrl-shift-i (show all headers) is now just ctrl-i.
this has been requested in the past on irc/matrix (i forgot who).
for each message part. The ContentDisposition value is the base value without
header key/value parameters. the Filename field is the likely filename of the
part. the different email clients encode filenames differently. there is a
standard mime mechanism from rfc 2231. and there is the q/b-word-encoding from
rfc 2047. instead of letting users of the webhook api deal with those
differences, we provide just the parsed filename.
for issue #258 by morki, thanks for reporting!
needed for upcoming changes, where (now) package admin needs to import package
store. before, because package store imports mox- (for accessing the active
config), that would lead to a cyclic import. package mox- keeps its active
config, package admin has the higher-level config-changing functions.
this allows removing some ugly instantiations of an rng based on the current
time.
Intn is now IntN for our concurrency-safe prng wrapper to match the randv2 api.
v2 exists since go1.22, which we already require.
if files {webmail,webaccount,webadmin}.{css,js} exist in the configdir (where
the mox.conf file lives), their contents are included in the web apps.
the webmail now uses css variables, mostly for colors. so you can write a
custom webmail.css that changes the variables, e.g.:
:root {
--color: blue
}
you can also look at css class names and override their styles.
in the future, we may want to make some css variables configurable in the
per-user settings in the webmail. should reduce the number of variables first.
any custom javascript is loaded first. if it defines a global function
"moxBeforeDisplay", that is called each time a page loads (after
authentication) with the DOM element of the page content as parameter. the
webmail is a single persistent page. this can be used to make some changes to
the DOM, e.g. inserting some elements. we'll have to see how well this works in
practice. perhaps some patterns emerge (e.g. adding a logo), and we can make
those use-cases easier to achieve.
helps partially with issue #114, and based on questions from laura-lilly on
matrix.
the pointer events for moving the mouse would be consumed by the iframe. that
broke resizing of the compose popup. we now disable pointerevents on the main
ui when we are dragging the corner of the compose popup.
this is similar to an earlier change about the draggable split bar between the
message list and the message view (when showing an html message).
we kept the "save draft" promise, and would wait for it again for other
operations (eg close, save again, send), which wouldn't make progress.
can easily be reproduced by saving a message with a control character in an
address or the subject. saving the draft will fail.
for issue #256 by ally9335, thanks for reporting
before this change, when archiving, we would move all messages from the thread
that are in the same mailbox as that of the response message to the archive
mailbox. so if the message that was being responsed to was already in the
archive mailbox, the message would be moved from archive mailbox to archive
mailbox, resulting in an error.
with this change, when archiving, we move the thread messages that are in the
same mailbox as is currently open (independent of the mailbox the message lives
in, a common situation in the threading view). if there is no open mailbox
(search results), we still use the mailbox of the message being responded to as
reference.
with this new approach, we won't get errors moving a message to an archive
mailbox when it's already there. well, you can still get that error, but then
you've got the archive mailbox open, or you're in a search result and
responding to an archived message. the error should at least help understand
that nothing is happening.
we are only moving the messages from one active/reference mailbox because we
don't want to move messages from the thread that are in the Sent mailbox, and
we also don't want to move duplicate messages (cross-posts to mailing lists)
that are in other mailboxes. moving only the messages from the current active
mailbox seems safe, and should do what is what users would expect most of the
time.
for issue #233 by mattfbacon, thanks for reporting!
when we send a list of messages from the mox backend to the js frontend, we
include a parsed form of the "initial" message: the one we immediately show,
typically the top-most (unread) message. however, if that message could not be
parsed (due to invalid header syntax), we would fail the entire operation of
loading the view.
with this change, we simply don't return a parsed form of an initial message if
we cannot parse it. that will cause the webmail frontend to not select &
display a message immediately. if you then try to open the message, you'll
still get an error message as before. but at least the view has been loaded,
and you can open the raw message to inspect the contents.
for issue #219 by wneessen
these singleusetokens can be redeemed once. so when you see it in the logs, it
can't be used again. they are short-lived anyway.
this change should help prevent me periodically investigating token handling...
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
since we have more of our own styling (probably since dark mode), we weren't
indicating anymore that a button was disabled. this actually only applies to
the button for the current mailbox of a message, when attempting to move it.
we now don't show any hover effects in that case, and we show the button
semitransparent.
as they occur in From/To headers, for example: "From:
=?iso-8859-2?Q?Krist=FDna?= <k@example.com>". we are using net/mail to parse
such headers. most address-parsing functions in that package will only decode
charsets utf-8, iso-8859-1 and us-ascii. we have to be careful to always use
net/mail.AddressParser with a WordDecoder that understands more that the
basics.
for issue #204 by morki, thanks for reporting!
some emails have text and html versions. the html can have several logo images.
and there may be a pdf attached. when gathering attachments to show in webmail,
the pdf would come last. it could happen the logo images would get a link to
click, and the pdf would be behind the "more ..." button. by putting
"multipart/mixed" files before the "multipart/related" in the list, it's more
likely that useful files can be clicked immediately, and unimportant logo files
are behind the "more"-button.
before, the iframe was consuming the mouse events, preventing the dragging to
the right from working properly. the workaround was to drag over the area with
the header, above the message iframe.
with this change, we disable pointer events over the entire right area, which
includes the iframe.
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").
otherwise, in dark mode, the plain text iframe content would be black text on
the white background of the iframe as set by webmail. i can't find a way to set
the content text on the iframe that contains it.
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!
bstore was updated to v0.0.6 to add this logging.
this simplifies some of the db-handling code in mtastsdb,tlsrptdb,dmarcdb. we
now call the package-level Init() and Close() in all tests properly.