qpsmtpd Wiki


You are here: start » plugins


You are currently not logged in! Enter your authentication credentials below to log in. You need to have cookies enabled to log in.


You don't have an account yet? Just get one: Register

Forgotten your password? Get a new one: Set new password

qpsmtpd Plug-ins

Plug-ins are the heart of qpsmtpd, but as of today, there is no good central repository for them. The qpsmtpd home page points to three locations: Peter J. Holzer's page and Gavin Carr's page, but neither of these are complete. Thus, we should try and make a more complete collection of plug-ins here.

Some plug-ins from here and some additional plug-ins can be found in the SVN contrib dir.

Generic Plug-ins



This plugin allows you to deny messages based upon the Subject: headers of the mails.



Reads the badmailfrom configuration like qmail-smtpd does. From the qmail-smtpd docs:

Unacceptable envelope sender addresses. qmail-smtpd will reject every recipient address for a message if the envelope sender address is listed in badmailfrom. A line in badmailfrom may be of the form @host, meaning every address at host.

They might be extinct by now, but in the past some dumb SMTP clients would not understand a rejection during MAIL FROM, so the plugin saves the rejection until the RCPT stage.

check_badmailfrom configuration

The check_badmailfrom plugin is configured by the file badmailfrom.

The purpose of the plugin is to reject every recipient address for a message if the envelope sender address is listed.




Much like the similar check_badmailfrom, this plugin references both the FROM: and TO: lines, and if they both are present in the badmailfromto config file (a tab delimited list of FROM/TO pairs), then the message is blocked as if the recipient (TO) didn't exist. This is specifically designed to not give the impression that the sender is blocked (good for cases of harassment).

Based heavily on check_badmailfrom.



The purpose of the plugin is to reject a message if the envelope recepient address is listed.

This plugin checks the badrcptto config (like badmailfrom for rcpt address). See also check_verybadrcptto

check_badrcptto configuration

The check_badrcptto plugin is configured by the file badrcptto.




This plugin checks the badrcptto_patterns config. This allows special patterns to be denied (e.g. percent hack, bangs, double ats).

Configuration file: config/badrcptto_patterns

Patterns are stored in the format pattern\sresponse, where pattern is a Perl pattern expression. Don't forget to anchor the pattern if you want to restrict it from matching anywhere in the string.

qpsmtpd already ensures that the address contains an @, with something to the left and right of the @.



Make sure both From and Date headers are present, and do optional range checking on the Date header

Rejects messages that do not have a From or Date header or are completely empty.

Can also reject messages where the date in the Date header is more than some number of the days in the past or future.

Takes one optional parameter, the number of days in the future or past beyond which to reject messages. (The default is to not reject messages based on the date.)



Checks to see if the remote host starts talking before we've issued a 2xx greeting. If so, we're likely looking at a direct-to-MX spam agent which pipelines its entire SMTP conversation, and will happily dump an entire spam into our mail log even if later tests deny acceptance.

Depending on configuration, clients which behave in this way are either immediately disconnected with a deny or denysoft code, or else are issued this on all mail/rcpt commands in the transaction.



This plugin detects loops by counting “Received” and “Delivered-To” header lines. It's a kluge but it duplicates what qmail-smtpd does, and it does at least prevent messages from looping forever.



This plugin checks the norelayclients config file to see if relaying is denied.

This allows specific clients, such as the gateway, to be denied relaying, even though they would be allowed relaying by the relayclients file.

check_norelay configuration

The check_norelay plugin is configured by the file norelayclients.

# no relay for specific IP
# no relay for 1 subnet



This plugin checks the relayclients config file and $ENV{RELAYCLIENT} to see if relaying is allowed.

check_relay configuration

The check_relay plugin is configured by the file relayclients.

# Format is IP, or IP part with trailing dot
# e.g. "", or "192.168."



Check a HELO message delivered from a connecting host. Reject any that appear in the badhelo config – e.g. yahoo.com and aol.com, which neither the real Yahoo or the real AOL use, but which spammers use rather a lot.

Add domains or hostnames to the badhelo configuration file; one per line.

check_spamhelo configuration

The check_spamhelo plugin is configured by the file badhelo.


It is also a good idea to add various variations of your own domain and host name to this file.


One problem with the qmail MTA is that is doesn't validate the recipient address until it attempts local delivery.

This plugin validates recipient addresses given in the RCPT TO: command of the SMTP conversation against a cdb file containing valid email addresses. Invalid addresses are rejected without first being being accepted for local delivery.

The cdb file can be generated in a variety of ways. I personally use John Simpson's mkvalidrcptto script. In fact, this plugin was inspired by his validrcptto.cdb patch for qmail.

Get it here :http://robinbowes.com/projects/check_validrcptto_cdb

The plugin contains extensive documentation. To read it, download the file and use:

perldoc check_validrcptto_cdb


The perl module Qmail::Deliverable on CPAN includes a qpsmtpd plugin named check_qmail_deliverable. The perl module has a daemon (qmail-deliverabled) that runs on the server. The qpsmtpd plugin queries the daemon, which in turn does realtime checks to see if the email address is deliverable or not. It works great.

This plugin would be an alternative to check_validrcptto_cdb above, which requires you to install a separate script and cron job to keep a CDB of valid users up-to-date. This requires no such updates because it does real time deliverability checks. The author of the plugin has create an excellent comparison of the deliverable scripts/plugins/solutions.



This plugin validates recipient addresses given in the RCPT TO: command of the SMTP conversation against a special DNS zone that you create. This is useful if you have several servers running qpsmtpd and you want all of them to have your user list.



Disconnect the client if it sends too many unrecognized commands. Good for rejecting spam sent through open HTTP proxies.

count_unrecognized_commands configuration

The count_unrecognized_commands plugin is configured by the file plugins.

# Defaults to 4
count_unrecognized_commands 4



I recommend to download the plug-in from one of the CPAN mirrors: http://search.cpan.org/~mpelzer/ The archive contains not only the plug-in, but also the config-file and example templates in german and english!

This plug-in is a whitelist which automatically maintains itself based on well known and widely used Captcha authentication where a user must identify characters within an image. You can define one ore more mail-domains or single email-addresses that will be protected by this auto-whitelist plugin. If the sender of an email is not whitelisted, he will get an automatic reply-mail which includes a Captcha image which he can solve in his answer-mail. If the Captcha-string is correct, he will be automatically added to the whitelist, otherwise he gets a new Captcha via email until he succeed or failed for 5 times (then he will be blacklisted).

Use this plug-in to efficiently protect your emails against Spam, because Spam-senders will never receive the Captcha mail (because they use faked email addresses) or if they do, they will never answer it. Your business contacts, friends and family will solve the Captcha because it's easy and they really want to get in contact with you. If you add all of your friends emails to the whitelist up-front, they will never need to solve the Captcha anyway.



The dns_whitelist_soft plugin allows selected host to be whitelisted as exceptions to later plugin processing. It is strongly based on the original dnsbl plugin as well as Gavin Carr's original whitelist_soft plugin. It is most suitable for multisite installations, so that the whitelist is stored in one location and available from all.



Checks the IP address of connecting peers against DNS-based blacklists such as ORDB or the SpamHaus SBL.

dnsbl configuration

The dnsbl plugin is configured by the file dnsbl_zones, dnsbl_allow and dnsbl_rejectmsg.



Maybe a link to listing policies here?


This needs an explanation, especially the last line is no good for most people


If you think you have been blocked in error, then please forward
this entire error message to your ISP so that they can fix their problems.
The next line often contains a URL that can be visited for more information.
Other DNSBL lists

The OpenRBL project has an interesting list of available (and historical) DNS blacklists.


greylisting Plugin to implement the 'greylisting' algorithm proposed by Evan Harris in http://projects.puremagic.com/greylisting/. Greylisting is a form of denysoft filter, where unrecognised new connections are temporarily denied for some initial period, to foil spammers using fire-and-forget spamware, http_proxies, etc.

Greylisting adds two main features: it tracks incoming connections using a triplet of remote IP address, sender, and recipient, rather than just using the remote IP; and it uses a set of timeout periods (black/grey/white) to control whether connections are allowed, instead of using connection counts or rates.

This plugin allows connection tracking on any or all of IP address, sender, and recipient (but uses IP address only, by default), with configurable greylist timeout periods. A simple dbm database is used for tracking connections, and relayclients are always allowed through. The plugin supports whitelisting using the whitelist_soft plugin (optional).



An example plugin to retrieve configuration via HTTP.



This plugin allows you to attach to milter filters (yes, those written for sendmail) as though they were qpsmtpd plugins.

In order to do this you need the Net::Milter module from CPAN.

To be continued

TyskJohan 2006/02/07 08:43



The purpose of the plugin is to deny mail based sender’s domains who don’t obey RFCs (Request for Comments). Note that it checks the right-hand side (rhs) of the envelope sender, not the domain name of the connecting peer.

rhsbl configuration

The rhsbl plugin is configured by the file rhsbl_zones.

dsn.rfc-ignorant.org		does not accept bounces. This violates RFC 821/2505/2821 http://www.rfc-ignorant.org/
postmaster.rfc-ignorant.org	does not have a working postmaster address http://www.rfc-ignorant.org/
abuse.rfc-ignorant.com		does not accept mail for user abuse. This violates RFC 2142 http://www.rfc-ignorant.org/ 
bogusmx.rfc-ignorant.com	has bogus MX records. This violates RFC 1035/3330/2181 http://www.rfc-ignorant.org/
rhsbl.sorbs.net			found in rhsbl.sorbs.net

There is also a list at whois.rfc-ignorant.org for domains that have invalid contact data in the WHOIS system; however the list policy also covers WHOIS servers who, by default, do not provide the contact information on record. If you use that list, you will not be able to receive any mail from Germany (.de) for example.

Other RHSBL lists

The OpenRBL project has an interesting list of available (and historical) RHS blacklists.


The spamassassin plugin is configured by the file plugins.

The purpose of the plugin is to check the mail using spamd daemon from the SpamAssassin package.

spamassassin configuration
# rejects mails with a SA score higher than 20 and munges the subject
# of the score is higher than 10.
spamasssasin  reject_threshold 20  munge_subject_threshold 10



This plugin allows you to distribute email address which will auto-destruct. There are two ways of having addresses destruct:

  1. Only accept a given number of delivery attempts
  2. Only accept mail prior to a given date.



This plugin allows you to block incoming connection based on a blacklist and whitelist where you can define cities and countries which should be blocked or allowed to pass through. It's using the Geo-City-Database from maxmind.com - they offer a commercial and also a free version of their geo-lookup DB. See the documentation inside the plugin for more details and the installation howto.



This plug-in checks wether the recipient of an email is known to the local alias file or not.

Authentication plug-ins

Also see the section on SMTP AUTH and qpsmtpd


The auth_vpopmail_sql plug-in uses a vpopmail SQL database for authentication.

auth_vpopmail_sql configuration

The auth_vpopmail_sql plugin is configured by the file plugins.

The purpose of the plugin is to authenticate vpopmail users directly against a standard vpopmail MySQL database. If using CRAM-MD5, it also requires that vpopmail be built with the recommended –enable-clear-passwd=y option, because there is no way to compare the crypted password.


The auth_vpopmail_sql plugin should be modified according to vpopmail MySQL database setting.

    my $connect  = "dbi:mysql:dbname=vpopmail:host=";
    my $dbuser   = "changeVpopmailUser";
    my $dbpasswd = "changeVpopmailPassword";

    my $dbh = DBI->connect( $connect, $dbuser, $dbpasswd );
    $dbh->{ShowErrorStatement} = 1;

Review and change variables $connect, $dbuser and $dbpasswd using favorite editor


The authcheckpassword plug-in works with djb's (or any other) checkpassword function.


The authpam plug-in makes use of PAM to authenticate users.


The auth_smtpd plug-in allows authentication by an SMTP server, you need to specify the server name and port in the plugins configuration file.


The auth_imap plug-in allows authentication by an IMAP server, you need to specify the server in the plugins configuration file.


The restrict_submission plug-in only allows connections to specified ports from authorised users. Can be used to restrict use of the submission port to authorised users.

Logging plug-ins



A simple example of a plugin that logs all incoming mail to a file. Useful for debugging other plugins or keeping an archive of things.



This plugin uses apache's logging mechanism… obviously only useful for Apache::Qpsmtpd

Queue plug-ins


http-forward This plugin allows you to send your email to a HTTP web-server using HTTP or HTTPS POST. Could be useful if you want to transport your received emails out through a firewall or if you want to make a “backup” of your emails using a remote CGI script. The plugin is using the Perl Module LWP::UserAgent - install it via 'perl -MCPAN -e shell' if you dont have it.


zmailer-queue – This plugin delivers mails to a zmailer spool dir

Anti-Virus plug-ins


The purpose of the aveclient plug-in is to scan incoming mail with the Kaspersky 5.x server-suite AV scanner and can block infected messages.

aveclient configuration

The aveclient plugin is configured by the file plugins.

# run the Kaspersky 5.x server-suite virus checking plugin


The purpose of the bitdefender plug-in is to scan incoming mail with the BitDefender Linux Edition scanner, and can reject or flag infected messages.

bitdefender configuration

The bitdefender plug-in is configured by the file plugins.

# BitDefender Linux Edition scanner
virus/bitdefender deny_viruses yes 


The purpose of the check_for_hi_virus is to check for the presence of the Hi virus.


The purpose of the clamav plug-in is to scan incoming mail with the ClamAV AV scanner, and can reject or flag infected messages.

clamav configuration

The clamav plug-in is configured by the file plugins.

# run the clamav virus checking plugin
virus/clamav clamscan_path=/usr/local/bin/clamdscan action=reject max_size=2097152 tmp_dir=/home/smtpd/qpsmtpd/tmp


The purpose of the clamdscan plug-in is to scan incoming mail with the ClamAV AV scanner, clamd and can reject or flag infected messages.

clamdscan configuration

The clamdscan plug-in is configured by the file plugins.

# run the clamdscan virus checking plugin
virus/clamdscan deny_viruses yes clamd_socket /home/smtpd/qpsmtpd/tmp/clamd


The purpose of the hbedv plug-in is to scan incoming mail with the H+BEDV AV scanner and can deny infected messages.

hbedv configuration

The virus/hbedv plug-in is configured by the file plugins.

# H+BEDV AV scanner
virus/hbedv hbedvscanner /usr/bin/antivir 


The purpose of the kavscanner plug-in is to scan incoming mail with the Kasperski A/V scanner and can deny infected messages.

kavscanner configuration

The kavscanner plug-in is configured by the file plugins.

# run the kasperski virus checking plugin


The purpose of the sophie plug-in is to scan incoming mail with the SOPHOS scan daemon, sophie and can reject or flag infected messages.

sophie configuration

The sophie plug-in is configured by the file plugins.

# SOPHOS scan daemon
virus/sophie deny_viruses yes 


The purpose of the uvscan plug-in is to scan incoming mail with the McAfee commandline A/V scanner, uvscan and can reject or flag infected messages.

uvscan configuration

The uvscans plug-in is configured by the file plugins.

# McAfee commandline A/V scanner
virus/uvscan deny_viruses yes

Other plug-ins

IDN support


Adds IDN (Internationalizing Domain Names - domains with non-7bit-ASCII chars) support for outgoing emails. The domain-part of the outgoing email address is being checked for UTF-8 characters and converted into ACE using puny-code.



Check recipients of a bounce mail against a list of regular expressions



DomainKey signature verification plugin for qpsmtpd. Requires Mail::DomainKeys and Crypt::OpenSSL::RSA libraries.


domainkeys_sign to sign outgoing mail with DomainKeys signatures.



This plugin accepts mail only for recipients in the goodrcptto config file (i.e. like badrcptto, but whitelisting). Supports recipient username extension stripping, and both domain ('@domain.com') and username (bare 'postmaster') wildcard entries in the config file.

Useful where something like check_delivery is overkill or not an option (e.g. relays, bastion hosts).



This plugin checks the verybadrcptto config (like badmailfrom for rcpt address) and will stop the e-mail being sent to any of the RCPT TO addresses (unlike check_badrcptto which only stops e-mail going to the matching badrcptto addresses)



The whitelist_soft plugin allows selected hosts or senders or recipients to be whitelisted as exceptions to later plugin processing. It is a more conservative variant of Devin Carraway's whitelist plugin.



The whitelist plugin allows portions of the SMTP conversation to override other plugins which might otherwise reject mail from a known-good sender, or where spam detection is less important than other factors.


nodialup is a crude attempt at stopping direct-connects from DSL and dialup lines.


denybounce is a plugin to make sure that bounces are not accepted for addresses that never send mail.


hashcash – a plugin to add HashCash to messages.


spamtrap – a plugin to trap spam, and deliver it to other places than the spammer intended.



The charset plugin allows or denies selected character sets (such as iso-8859-1, us-ascii, koi8-r, big5, …). It checks the Content-Type: header for a text/* MIME Type and acts on the given charset. This plugin requires the Qpsmtpd::ContentType module found in the same place as the plugin.



This is a simple module written as a test module for the pre- and post-connection hooks. It logs the time of a SMTP connection.



This plugin looks up users in an LDAP Directory, it uses the 'ldap_rcpt_filter' to match the recipient address. The default 'ldap_rcpt_filter' assumes the qmail.schema from qmail-ldap.org (inside the diff against qmail). Any filter will work, as long as at least one result is returned. Requires the Net::LDAP modules.



Looks up Rcpt addresses in a local aliases file, rejects unknown addresses, expands aliases (preserving the detail string) and sets per rcpt options (which can be used by other modules).



(Note: This plugin used to be called rcpt_ok, but the distribution now contains a different plugin with this name)

This module simply returns OK for each rcpt request. It is meant to be called after other plugins which return DECLINED for addresses which are ok (e.g, the aliases plugin).



The spambayes plug-in is designed to process email through SpamBayes (http://spambayes.sourceforge.net/). It is based on Devin Carraway’s spamassassin_spamc plug-in. Currently it just processes email through sb_filter.py and adds the X-Spambayes-Classification header to the email.



The cf_wrapper plugin provides a framework for content filters which may reject or accept a mail for different recipients.



This module parses a MIME message into its components and compares the content types of all parts with the contents of config/content_types. It returns OK, DENY or DECLINED on the first match, or DECLINED if there is no match.



This module reads the majordomo configuration for recipi­ ents marked as majordomo lists and does some checks before accepting the mail.

Currently the only check implemented is “restrict_post”: If this option is set for the mailing-list, mails from senders which aren't on the lists are rejected.


tarpit – Slows smtp conversation on errors



All these plugins/programs are for working with a BerkeleyDB, the general format for this db is KEY=IP, DATA=timestamp|moredata

At this time (but other format/modes could be very easily implemented) it has several modes:

  • The IP and a yes/no flag (and the timestamp)
  • The IP and a Algorithm::TokenBucket object (and the timestamp) for blacklisting IP's based on rates of events.

Several things could be done with this plugins, for example, deny dictionary attacks, I configure the berkeley_tokenbucketadd plugin at deny hook (for example on rcpt to), and count the bad rcpt the IP is making. If the IP is having a log of bad rcpt's, the plugin, starts denying/blacklist the sender ip

Another example, would be based on a logfile count IP's and blacklist the top xxx of those IP's for a while.

Something like (pseudopseudocode, for examples look the perldocs of the plugins):

 tail -n xxxx logfile | grep "things" | sed -e 's/allgarbage_so_only_the_ip_is_left//' | sort | uniq -c | sort -n | tail | cut -f 2 | [[plugins:spam:berkeley_operation]] --param1 --param2 ...

inserts the top n IP's in the db, so they will be blacklisted for a while


berkeley_ipblacklist – This is the plugin that returns declined/deny/denysoft/log at connection time. (This is only reading the BerkeleyDB)

berkeley_tokenbucketadd – This is the plugin I use in Algorithm::TokenBucket mode, to save the rates of event's to the BerkeleyDB. For example, I could count the deny's for an IP

berkeley_ipblacklist_ignore – This is the whitelist plugin for all this BerkeleyDB stuff.

berkeley_operation – This is a script to mantain (add/clean) the BerkeleyDB

Remember to db_verify at start



This plugin checks for ~/.redirect. If it exists, it uses the recipient address contained there to inform the sender that this user is actualy somewhere else. This is specialy useful as an alternative for traditional forwarding because:

It doesn't break when the sender has published SPF records. It gives the final recipient's MTA a chance to perform its own delivery-time anti-spam checks (greylisting, spf, etc), in addition to whatever checks we have (or have not) performed on our side.


mailinglist_simple This plugin adds very simple mailinglist functionality to alias-file based distribution lists. It reads its config-file “config/mailinglist_simple” and checks if the RCPT is a defined 'mailinglist'. If true, it adds a 'Reply-to' header to the email before it gets queued. It also adds a 'Precedence: bulk' and 'X-Mailing-List' header to prevent mail-loops/bounces from auto-reply applications. Its also possible to define a mailinglist as PUBLIC or PROTECTED - meaning if everyone can send an email to the list or just members of the list. You can also have a different signature for each list that will be added to the end of the mail.


The rcpt_regexp check recipients against a list of regular expressions. It reads a list of regular expressions, return codes and comments from the rcpt_regexp config file. If the regular expression does NOT match m#^(/.*/)$#, it is used as a string which is compared with eq lc($rcpt). The recipient addresses are checked against this list, and if the first matches, the return code from that line and the comment are returned to qpsmtpd. Return code can be any valid plugin return code from Qpsmtpd::Constants. Matching is always done case insenstive.


This plug-in adds a notes method to the Qpsmtpd::Address class. This allows arbitrary data to be attached to an address similar to the connection and transaction notes. One possible use would be to use it to pass per-recipient configuration between plug-ins.

http://www.hjp.at/projekte/qpsmtpd/address_notes/ http://svn.perl.org/qpsmtpd/contrib/hjp/address_notes/


Plugin to reject mails if the IP address of the client doesn't resolve to a hostname. Can be enabled on a per-recipient basis (needs a plugin which sets the 'recipient_options' transaction note, e.g, the aliases_check plugin) and individual hosts can be whitelisted with the client_options plugin.

http://www.hjp.at/projekte/qpsmtpd/require_resolvable_client/ http://svn.perl.org/qpsmtpd/contrib/hjp/require_resolvable_client/


connection_shaper This plugin limits the connection rate for each IP address by counting the connection times every certain period. That prevents Spammers' intensive connections.


Plugin to support STARTTLS and encrypt all communications.

This plugin implements basic TLS support. It can also be used to support port 465 (SMTP over SSL), but only with qpsmtpd-forkserver. In this case, be sure to load plugins/tls before any other connect plugins and start qpsmtpd like this:

qpsmtpd-forkserver –port 25 –port 465

You can also specify multiple –listen-address options as well; see the help for qpsmtpd-forkserver for more details.

Use the script plugins/tls_cert to automatically generate a self-signed certificate with the appropriate characteristics. Otherwise, you should give absolute pathnames to the certificate, key, and the CA root cert used to sign that certificate.

For instructions below:

server.key (private key) server.crt (signed public key) CA.crt (certificate authority key)

For a self-signed certificate, enter the following line in config/plugins:

tls /full/path/to/server.crt /full/path/to/server.key /full/path/to/CA.crt

For a certificate signed by a CA such as DigiCert, which is signed by Entrust (ie chained):

cat server.crt DigiCertCA.crt TrustedRoot.crt > cert-bundle.pem

tls /full/path/to/cert-bundle.pem /full/path/to/server.key /full/path/to/DigiCertCA.crt

Writing your own plug-ins

Check out the documentation for the Plug-in API to learn how to write your own plug-ins.

Adding your plug-ins to the wiki

You can add plug-ins to this wiki by following the instructions contained in the plug-in template. Please add plug-in pages to the wiki in accordance with the documented namespace standard.