[Dovecot] Configuration of LMTP Reject Code
Is it possible to change the reject codes from the Dovecot LMTP agent? In particular I would like to change the "550 5.1.1 <...> User doesn't exist." to a temporary failure, since we already validate email addresses on the mail front-end, and such errors are most likely due to a temporary glitch in the user database lookup.
We use Postfix on the front-end, which is very configurable in this respect. I don't see a way to override the error code from LMTP, though, but suggestions are welcome.
Am 21.02.2011 11:05, schrieb Petter Urkedal:
Is it possible to change the reject codes from the Dovecot LMTP agent? In particular I would like to change the "550 5.1.1 <...> User doesn't exist." to a temporary failure, since we already validate email addresses on the mail front-end, and such errors are most likely due to a temporary glitch in the user database lookup.
We use Postfix on the front-end, which is very configurable in this respect. I don't see a way to override the error code from LMTP, though, but suggestions are welcome.
you may study this
unknown_hostname_reject_code (default: 450)
The numerical Postfix SMTP server response code when the hostname
specified with the HELO or EHLO command is rejected by the reject_unknown_helo_hostname restriction.
Do not change this unless you have a complete understanding of RFC 2821.
unknown_local_recipient_reject_code (default: 550)
The numerical Postfix SMTP server response code when a recipient
address is local, and $local_recipient_maps specifies a list of lookup tables that does not match the recipient. A recipient address is local when its domain matches $mydestination, $proxy_interfaces or $inet_interfaces.
The default setting is 550 (reject mail) but it is safer to
initially use 450 (try again later) so you have time to find out if your local_recipient_maps settings are OK.
Example:
unknown_local_recipient_reject_code = 450
This feature is available in Postfix 2.0 and later.
unknown_relay_recipient_reject_code (default: 550)
The numerical Postfix SMTP server reply code when a recipient
address matches $relay_domains, and relay_recipient_maps specifies a list of lookup tables that does not match the recipient address.
This feature is available in Postfix 2.0 and later.
unknown_virtual_alias_reject_code (default: 550)
The SMTP server reply code when a recipient address matches
$virtual_alias_domains, and $virtual_alias_maps specifies a list of lookup tables that does not match the recipient address.
This feature is available in Postfix 2.0 and later.
unknown_virtual_mailbox_reject_code (default: 550)
The SMTP server reply code when a recipient address matches
$virtual_mailbox_domains, and $virtual_mailbox_maps specifies a list of lookup tables that does not match the recipient address.
This feature is available in Postfix 2.0 and later.
unverified_recipient_defer_code (default: 450)
The numerical Postfix SMTP server response when a recipient address
probe fails due to a temporary error condition.
Unlike elsewhere in Postfix, you can specify 250 in order to accept
the address anyway.
Do not change this unless you have a complete understanding of RFC 2821.
This feature is available in Postfix 2.6 and later.
unverified_recipient_reject_code (default: 450)
The numerical Postfix SMTP server response when a recipient address
is rejected by the reject_unverified_recipient restriction.
Unlike elsewhere in Postfix, you can specify 250 in order to accept
the address anyway.
Do not change this unless you have a complete understanding of RFC 2821.
This feature is available in Postfix 2.1 and later.
-- Best Regards
MfG Robert Schetterer
Germany/Munich/Bavaria
On 2011-02-21, Robert Schetterer wrote:
you may study this
unknown_hostname_reject_code (default: 450)
The numerical Postfix SMTP server response code when the hostname
specified with the HELO or EHLO command is rejected by the reject_unknown_helo_hostname restriction.
Do not change this unless you have a complete understanding of RFC 2821.
I don't see how unknown_hostname_reject_code or reject_unknown_helo_hostname will help us here.
unknown_local_recipient_reject_code (default: 550)
The numerical Postfix SMTP server response code when a recipient
address is local, and $local_recipient_maps specifies a list of lookup tables that does not match the recipient. A recipient address is local when its domain matches $mydestination, $proxy_interfaces or $inet_interfaces.
Yes, am aware unknown_local_recipient_reject_code, and that would be what we wanted if we were running Postfix on the mail-storage server. But we deliver mail directly from the mail front-end to the Dovecot LMTP agent on the mail store.
I forgot to mention that we use Dovecot 2.0.9.
On Mon, 2011-02-21 at 11:05 +0100, Petter Urkedal wrote:
Is it possible to change the reject codes from the Dovecot LMTP agent? In particular I would like to change the "550 5.1.1 <...> User doesn't exist." to a temporary failure, since we already validate email addresses on the mail front-end, and such errors are most likely due to a temporary glitch in the user database lookup.
What userdb are you using? Temporary userdb lookup glitches should cause Dovecot to return a temporary error failure, not "user doesn't exist"..
We use Postfix on the front-end, which is very configurable in this respect. I don't see a way to override the error code from LMTP, though, but suggestions are welcome.
I don't really like adding settings that have very few users..
On 2011-02-22, Timo Sirainen wrote:
On Mon, 2011-02-21 at 11:05 +0100, Petter Urkedal wrote:
Is it possible to change the reject codes from the Dovecot LMTP agent? In particular I would like to change the "550 5.1.1 <...> User doesn't exist." to a temporary failure, since we already validate email addresses on the mail front-end, and such errors are most likely due to a temporary glitch in the user database lookup.
What userdb are you using? Temporary userdb lookup glitches should cause Dovecot to return a temporary error failure, not "user doesn't exist"..
We are using auth-system.conf.ext with
passdb {
driver = pam
}
userdb {
driver = passwd
args = home=/srv/mail/nbi.ku.dk/%1n/%n mail=maildir:~/Maildir
}
We also have a post-login script which may override MAIL if the mail directory does not exist. This is on Red Hat 6 with the new sssd-based user database and authentication.
We only have two rejects of this type, 9 s apart, since we switched to the new mail server a week ago, so it's a rare event.
We use Postfix on the front-end, which is very configurable in this respect. I don't see a way to override the error code from LMTP, though, but suggestions are welcome.
I don't really like adding settings that have very few users..
I understand, it's really a workaround. A global directive to turn all permanent errors into temporary ones, would do as well, since any error from LMTP is a potential issue we want to know about. I'm not sure whether that's any nicer from your point of view.
On Tue, 2011-02-22 at 11:02 +0100, Petter Urkedal wrote:
userdb { driver = passwd args = home=/srv/mail/nbi.ku.dk/%1n/%n mail=maildir:~/Maildir }
The problem with passwd is that it can't separate "user doesn't exist" from "temporary error". http://wiki2.dovecot.org/UserDatabase/NSS can separate these, but it hasn't been tested much..
We use Postfix on the front-end, which is very configurable in this respect. I don't see a way to override the error code from LMTP, though, but suggestions are welcome.
I don't really like adding settings that have very few users..
I understand, it's really a workaround. A global directive to turn all permanent errors into temporary ones, would do as well, since any error from LMTP is a potential issue we want to know about. I'm not sure whether that's any nicer from your point of view.
Well, there aren't really any other permanent errors.. Quota already has quota_full_tempfail setting.
On 2011-02-22, Timo Sirainen wrote:
On Tue, 2011-02-22 at 11:02 +0100, Petter Urkedal wrote:
userdb { driver = passwd args = home=/srv/mail/nbi.ku.dk/%1n/%n mail=maildir:~/Maildir }
The problem with passwd is that it can't separate "user doesn't exist" from "temporary error". http://wiki2.dovecot.org/UserDatabase/NSS can separate these, but it hasn't been tested much..
I can see the issue with getpwnam is described in its Linux man-page:
The formulation given above under "RETURN VALUE" is from POSIX.1-2001.
It does not call "not found" an error, and hence does not specify what
value errno might have in this situation. But that makes it impossi-
ble to recognize errors. One might argue that according to POSIX
errno should be left unchanged if an entry is not found. Experiments
on various Unix-like systems show that lots of different values occur
in this situation: 0, ENOENT, EBADF, ESRCH, EWOULDBLOCK, EPERM and
probably others.
Since this is an issue with getpwnam (even the POSIX standard, apparently), maybe the assumption about why getpwnam fails can be passed directly to the userdb module? I can see that userdb_static_template_build accepts arbitrary key=value pairs, so how about something like
userdb {
driver = passwd
args = ... tempfail=1
}
Anyway, thanks for the suggestion about NSS. We may also use LDAP directly, though that means we bypass the nslcd (nscd) cache, which is a bit unfortunate. So I think we can manage, but you have my vote for adding a workaround for the getpwnam issue.
On 2011-02-22, Timo Sirainen wrote:
On Tue, 2011-02-22 at 11:02 +0100, Petter Urkedal wrote:
userdb { driver = passwd args = home=/srv/mail/nbi.ku.dk/%1n/%n mail=maildir:~/Maildir }
The problem with passwd is that it can't separate "user doesn't exist" from "temporary error". http://wiki2.dovecot.org/UserDatabase/NSS can separate these, but it hasn't been tested much..
We use Postfix on the front-end, which is very configurable in this respect. I don't see a way to override the error code from LMTP, though, but suggestions are welcome.
I don't really like adding settings that have very few users..
I understand, it's really a workaround. A global directive to turn all permanent errors into temporary ones, would do as well, since any error from LMTP is a potential issue we want to know about. I'm not sure whether that's any nicer from your point of view.
Well, there aren't really any other permanent errors.. Quota already has quota_full_tempfail setting.
I think there is a better solution. It seems that getpwnam_r is POSIX and does the right thing. The attached patch adds a feature-check for getpwnam_r and, if present, uses it in userdb-passwd.c in place of the problematic getpwnam. I've not some light testing on a non-production server.
On Thu, 2011-03-17 at 14:16 +0100, Petter Urkedal wrote:
I think there is a better solution. It seems that getpwnam_r is POSIX and does the right thing.
Oh, weird. I knew about that function but I never realized it fixed the error handling problem. Also everything I saw discussing the getpwnam() error problems never bothered to mention getpwnam_r().
The attached patch adds a feature-check for getpwnam_r and, if present, uses it in userdb-passwd.c in place of the problematic getpwnam. I've not some light testing on a non-production server.
I think I'll do a bit larger change here that replaces all getpwnam(), getpwuid() and maybe other calls. Dovecot doesn't need thread-safe getpw*() so I can do an easier to use wrapper function.
On 2011-03-17, Timo Sirainen wrote:
On Thu, 2011-03-17 at 14:16 +0100, Petter Urkedal wrote:
I think there is a better solution. It seems that getpwnam_r is POSIX and does the right thing.
Oh, weird. I knew about that function but I never realized it fixed the error handling problem. Also everything I saw discussing the getpwnam() error problems never bothered to mention getpwnam_r().
Yeah, that's odd. I don't have the POSIX standard, but my reading a few of the top Google matches for "getpwnam_r POSIX", suggests it returns 0 on "not found". My testing is for RHEL-6 using sssd.
The attached patch adds a feature-check for getpwnam_r and, if present, uses it in userdb-passwd.c in place of the problematic getpwnam. I've not some light testing on a non-production server.
I think I'll do a bit larger change here that replaces all getpwnam(), getpwuid() and maybe other calls. Dovecot doesn't need thread-safe getpw*() so I can do an easier to use wrapper function.
Sounds good.
On Thu, 2011-03-17 at 14:49 +0100, Petter Urkedal wrote:
I think I'll do a bit larger change here that replaces all getpwnam(), getpwuid() and maybe other calls. Dovecot doesn't need thread-safe getpw*() so I can do an easier to use wrapper function.
Sounds good.
Added to hg: http://hg.dovecot.org/dovecot-2.0/rev/7f5735ab7c35 http://hg.dovecot.org/dovecot-2.0/rev/02829f7f79c7
participants (4)
-
Petter Urkedal
-
Petter Urkedal
-
Robert Schetterer
-
Timo Sirainen