Patching qmail


The complete changelog is inside the patch file.

  • 2014-04-14
    -added qmail-maxrcpt patch, which allows you to set a limit on how many recipients are specified
  • 2014-03-10
    -added qmail-smtpd-liberal-lf patch, which allows qmail-smtpd to accept messages that are terminated with a single \n instead of the required \r\n sequence. This should avoid some "read failed" reject.
  • 2013-12-30
    -added qmail-SRS patch. You have to install libsrs2 now.
    -the character "=" in the sender address is now considered valid by chkuser in order to accept SRS
  • 2013-12-18
    -added qmail-date-localtime patch
    -added qmail-hide-ip patch
    -the original greetdelay by e.h. has been replaced with the improved patch by John Simpson. Now
    communications trying to send commands before the greeting will be closed. Premature disconnections will be
    logged as well.
    -CHKUSER_SENDER_FORMAT enabled to reject fake senders without any domain declared (like <foo>)
    -chkuser logging: I slightly modified the log line adding the variables' name just to facilitate its interpretation
    -added qmail-moreipme patch
    -added qmail-dnsbl patch (more info here)
  • 2013-12-05
    added two patches to make qmail rfc2821 compliant
  • 2013-11-23
    any-to-cname patch added

I have created a combined patch including the latest versions of several commonly-used qmail patches:

[Follow the patch details here]

Other patches:

You're invited to take a look at the next page of this guide, which presents several tests for these patches toward the bottom of the page.

Installing libdomainkeys

This library is a prerequisite of the DKIM patch by Manvendra Bhangui, which is part of my package. You must compile this, otherwise the compilation will break.

cd /usr/local/src
tar xzf libdomainkeys-0.69.tar.gz
ln -s libdomainkeys-0.69 libdomainkeys
cd libdomainkeys
chown -R root.root .
patch < ../libdomainkeys-0.69.diff
cd ../

Installing libsrs2

This library is a prerequisite of the SRS patch, which is part of my package. You must install this, otherwise the compilation will break.

tar xzf libsrs2-1.0.18.tar.gz
cd libsrs2-1.0.18
make install
cd ../

Be sure that libsrs2 is actually linked, otherwise you are going to have a qmail-send infinite crash and finally an auto-DoS:

> ldconfig -p|grep libsrs2 (libc6,x86-64) => /usr/local/lib/ (libc6,x86-64) => /usr/local/lib/

In case you decided to install the libsrs2 library by means of a package provided by your Linux distribution, you should check the path where the library was installed. Check if the file /usr/local/include/srs2.h actually exists; if not you may have to modify the srs.c in the netqmail source dir as follows:

#include </usr/local/include/srs2.h>
#include </usr/include/srs2.h>

Apply the patch

cd netqmail-1.06
gunzip -c ../roberto-netqmail-1.06.patch-latest.gz | patch

Configuring chkuser

The combined patch you downloaded has chkuser enabled. It’s configured to perform recipient verification and MAV (Mail From: Address Verification). 

You can customize your configuration by editing the chkuser_settings.h file (in /usr/local/src/netqmail-1.06) before compiling qmail. In order to enable chkuser, the following line must be commented out:


Uncomment to enable the check of user and domain format for sender address. This will reject fake senders without any domain declared (like <foo>).


Uncomment to enable checking of domain MX for rcpt addresses


Uncomment to enable checking of domain MX for sender address


This enables usage of "#" and "+" characters within sender address. It is used by SRS (Sender Rewriting Scheme) products.

As far as my MTA Is concerned, this solved an "invalid sender address format" reject message prompted by an email address of a mailman mailing list..


force-tls variables

By default the authentication will be denied if the client does not provide the STARTTLS command. If you want to allow connections without TLS, just do

export FORCETLS=0

in your run file. Values other than 0 (or not declaring this variable at all) will force TLS before the auth.

qmail-auth variables

By default the auth is allowed with LOGIN or PLAIN mechanism. You are invited to look at the README.auth file for further details concerning the use of the SMTPAUTH environment variable, expecially if you want to use CRAM-MD5.

Recompiling qmail

The BIG-TODO patch included in my combined patch may require that your queue be rebuilt. So be aware that all existing messages in the queue will be destroyed when you erase the queue below.

To discover if your qmail has messages in the queue:

> qmailctl stat

/service/qmail-send: up (pid 18127) 6 seconds
/service/qmail-send/log: up (pid 18134) 6 seconds
/service/qmail-smtpd: up (pid 18126) 6 seconds
/service/qmail-smtpd/log: up (pid 18135) 6 seconds
/service/qmail-submission: up (pid 18131) 6 seconds
/service/qmail-submission/log: up (pid 18132) 6 seconds
/service/vpopmaild: up (pid 18129) 6 seconds
/service/vpopmaild/log: up (pid 18128) 6 seconds
messages in queue: 0
messages in queue but not yet preprocessed: 0

If this will be the first time you install the combined patch (which contains the BIG-TODO patch), you’ll need to take these steps:

qmailctl stop
rm -r /var/qmail/queue

Now compile qmail:


If qmail is running stop the services before installing:

qmailctl stop

Finally install and start  qmail:

make setup check
qmailctl start

Creating an SSL key file

If you don’t want to enable SMTP relay (using SMTP/TLS access), you can skip this section.

To secure the smtp authentication you must create the SSL certificate. The certificate must be owned by the user who runs qmail-smtpd, in our case vpopmail.

> make cert

Generating a 1024 bit RSA private key
writing new private key to '/var/qmail/control/servercert.pem'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]:IT
State or Province Name (full name) [Some-State]:Italy
Locality Name (eg, city) []:Cagliari
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Your Name
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []
Email Address []

> make tmprsadh
> chown vpopmail.vchkpw /var/qmail/control/*.pem

It is important that the “Common Name” matches the domain name that your email clients will specify as their SMTP server.

Now let’s create a cronjob to update the certificate every day:

> crontab -e

03 05 * * * /var/qmail/bin/update_tmprsadh > /dev/null 2>&1

Important: If you run qmail-submission as a user other than vpopmail, and you’re installing my combined patch, you must adjust /var/qmail/bin/update_tmprsadh accordingly. Otherwise you’ll probably exceed the connection timeout due to privilege problems, and won’t be able to send messages when connected remotely.

Combined patch details


It provides cram-md5, login, plain authentication support for qmail-smtpd (port 587) and qmail-remote.


It implements SSL or TLS encrypted and authenticated SMTP between the MTAs and from MUA to MTA. I have adjusted the file update_tmprsadh to chown the .pem files to vpopmail, which runs qmail-smtpd.

You may interested to take a look to the page concerning smtp-auth and TLS testing here.


optionally gets qmail to require TLS before authentication to improve security.


performs recipient verification and Mail From: Address Verification (MAV).

You may be interested to take a look to this page concerning chkuser testing.


Enables simscan and qmail-dkim to return the appropriate message for each e-mail it refuses to deliver. Simscan rejects with the name of the virus or the spam-score; qmail-dkim rejects with the verification failure message.


  • Author: Christophe Saout. Patch modified by Manvendra Bhangui to make it IPv4-mapped IPv6 addresses compliant.
  • Info:
  • Version rc5

It can check incoming mails inside the SMTP daemon, add Received-SPF lines and optionally block undesired transfers.


implements Sender Rewriting Scheme fixing SPF break upon email forwarding. To enable SRS read carefully the configuration instructions above.

Oversize DNS

This patch enables qmail to handle large DNS packets.

Reread concurrency patch

rereads control/concurrencylocal and control/concurrencyremote files when qmail-send receives a HUP signal.

Big Concurrency patch

It sets the spawn limit above 255.

Big Concurrency fix

Fixes a compiler error if you set concurrency higher than 509 in /usr/local/src/netqmail-1.06/conf-spawn.

maildir++ patch

adds maildirquota support to qmail-pop3d and qmail-local.

Better qmail-smtpd Logging patch

Facilitates diagnosing qmail-smtpd logging its actions and decisions (search for a line starting with qmail-smtp:). This is useful for discovering fake IP addresses with bad HELO’s when qmail-smtpd doesn’t log anything.

Greeting delay patch

  • Author: John Simpson (?)
  • Download here
  • More info here

adds a user-definable delay after SMTP clients have initiated SMTP sessions, prior to qmail-smtpd responding with "220 ESMTP". It can reject connections from clients which tried to send commands before greeting. You can control the delay via the environment variable SMTPD_GREETDELAY (was GREETDELAY in the original patch). A value of SMTPD_GREETDELAY=”30” will delay qmail-smtpd’s response for 30 seconds.

DKIM and SURBL patch

adds DKIM signing & verification support to qmail at both qmail-smtpd and qmail-remote/local level and SURBL filtering support to qmail.  
The file hier.c modified to chown /var/qmail/control/cache and subdirs to vpopmail.

EXT-TODO patch

addresses a problem known as the silly qmail (queue)  problem.

BIG-TODO patch

Makes qmail use a hashing mechanism in the todo folder similar to that used in the rest of the queue.

qmail-inject-null-sender patch

Prevents qmail-inject from rewriting the null sender, fixing an issue with sieve vacation/reject messages.

doublebounce-trim patch

Prevents double bounces from hitting your queue a second time provided that you delete the first line from /var/qmail/control/doublebounceto

esmtp-size patch

Enables qmail-smtpd to reject messages if they’re larger than the maximum number of bytes allowed (you can set this value in the /var/qmail/control/databytes control file).


Provides the ability to archive each email that flows through the system.

qmail-remote CRLF patch

Enables qmail-remote to handle CR (\r) properly, always sending the line breaks as CRLF (\r\n) and avoiding to double the CR (like qmail-remote normally does). This often caused me a broken header when forwarding messages by means of a sieve rule.

outgoingip patch

  • Author: Andy Repton (adjusted by Sergio Gelato)
  • Original patch:
  • Robbie Walker provided a patch to correct qmail-qmqpc.c's call to timeoutconn(), because the function signature was modified by the original outgoingip patch

By default all outgoing emails are sent through the first IP address on the interface. In case of a multiple IP server this patch makes qmail send outgoing emails with the IP eventually stored in control/outgoingip. The ehlo domain is NOT modified by this patch.

qmail-bounce patch

limits the size of bounces. The default limit for bounces is 50000 bytes, but you can create a file in crontrol/bouncemaxbytes in order to change that number.

qmail-smtpd pid, qp log patch

makes qmail-smtpd log a line similar to the following:

@4000000039b89c95026a89b4 mail recv: pid 8155 from <name@domain.xy> qp 8157

The pid allows you to match the message up with a given tcpserver process and the qp lets you find a particular delivery.


avoids qmail getting large amounts of DNS data we have no interest in and that may overflow our response  buffer.

qmail-rfc2821 patch

makes qmail rfc2821 compliant

smtpd-502-to-500 patch

  • Author: Jonathan de Boyne Pollard
  • Original patch: local copy
  • More info here

makes qmail rfc2821 compliant

qmail-dnsbl patch

allows you to reject spam and virus looking at the sender's ip address. Added a line to make qmail-smtpd log the reject reason as well as the envelope to facilitate diagnostics.

qmail-moreipme patch

prevents a problem caused by an MX or other mail routing directive instructing qmail to connect to itself without realizing it's connecting to itself, saving CPU time.


  • Author: Alex Nee
  • Download here

It will hide your Private or Public IP in the email Headers when you are sending Mail as a Relay Client.

qmail-date-localtime patch

  • Author: John Saunders
  • Download here

causes the various qmail programs to generate date stamps in the local timezone.

qmail-liberal-lf patch

allows qmail-smtpd to accept messages that are terminated with a single \n instead of the required \r\n  sequence.


allows you to set a limit on how many recipients are specified for any one email message by setting control/maxrcpt. RFC 2821 section says that an MTA MUST allow at least 100 recipients for each message, since this is one of the favourite tricks of the spammer.
I slightly modified the patch also to log its response.


forcetls patch

Can you pls let me know how to remove the ForceTls patch from the big patch? I need the auth to work without tls.

Thank you!

read above! :)

read above! :)

DKIM and SRS = fail :-(


if you use SRS, DKIM filter fails, as it sets original SENDER domain instead of that specified in SRS. Any suggestions how to fix it?

cheers and thanks for your patches!


Can you post how the headers

Can you post how the headers look like when we you use SRS?

I contacted M.Banghui, the author of the DKIM patch, and he told me that he can fix it.

Sure :)

The DKIM is getting _SENDER  - and SRS is providing to qmail an original Sender domain, instead of the one taken from /var/qmail/control/srs_domain

BTW, why don't you move your awesome patchset to github? It would make things much easier :)

I would declare I can work on IPv6 part, as it is the only (but big) missing thing from your patches.



Hi, can you do a cut&paste of

Hi, can you do a cut&paste of the headers?

Actually an help on the IPv6 patch would be appreciated, as I have not much time these days, and I'm not an IPv6 expert. As you probably know M.Banghui has merged an IPv6 patch in his DKIM/SURBL and my plan is to add it to my package soon or later :)

qmail-todo problem

Firslty, thanks Roberto for ur efforts of creating the patch, But i'm facing a critical problem after i patched qmail 1.6  with ur patch that i have found my server load reached to 250, and when i check the process found that qmail-todo consuming cpu terribly. But i don't know why this happened and what should i do, although i have applied the steps and installed qmail successfully.

Re: qmail-todo problem

Hi Kamal,

I assume that you erased your queue in this way before installing the todo-patched qmail for the first time:

qmailctl stop
rm -rf /var/qmail/queue
make setup check

If yes please post a

ps axfuww | grep qmail 

The best way to investigate what qmail-todo is doing is using strace:

strace -Ff -o /tmp/qmail-strace.log -p <pid_of_qmail-todo>

Re: qmail-todo problem

Hi Roberto,

Yes, I already erased the queue as you mentioned, I want to clear something i'm using the combined patch "roberto-netqmail1.06.patch-latest"  NOT todo-patch. but the problem with qmail-todo process that was consuming cpu.

Kindly find output details below,



Maybe a lbsrs problem did you

Maybe a lbsrs problem did you successfully installed it? did you ldconfig it?


I think it's not a libsrs

I think it's not a libsrs issue, as in that case the compilation itself will break

Re: qmail-todo problem

it seems to be an infinite loop...

when you stop qmail I would try to kill all those qmail-todo which doesn't belong to qmail-send anymore, and after that erase the existing queue, recompile and restart qmail

Re: qmail-todo problem

I realy did that, but unfortunately still the same, the load reached to 270,and server was going to explode.



I am trying out the latest patch with the SRS2. While compiling i had an error

/usr/bin/ld: cannot find -lsrs2
collect2: ld returned 1 exit status
make: *** [qmail-local] Error 1

In the beginning it cannot find the file srs2.h so i download it from and copied it to /usr/local/include/

I am on CentOS 6 64 bits.

Thanks for helping.


You need libsrs2

You have to install the libsrs2 libraries, not only the srs.h, see above. Check if they are installed in this way

ldconfig -p|grep libsrs2

Hello,Yes i


Yes i did.

[root@beyond ~]# ldconfig -p|grep libsrs2 (libc6,x86-64) => /usr/lib64/



did you modify srs.c?

did you modify srs.c accordingly?

Didnt thought of doing that.

Didnt thought of doing that. What should i edit?



Nic, read above :)

Nic, read above :)


Hi roberto

I succesfully create the certificates and it works great, the only problem is that in mozilla-thunderbird, iphone, android show a warning because the certificate is not valid, configuring an exception it works. About it I have two questions.


Is there any chance to have differents certificates for every domain?


If I buy a "valid certificate" can I just copy into the folder and it will work?

Thanks in advance

Enetcs as far as I know


as far as I know the e.h. auth patch works with a global certificate.

Yes you simply have to copy the certificate into that folder, but when you buy a valid certificate you also get an "intermidiate certificate" to be copied in the same folder, which assures that your cert is valid

CHKUSER patch - how to disable!!

imho, chkuser patch is way more problems than it's worth. It's blocking legit emails from namecheap, comodo, godaddy and others. How does one disable chkuser permenantly????? I've tried commenting out of my qmail-submission/run, and restarting qmail, chkuser still running. grrr.

can you please provide log

can you please provide log details about the rejections for such providers? thank you

chkuser silently dropping

chkuser silently dropping mail !  How do I completely disable chkuser??????????????????????

2013-10-11 12:39:48.373851500 tcpserver: status: 1/20

2013-10-11 12:39:48.374029500 tcpserver: pid 28172 from

2013-10-11 12:39:48.374142500 tcpserver: ok 28172 0:::ffff: :

2013-10-11 12:39:48.621588500 CHKUSER accepted sender: from <> remote <> rcpt <> : accepted any sender always

2013-10-11 12:39:48.767883500 tcpserver: end 28172 status 02013-10-11 12:39:48.767910500 tcpserver: status: 0/20

what make you think that it's

what makes you think that it's a chkuser fault? this is not a rejection, and this is the log of port 587, but you said that you have some incoming legitimate email rejected, which should be received on port 25

It blocks legitimate emails,

It blocks legitimate emails, it just sucks. Shouldn't be included in the net-qmail patch.

Tried commenting out of my

Tried commenting out of my qmail/submission/run file, chkuser still running!


# cat /var/qmail/supervise/qmail-submission/run 

QMAILDUID=`id -u vpopmail`NOFILESGID=`id -g vpopmail`MAXSMTPD=`cat /var/qmail/control/concurrencyincoming`SOFTLIMIT=`cat /var/qmail/control/softlimit`
# You MUST export this, otherwise you'd get a 30 sec timeoutexport

# This enables greetdelay for qmail-smtpd.export

# This enables chkuserexport

# This enables simscan debug#export

exec /usr/local/bin/softlimit -m "$SOFTLIMIT" \    /usr/local/bin/tcpserver -v -H -R -l 0 \    -x /home/vpopmail/etc/tcp.submission.cdb -c "$MAXSMTPD" \    -u "$QMAILDUID" -g "$NOFILESGID" 0 587 \    /var/qmail/bin/qmail-smtpd \    /home/vpopmail/bin/vchkpw /bin/true 2>&1

again, this is the submission

again, this is the submission service, which has nothing to do with incoming emails. In any case you have an error. Correct in this way


but be aware that this should be done on standard smtpd (port 25) service.

first of all, i think you can

first of all, i think you can try to take a look to the chkuser manual, to see how to fit it to your needs.

If you want to disable it, just comment it in your run file (in case you are following my configuration).

If you want to delete it from my package you have to look at the original patch and see what it modifies. I remember that it modifies only qmail-smtpd.c and the Makefile, apart from new created files. You can easily recognise the modifications because there is a comment more or less like "chkuser patch starts here"

qmail-qmqpc.c change needed

Hi Roberto,

First, thanks for the patch collection. I ran across an issue that I thought I would make you aware of: one of the patches in this collection modifies the function signature of timeoutconn.c/timeoutconn() . I assume it's one of the TLS or AUTH patches, but I haven't tried to figure it out. In any case, the patch adds an additional parameter to the signature which is not present in the original calls to timeoutconn() in qmail-qmqpc.c

None of the patches even touch qmail-qmqpc.c ( probably because very few people make use of it) but I actually use it for SMTP servers. Crypto can put quite a load on older hardware so I "spread the wealth" around with multiple smtp servers using QMQP to send the messages to my queue machine.

In any case, the fix is pretty straightforward and I am going to try and post the patch here in this comment:

diff netqmail-1.06/qmail-qmqpc.c netqmail-1.06.patched/qmail-qmqpc.c
>   /*** 2013-08-24 Robbie Walker <>
>   DESCRIPTION: the great collection of patches from Roberto Puzzanghera [ ]
>   includes changes to timeoutconn.c function signature as listed below. qmail-qmqpc.c also calls
>   timeoutconn and needs to be patched as well 
>   original timeoutconn() signature:
>   int timeoutconn(s,ip,port,timeout)
>   int s;
>   struct ip_address *ip;
>   unsigned int port;
>   int timeout;
>   modifed timeoutconn() signature:
>   int timeoutconn(s,ip,outip,port,timeout)
>   int s;
>   struct ip_address *ip;
>   struct ip_address *outip;
>   unsigned int port;
>   int timeout;
>   */
>   struct ip_address outip;
>   outip.d[0]=outip.d[1]=outip.d[2]=outip.d[3]=(unsigned char) 0;
<   if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) {
>   if (timeoutconn(qmqpfd,&ip,&outip,PORT_QMQP,10) != 0) {

Thanks for the fix

Hi Robbie, I'm going to add your fix in the next release that will be released in a few days

Thanks for the contribution :)

You're welcome

Glad to contribute!



I noticed that the spf is not running properly. The IP consist of 4 fs.

Received: from unknown (HELO (::ffff:
  by 0 with SMTP; 28 Jul 2013 14:37:47 -0000
Received-SPF: unknown (0: No IP address in conversation)

Whereas my old box running on shupp toaster 0.9.4

Received: from unknown (HELO (
  by 0 with SMTP; 26 Jul 2013 03:02:52 -0000
Received-SPF: pass (0: SPF record at designates

Am i right to say that the fs infront of the IP is affecting spf?

Is there a fix or workaround?


Hi Nicholas,I think you are

Hi Nicholas,

I think you are right. The SPF patch is very old (the same embedded in the shupp's combiend patch) and is not compatible with IPv6. As far as I know there are no fix to this (but you can ask the author) or alternative spf patches.If you find something interersting let me know

But i am not on

But i am not on IPv6.




you are not in an IPv6 net

you are not in an IPv6 net but that address ::ffff: is IPv6, and the SPF patch is not able to recognize such an IP

Understand nowThanksnic

Understand now



Hi Roberto,Manvendra Bhangui

Hi Roberto,

Manvendra Bhangui from IndiMail get it fixed.
Is it possible to get it into your combined patches?


Hi Nick, Manvendra Bhangui

Hi Nick, Manvendra Bhangui has already answered to my requests. He is kind as always and provided details to make saout's spf patch work with IPv6-mapped as well. So I modified my big patch accordingly and this is a test version:


It is important that you have the new ucspi-tcp6 installed otherwise the filter on IPv6 clients will not work. I tested it both against the new tcpserver (ucspi-tcp6) and the original djb's ucspi-tcp-0.88 and they are both ok for IPv4 clients. Unfortunately I don't have any IPv6 net.

Test if you like and let me know :)

Hi Roberto,I also do not have

Hi Roberto,

I also do not have IPv6, Tested the new patch and don't seem to be working

Received: from unknown (HELO (::ffff:


So, if I understand well, you

So, if I understand well, you can't see the "Received-SPF: ...." line in the header?

Edit: Can you confirm that you are using ucspi-tcp6 or another tcpserver with IPv6 capabilities?

Roberto,Can you send me


Can you send me qmail-smtpd.c as an attachment. Just want to check the call to spfcheck() function.

Regards Manvendra

Hi Roberto,Received-SPF:

Hi Roberto,

Received-SPF: unknown (0: No IP address in conversation)

I am using uspi-tcp6-0.98


Hi NIck, I will try to ask

Hi NIck, I will try to ask Manvendra Bhangui if he can provide more details. If he can I will certainly update my patch

The link to the download page is the big indimail patch and it's impossibile (for me) to extract the modifications he did.

Thanks for the contribution



Hi , i need some help, after applying his combined patch, i get many emails with this errors:


No mail that happen this error are delivering in my mailbox, make a lot of googleeing and nothing, could you help me?

Re: 503_MAIL_first_(#5.5.1)

Hi Fabiano, I think this is due to improper commands entered by the client. You should enable recordio inside your smtpd run file to record the entire smtp conversation and discovered the reason of the reject. Post here the smtp dialog if you like.

Bounce size limitation

Hi Everyone,

Has anyone came across a patch to limit size of any type of bounce?

I had tried qmail-bounce.patch by Frank Denis. But it will only work if databytes is enabled.



Hi after apply the patch and export auth, CRAM-MD5 is not enabled

250 SIZE 0

Do i need to export CRAM-MD5?



cram-md5 auth

No, take a look to README.auth for details

Many thanks!

Many thanks!