Juerd Waalboer skribis 2007-12-07  1:53 (+0100):
> I'm going to email all the authors, as far as I can find their
> addresses, so they have a chance to respond to my critique.

Instead of complaining about lack of qmail support, I've decided to
simply recategorize things into less offending "support levels". After
all, many weren't even written with qmail in mind. I'm including them
anyway, because they might still be viable alternatives for some
systems.

Attached is the draft POD of what I want to release with my
Qmail::Deliverable module, as Qmail::Deliverable::CPAN. Thanks to the
people who've replied to my feature matrix, it's more complete than
that.

Any comments?
-- 
Met vriendelijke groet,  Kind regards,  Korajn salutojn,

  Juerd Waalboer:  Perl hacker  <[EMAIL PROTECTED]>  <http://juerd.nl/sig>
  Convolution:     ICT solutions and consultancy <[EMAIL PROTECTED]>
=head1 NAME

Qmail::Deliverable::Comparison - Overview of recipient checkers for qmail

=head1 SYNOPSIS

    There is more than one way to do it
    -- Larry Wall

=head1 DESCRIPTION

Qmail::Deliverable is not the only software that checks if a local qmail user
exists. Other solutions have existed for a long time, but after evaluating
them, I felt more comfortable rolling my own.

While exploring the existing options, I learned their strengths and weaknesses.
I revisited them all again after writing Q::D, and now share my findings.

It is most amazing, though, that no other solution provides a re-usable
library. One comes very close, by providing a daemon that you can query via a
very simple protocol. Q::D has both a library and a daemon. Also, good support
for dot-qmail files like .qmail-ext-default, is rare, but absolutely essential
for interoperability with, for example, ezmlm.

The main problem with checking address validity during the SMTP transaction, is
one of permissions and separation. Root access is required to peek into home
directory of system users. Privilege separation is one of the classic strengths
of qmail, and it would be unwise to break that. Additional mechanisms are needed
to keep things separate, but as you can see, this wheel has been invented plenty
of times.

Qmail's modular design made replacing the SMTP daemon very simple, and because
development on qmail stopped with version 1.03 in 1993, several replacement
daemons have been released. There is a patch for qmail-smtpd, to make it
extensible with plugins, called qmail-spp. Then, there is a daemon called
magic-smtpd. My favourite, however, is the very extensible Perl based qpsmtpd.

http://cr.yp.to/qmail.html

http://qmail-spp.sourceforge.net/

http://www.linuxmagic.com/opensource/magicmail/magic-smtpd

http://smtpd.develooper.com/

=head2 Using qmail-local logic

Any solution that is to integrate well with existing qmail systems, has to copy
the delivery logic that qmail itself uses.

They need to use the qmail control files L<locals> and C<virtualdomains>, the
L<users/assign> text file or CDB, and some mechanism to detect local users
(getpw).

Vpopmail support can be added by checking dot-qmail files for the presence of
C<vdeliver> and C<bounce-no-mailbox>. In a similar fashion, fastforward and
bouncesaying can be supported at SMTP level. Bouncesaying is used by Plesk.

=head2 List of patches and plugins for qmail SMTP daemons

I've divided the solutions into support levels. Level 0 supports only lists
of specific email addresses, level 3 solutions are (almost) drop-in compatible
with existing setups.

Before installing any solution, carefully read the documentation (if there is
any) and/or source code to determine if everything you need is sufficiently
supported.

As you know, programmers start counting at 0 :)

=head3 Level 0

Level 0 solutions are limited to checking specific [EMAIL PROTECTED], without 
support
for catch-all addresses.

=over 4

=item db/user plugin for qpsmtpd

Written in Perl, checks against an SQL database

http://dienstleistung-kultur.de/qpsmtpd/

=item magic-smtpd, support built in

Written in C, checks against a Berkely DB.

http://www.linuxmagic.com/opensource/magicmail/magic-smtpd

=item aliases plugin for qpsmtpd

Written in Perl, checks against a text file with aliases and expands them.

http://www.hjp.at/projekte/qpsmtpd/aliases/aliases_check.html

=item check_user_cdb plugin for qpsmtpd

Written in Perl, checks against a CDB

http://ankh-morp.org/~vetinari/projects/qpsmtpd/

=item check_vuser plugin for qpsmtpd

Written in Perl, checks against a directory tree.

http://ankh-morp.org/~vetinari/projects/qpsmtpd/

=back

=head3 Level 1

Level 1 solutions are limited to checking [EMAIL PROTECTED] and also provide 
support
for catch-all domains ([EMAIL PROTECTED]) and sometimes catch-all extensions
([EMAIL PROTECTED]), but not specific user extensions
([EMAIL PROTECTED]).

=over 4

=item goodrcptto patch for qmail-smtpd

Written in C, checks against a text file or CDB.

http://web.netdevice.com:9080/qmail/patch/

=item validrcppto patch for qmail-smtpd

Written in C, checks against a text file.

http://www3.sympatico.ca/humungusfungus/code/validrcptto.html

=item validrcptto.cdb patch for qmail-smtpd

Written in C, checks against a CDB.

http://qmail.jms1.net/patches/validrcptto.cdb.shtml

=item check_dns_user plugin for qpsmtpd

Written in Perl, checks against a DNS zone. Supports catch-all domains if you
use wildcard hostnames in the zone.

http://ankh-morp.org/~vetinari/projects/qpsmtpd/

=item check_goodrcptto plugin for qpsmtpd

Written in Perl, checks against a text file. Supports catch-all extensions, but
not specific extensions.

http://www.openfusion.com.au/labs/qpsmtpd/check_goodrcptto

=item qmail-ldap suite

Written in C, checks against an LDAP database.

http://www.qmail-ldap.org/

=back

=head3 Level 2

Level 2 solutions do everything that level 1 solutions do, but also provide
support for prefixed wildcards, like [EMAIL PROTECTED] Level 2 is the
minimum level of support needed for good integration with existing qmail
installations and things like EZMLM, but may still require a certain specific
setup like a user database or vpopmail.

Dot-qmail files belonging to users may not be accessible to the SMTP daemon.
This limitation can be lifted by pregenerating a list or database, by using a
special purpose setuid root program, or a daemon that runs as root.

=over 4

=item vpopmail_check_recipient-wm plugin for qmail-spp

Written in sh, checks against vpopmail executables and dot-qmail.

Supports .qmail-default, of course handling vpopmail's vdeliver, and has hard
coded support for ezmlm, and resulting from the way that was written, limited
support for .qmail-ext-default. It assumes a strictly vpopmail-ized setup with
no local users or local aliases. Requires that the vpopmail utilities are
setuid, including vuserinfo which displays user passwords, clear text if
available. That makes it unsafe for use on any system that has local users
other than the system administrators.

http://www.maiers.de/qmail/art38,71.html

=item local_check_recipient plugin for qmail-spp

Written in sh, checks against a directory tree and dot-qmail.

This is like vpopmail_check_recipient, but for local users only. It does not
actually query /var/qmail/users/assign or getpw for home directories, but
requires /home/username, where username is directly taken from the email
address. Probably needs to be suid root to function correctly.

http://www.maiers.de/qmail/art38,72.html

=item check_recipient plugin for qmail-spp

Written in Perl, checks against partial qmail-local logic.

Uses virtualdomains and users/assign logic, but does not query getpw for local
users not listed there. With its limited set of allowed characters, it would
immediately disqualify a local-part like the C<#####> in my email address.
Having ~alias/.qmail-default turns everything into one big catch all with this
script, disregarding users/assign logic and .qmail-ext for local users.
Supports .qmail-default, but not .qmail-ext-default.

Cannot be used for relay servers, because a bug causes it to disallow all
remote addreses. (It should read locals and virtualdomains to find out if a
domain is local).

Not networked.

http://perolo.vantage.at/qmail-spp/check_recipient.pl

=item vpopmail-check-user script for magic-smtpd

Written in sh, checks against vpopmail executables.

Appears to be a proof of concept only, since it does not support domain
catch-alls. (If I were strict, it wouldn't even classify as level 1.)
Has to run setuid vpopmail.

http://www.linuxmagic.com/opensource/magicmail/magic-smtpd

=item rcpt_regexp plugin for qpsmtpd.

Written in Perl, checks against a text file with regular expressions or static
strings.

http://ankh-morp.org/~vetinari/projects/qpsmtpd/

=item rcpt_ldap plugin for qpsmtpd

Written in Perl, checks against an LDAP database. Supports extensions if you
craft an ldap filter that does.

http://ankh-morp.org/~vetinari/projects/qpsmtpd/

=back

=head3 Level 3

Level 3 solutions do everything that level 2 solutions do, but fully support
qmail-local logic, and can be added to existing mailservers without changing
their setup. This does, of course, assume that the mail setup is based on
qmail's structure and not a heavily patched system that changes the delivery
rules, as is the case with qmail-ldap (although that has its own recipient
checking).

=over 4

=item check_delivery plugin for qpsmtpd

Written in Perl, checks against qmail-local logic using a suid root program.

No longer developed or maintained. The documentation says that .qmail-default
files are only fully supported for the alias user, but there does seem to be
code for supporting .qmail-ext-default.

It requires an external suid root program, dot-qmail-exists.pl, that seems to
have vanished from the web. Even a re-implementation because the original could
not be found, is either no longer there, or very well hidden.

http://www.nntp.perl.org/group/perl.qpsmtpd/2005/06/msg3174.html

http://www.redhotpenguin.com/check_delivery

=item qmail-realrcptto patch for qmail-smtpd

Written in C, checks against qmail-local logic.

Runs under the same user as qmail-smtpd and as such may not be able to access
users' files. It does not have any special support for vpopmail, fastforward,
or bouncesaying, i.e. all .qmail-default files are considered catch all.

http://code.dogmap.org/qmail/

=item qmail-verify daemon + patch for qmail-smtpd

Written in C, checks against qmail-local logic and dot-qmail using a daemon.

In hindsight, my solution was probably mostly inspired by this nice piece of
software. A light weight daemon works together with a patched qmail-smtpd, and
they communicate through UDP. A single bit, 0 or 1, determines the fate of the
current message. While possibly susceptible to spoofing and race conditions,
that's unlikely because all the malicious hacker can probably accomplish, is
that email is rejected.

Unfortunately it has no support for vpopmail, bouncesaying, or fastforward.

This solution is networked and lets you pick the server based on the connecting
host. That's almost sufficient for using the client on a mail hub, which
requires some kind of domain to qmail-verify host mapping.

http://www.nwdb.co.uk/email/qmail-verify.html

=item check_validrcptto_cdb plugin for qpsmtpd

Written in Perl, checks against a CDB. Together with mkvalidrcptto, qualifies
as level 3.

http://robinbowes.com/projects/check_validrcptto_cdb

=item check_qmail_deliverable plugin for qpsmtpd

Written in Perl, checks against qmail-local logic and dot-qmail using a daemon.

This is the plugin that comes with the Qmail::Deliverable distribution. It uses
the bundled qmail-deliverabled daemon which is like qmail-verify, but heavier.
It inherits all supported features from Qmail::Deliverable::deliverable, which
means that it works well with vpopmail and bouncesaying, but not fastforward.

Its networking can be configured to look in the smtproutes configuration file
to find the server to query, so it can easily be used on a mail hub.

This is the only solution that I know of, that separates the core functionality
and provides it as a software library -- in this case, a Perl module. This
makes writing a similar plugin for qmail-spp or magic-smtpd relatively simple.

http://search.cpan.org/~juerd/Qmail-Deliverable/

=back

=head3 Unknown support level

=over 4

=item chkrcptto plugin for qmail-spp

Closed source, distributed with Plesk. I have no idea how well it would work
with a non-plesk setup.

http://www.swsoft.com/plesk/

=back

=head2 Recipient list generators

These programs read your qmail configuration files and generate a list of valid
recipients.

=over 4

=item mkvalidrcptto

Written in Perl, generates according to qmail-local logic and dot-qmail.

Has support for vpopmail and fastforward, but not for bouncesaying. It
understands domain aliases, but keeps .qmail-ext-default as [EMAIL PROTECTED],
which only the check_validrcptto_cdb plugin for qpsmtpd handles.

http://qmail.jms1.net/scripts/mkvalidrcptto.shtml

=back

=head1 MORE?

If you know of other alternatives for qmail that reduce backscatter by checking
if a recipient is valid, please inform me.

I've contacted all authors if I could find contact information, but if you
wrote one of these tools and did not get my message, and you wish to inform me
that I made a mistake, please do contact me.

=head1 ACKNOWLEDGEMENTS

Thanks to all the authors of the tools listed on this page. I've used them for
inspiration while writing my solution, and their software has already prevented
a lot of CPU usage, memory consumption, queue capacity, data traffic, and the
annoyance that spam backscatter causes.

=head1 AUTHOR

Juerd Waalboer <[EMAIL PROTECTED]>

=head1 SEE ALSO

L<Qmail::Deliverable>, L<http://web.netdevice.com:9080/qmail/rcptck/>

Reply via email to