| |
|
|
| qmail Recipient Check script: |
Below are the instructions on how to install my qmail Recipient Check script.
This script exists because qmail doesn't check to make sure recipients are
valid during the SMTP conversation.
My script checks for users against the system password file /etc/passwd
and against qmail's user file /var/qmail/users/assign
for the domains your box accepts mail in the /var/qmail/control/locals
and /var/qmail/control/virtualdomains files.
Download version 0.1 here:qmrcptchk01.pl
Download the latest version 0.2 here:qmrcptchk02.pl
NOTE: Version 0.2 now checks against qmail's aliases as well as the others listed above.
This script would not be possible without Zachary Bedell's patch. His
original work can be found here
Is Anbody Home?
Below in the installation instructions is a modified version of the patch
which I've tested with qmail-1.03 and netqmail-1.05.
|
INSTALLATION INSTRUCTIONS for applying the qmrcptchk.pl script:
To install this script you must first patch Qmail.
I'm sure everyone is using heavily patched version of either
qmail-1.03 or netqmail-1.05. In either case, this patch should work.
- cd to your qmail source directory (eq: cd /usr/src/mail/qmail-1.03)
- edit qmail-smtpd.c with your favorite editor (emacs qmail-smtpd.c)
- add this line:
#include "wait.h"
after all of the #includes at the top of the file.
The result should look something like this:
#include "timeoutwrite.h"
#include "commands.h"
#include "wait.h"
- search for 'void die_alarm()' (probably around line 45)
add this line after the 'void die_alarm()'
void die_rcptcheck() { out("421 unable to verify recipient (#4.3.0)\r\n"); flush(); _exit(1);}
The result should look something like this:
void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); }
void die_rcptcheck() { out("421 unable to verify recipient (#4.3.0)\r\n"); flush(); _exit(1);}
void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); }
- search for 'void err_wantmail()' (probably around line 60)
add this line after the 'void err_wantmail()'
void err_realrcpt() { out("550 sorry, no mailbox here by that name (#5.1.1 - chkusr)\r\n"); }
The result should look something like this:
void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
void err_realrcpt() { out("550 sorry, no mailbox here by that name (#5.1.1 - chkusr)\r\n"); }
void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
- search for 'stralloc addr = {0};' (probably around line 150)
add this function after the 'stralloc addr = {0};'
int realrcpt_check()
{
char *bincheck;
int ret, wstat;
/* For non-local domains, this function shouldn't interfere */
if (!addrallowed()) return 1;
bincheck = env_get("QMAILCHECKRCPT");
if (!bincheck) return 1; /* No custom check script, so accept message. */
switch(ret = fork())
{
case -1:
return 1; /* If fork failed, just accept the mail. */
case 0:
execlp(bincheck, bincheck, addr.s, 0); /* changed from NULL to 0 by Nick
gcc wouldn't compile it as NULL */
}
wait_pid(&wstat,ret);
ret = wait_exitcode(wstat);
switch(ret)
{
case 0:
return 0; /* Check returns 0 if positive no match. Return 0 to disallow delivery. */
case 1:
return 1; /* Check returns 1 if positive match. Return 1 to allow delivery. */
default:
die_rcptcheck(); /* Problem running script. Temp failure. */
return 1; /* Never get here, but quiets compiler warning. */
}
}
The result should look something like this:
stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */
int realrcpt_check()
{
char *bincheck;
int ret, wstat;
/* For non-local domains, this function shouldn't interfere */
if (!addrallowed()) return 1;
bincheck = env_get("QMAILCHECKRCPT");
if (!bincheck) return 1; /* No custom check script, so accept message. */
switch(ret = fork())
{
case -1:
return 1; /* If fork failed, just accept the mail. */
case 0:
execlp(bincheck, bincheck, addr.s, 0); /* changed from NULL to 0 by Nick
gcc wouldn't compile it as NULL */
}
wait_pid(&wstat,ret);
ret = wait_exitcode(wstat);
switch(ret)
{
case 0:
return 0; /* Check returns 0 if positive no match. Return 0 to disallow delivery. */
case 1:
return 1; /* Check returns 1 if positive match. Return 1 to allow delivery. */
default:
die_rcptcheck(); /* Problem running script. Temp failure. */
return 1; /* Never get here, but quiets compiler warning. */
}
}
int addrparse(arg)
- search for 'stralloc_cats(&rcptto,"T"' (probably around line 310)
add this line before the 'stralloc_cats(&rcptto,"T"'
if (!realrcpt_check()) { err_realrcpt(); return; }
The result should look something like this:
else
if (!addrallowed()) { err_nogateway(); return; }
if (!realrcpt_check()) { err_realrcpt(); return; }
if (!stralloc_cats(&rcptto,"T")) die_nomem();
- recompile qmail with a 'make'
- Download my check program from
here.
- Make it executable
# chmod 755 qmrcptchk.pl
- Copy it to /usr/local/bin
# cp qmrcptchk.pl /usr/local/bin
- test qmail-smtpd by running ./qmail-smtpd in the source directory
run a 'mail from' and 'rcpt to' through it to make sure its working.
For example:
bash$ export QMAILCHECKRCPT=/home/user/qmrcptchk.pl (or wherever you downloaded it to)
bash$ ./qmail-smtpd
220 mail.server.com ESMTP
mail from:test@domain.com
250 ok
rcpt to:to@domain.com
550 sorry, no mailbox here by that name (#5.1.1 - chkusr)
- Stop qmail, copy the qmail-smtpd binary into the correct place.
Make a backup of your qmail-smtpd first.
# cp /var/qmail/bin/qmail-smtpd /var/qmail/bin/qmail-smtpd.bak
Then copy it over:
# cp ./qmail-smtpd /var/qmail/bin
Then, change the permissions, so everything is back to normal:
chown root:qmail qmail-smtpd
- Edit your /service/qmail-smtpd/run with your favorite editor.
bash$ emacs /service/qmail-smtpd/run
And after the first line
#!/bin/sh
add this line
export QMAILCHECKRCPT=/usr/local/bin/qmrcptchk.pl
- That should be it! You're Done!
|
TROUBLESHOOTING:
If you get any errors like this:
421 unable to verify recipient (#4.3.0)
- You may not have perl located at /usr/local/bin/perl, to fix it
just change the first line of the qmrcptchk.pl script to where
you have perl installed.
- You may have forgotten to make the qmrcptchk.pl executable.
- There may be problems with some of the files listed in qmrcptchk.pl
(The qmail configuration files that it reads)
- If you get an error something like this from the /var/log/qmail/smtpd logs
@400000004238b7f40a5c4e3c /usr/bin/perl: error while loading shared libraries: \
libc.so.6: failed to map segment from shared object: Cannot allocate memory
Than your softlimit is too low. You have to increase it to 6-8MB or higher.
To increase your softlimit, edit your /service/qmail-smtpd/run file,
and increase the 2000000 to 8000000 or even higher like 16000000.
|
If you have any other questions or comments, please feel free to email me.
web at my domain name (My domain name should be obvious as it is the
image at the top of the screen).
|
|