On 26. Jan 2025, at 18.39, subscriptions--- via dovecot <dovecot@dovecot.org> wrote:
Hi Timo,
Timo Sirainen wrote:
Oh, should clarify these. I was talking about global auth_username_format setting. With that it behaves as expected. But if you set it only inside passdb {} or userdb {} then it affects only the lookup user (i.e. lookup "user", not "user@domain" in passwd-file), but not the %{user} variable (it will contain "user@domain"). This behavior is intentional, but I wonder if it could be documented better somewhere.
Indeed I can confirm that the documentation on this subject is... optimizable.
Actually, back when I was going through the Dovecot docs for the first time, I found it utterly confusing and chaotic. It's very detailed, which is great, but for first time readers it kind of lacks an "entry point" - a place that says "This is how Dovecot is structured, this is what you have to know first, then probably this is the second thing you'll need...".
We have a new documentation structure, but I don't know if it's any better regarding that. For some reason people aren't super interested in spending much time on writing documentation. :)
Once you get used to it, you're able to navigate around and find what you need, but back then it took me like 2 full days to be able to even read (and understand) the sample config. Having it scattered over a dozen files doesn't help, either.
Well, the multiple files are gone now. And all settings are available in a single page in web documentation.
Back to the topic of the username format: Due to the above reasons, I didn't even know there was a global "auth_username_format" setting.
One big idea behind v2.4 config rewrite is that now all settings are global settings. You can add any setting inside any filter { .. } section, although it might get just ignored there.
I always used the per-passdb/userdb, because this is what the (pre-2.4) documentation on "passwd-file" says. And yes, I found out the hard way that setting this to "%n" changes the username just for the purpose of the lookup, but afterwards it remains user@domain. My workaround currently is to use a "default_fields = user=%n" in the userdb definition, which then persists for the remainder of the session.
I updated the documentation now for auth_username_format in https://github.com/dovecot/documentation/pull/1148
So my question is: Is this the "right way" to do things, or is it better to use the global "auth_username_format" ? On a broader level, the problem I'm facing (and I can't imagine I'm the only one) is that I'd like to achieve the following behavior:
Authenticate users with plain "username", and NOT accept "user@domain" style usernames. This is the reason I'm currently not using "username_format" in the passdb definition, since this would basically allow logging in with arbitrary user@anydomain, as long as the username part exists. I'm guessing this is not what most people using plain usernames want.
When receiving incoming mail via LMTP, validate the recipient addresses, ideally using the SAME userdb that is used for authentication/login, but accept the mail only if the address is on the "correct" domain. The docs suggest using a second userdb definition (referring to the same source user data like SQL, or passwd-file or whatever) and setting "username_format = %n" there. The problem here is that, again, this would accept any arbitraty recipient address having a valid username part. So user@correctdomain and user@anyrandomdomain would be happily delivered to the same inbox. Currently, the only thing that prevents this from happening (at least in my setup) is that Postfix is configured to only accept @correctdomain mails, and reject all others. However, it would be much better - and safer - to be able to configure this within Dovecot, and not rely on external software.
2.1. There is an almost-workaround for this, using the "username_filter" parameter which allows wildcards like "*@domain" and would fail if the user doesn't match the correct domain. Regrettably, this is only supported for passdb definitions, but not for userdb's. However, LMTP and LDA validate incoming mail addresses against the userdb only, and don't perform a passdb lookup.
2.2 The only real solution I can think of is having a separate userdb for incoming mail validation (i.e. not same as the one used for login purposes) where you explicitly list all valid email addresses as user@domain, and use the (default) username_format of "%Lu". This looks like a support nightmare - you have to redundantly manage your users in two separate places, not to mention having the same "@domain" string repeated hundreds of times (and prone to typos, etc.).
Is there a more "elegant" way to achieve the above behavior (which to me seems like the most basic setup), without using dirty hacks and workarounds? Am I missing something?
How about your passdb/userdb contains only user@example.com, and then you set auth_default_domain=example.com?
Another possibility could be to add a new userdb before the real one, which drops the domain for valid domains:
userdb drop-domain { driver = passed-file passwd_file_path = /etc/dovecot/valid-domains result_success = continue fields { user = %{user | username} } }
valid-domains file would just list all valid domains, one per line
Yet another possibility could be to use %{if} to drop the domain in the existing userdb passwd-file { auth_username_format }