[ English / Japanese ]
The SMTP wrapper `antibadmail' provides generic spam rejection on SMTP session. This program is a successor of my qmail patches.
Because `antibadamail' is a wrapper, it can work not only with qmail, but also with sendmail, postfix and any other RFC2821 compliances.
Unlike the `Message contents spam filter', antibadmail rejects bad mail without seeing contents of them. Imagine if you were a large scale bad mail sender. Do you send bad mails from valid SMTP server? Do you send bad mails with your correct email addresses?
No.
Antibadmail reject all bad mails seeing the bogus parameters in SMTP session. Doing so reduces the load of mail servers because antibadmail program check only three SMTP parameters(HELO, MAIL-FROM and RCPT-TO) and smtp-client's DNS-record settings.
To get latest version, use cvs.
cvs -d :pserver:anonymous@yatex.org:/qmail co antibadmail
Once you've checked out source, all you have to do when you want to get latest source is typing
cvs -z1 up -Pd
in antibadmail/
directory. If you want to improve this
program by yourself, please feel free to email to abmusers ML. Then
we'll create developer's account in CVS repository for you.
Snapshot here.
antibadmail-1.43.tar.gz
And join abmusers ML.
The antibadmail program enables handy bad mail rejection for qmail/sendmail/Postfix as below;
($CONTROLDIR defaults to /var/qmail/control)
Reject mail from host which sent HELO parameter that matches with file name in $CONTROLDIR/badhelodir/. Entries starting with period are treated as wildcard.
Some spammer's smtp hosts send helo of bogus IP address. Almost all of them are spam. Reject them.
More strict HELO qualification as below will be done for unknwon-host(hosts with PTR record of IP address unset).
No dots in HELO string assumed to be a bad host.
Much wider wildcard match for helo string, `.jp' for example, can be applied for unknown host. Put wider wildcard patterns into $CONTROLDIR/badhelodir/unknown/ by creating empty file with that name.
If environment variable REJECTIPINHELO is set, reject when HELO
string contains 4 octets of client host's IP address. This is
effective to reject spam from hosts whose IP address are
dynamically allocated. When REJECTIPINHELO is set to integer
n(1<=n<=3), skip first n
octets and the trailing 4-n octets are compared.
eg. If REJECTIPINHELO="2"
and client address is 10.2.3.4, only "3" and "4" are tested.
In any case above, badhelo check is skipped when $RELAYCLIENT or $RELIABLECLIENT is set like qmail manner.
In the same way as badhelo rejection, you can reject certain pattern of MAIL-FROM addresses. Put the email address string you want to reject into $CONTROLDIR/badmailfromdir/. Any patterns starting with `@' means all email addresses on that domain. Any patterns starting with dot(.) matches with all email domains under that domain.
(eg.) @hotmail.com -> matches with all *@hotmail.com addresses .biz -> matches with all *@*.biz addresses
You might know there are very very very many spam under the assumed name of RANDOM@hotmail.com. Giving up receiving all @hotmail.com is a clever solution. Do you think is it a overdosing?? Read the next.
Setting GOODMAILFROM to acceptable domains in tcpserver rule
file. Domains listed in this variable should be accepted even if
that domain is in $CONTROLDIR/badmailfromdir/
list.
With this feature, you can reject all false @hotmail.com while you
get real hotmail messages from real hotmail servers. To achieve
this, put
=.hotmail.com:allow,GOODMAILFROM="@hotmail.com"
in tcpserver's rule and then put @hotmail.com in
badmailfrom
database. Note that tcpserver for
antibadmail should be invoked *WITHOUT* -H flag(-H means not
to lookup remote host name).
Like the manner of $GOODMAILFROM, values listed in $GOODHELO
should be accepted even if the string is in
$CONTROLDIR/badhelodir/
.
USE THIS WITH CARE
There are some ISP which provide free email service and commercial Internet connection service, such as Yahoo. Authentic Yahoo SMTP servers send correct FQDN name of them. So it is good idea to reject `HELO yahoo.com' because 100% of them are sent from badmail. You'd better to put 'yahoo.com' entry in badhelodir/ database. Do not set $GOODHELO for this case. But..
Disgusting SMTP servers, hotmail.com for example, don't send FQDN of them. Hotmail SMTP server stupidly sends `HELO hotmail.com'. Sigh.. Use $GOODHELO only for these case.
=.hotmail.com:allow,GOODMAILFROM="@hotmail.com",GOODHELO="hotmail.com"
Put a line above in tcpserver's rule file and you can receive emails from silly setting servers.
Reject all mail of localpart-only sender, except messages of bounce or messages from RELAYCLIENT.
Null-sender is used for bounce mail. Some spammer's MTA sends emails with null-sender to multiple recipients. That's surely spam. The antibadmail program refuses null-sender emails once the client requests more than one RCPT TO.
If $RELAYCLIENT or $RELIABLECLIENT is set, cancel mail-from domain check. Useful for receiving bounce mail from reliable mail server.
When you had old mail account on host you previously used, you want to forward emails to current mail server. In such case, you ought to know "forwarded email are full of spam!!", because your current mail server should rely the forwarding servers. Against this problem, the antibadmail program rejects all forwarded mail from such server except those listed in $PASSONLY. If you want to limit forwarded emails from old server to *.jp and *.org, put
=old.server.previously.used:allow,PASSONLY=".jp/.org"
in tcpserver's rule.
Reject any RCPT-TO recipient addresses listed in $CONTROLDIR/badrcpttodir/.
If the environment variable BADHOST set, reject the mail from that host with SMTP error 553. It is bad idea to refuse TCP connection from host which sends emails you want to reject, because natural action of SMTP client is to try to connect to secondary MX and/or more. Set $BADHOST by tcpserver as follows;
=.evil.domain:allow,BADHOST=""
It will always sends SMTP-5xx error code to smtp client that matches with above rule.
Requires tcpserver with tcpserver-paranoid patch.
It is true IP'addresse's DNS PTR record is not absolutely required. But almost all UBE sender disguise or omit PTR record.
If you want to reject mail from server whose PTR record is disguising, add -p option to tcpserver
tcpserver -p ......
and replace tcpserver with tcpserver-paranoid patch. The antibadmail will reject mail from such host whose IP address has invalid PTR record.
Paranoid check is too much powerful. It sometimes rejects desirable email. You can find rejection log by grep-ping "BAD_PARANOID". To forgive x.y.z.w which sends *@xyz.its.dom.ain for incorrect PTR record setting, add a rule to tcprule file as follows;
x.y.z.w:allow,PASSONLY="@xyz.its.dom.ain"
Emails from x.y.z.w that matches with $PASSONLY is acceptable even if x.y.z.w has wrong PTR record.
In most case, spammer's computer is connected as unknown host. So it is clever to reject from unknwon host. But in fact, many desirable messages are sent from unknown host, since some mail-server administrators can't imagine the importance of correct DNS settings.
For this problem, we should request PTR record of IP-address blocks for unfamiliar country. If you and your site's users all don't have needs to communicate with AAA-country, and IP-address block of `XXX.YYY.*.*' is allocated to AAA-country, put
XXX.YYY.:allow,REQPTR=""
in tcpserver's rule file. All connections from XXX.YYY.*.* without PTR record will be rejected. With PTR record, of cource, accepted.
In most case, polite SMTP clients send correct FQDN as HELO parameter. But not all. So, we can not reject all connections that send wrong HELO parameter even if it is effective.
Requiring correct FQDN HELO can be partially activated against clients when environment variable CHECKHELODOMAIN is set.
=*.ppp.example.net:allow,CHECKHELODOMAIN=""
This rule request correct FQDN HELO for clients whose PTR
record matches with *.ppp.example.net
.
Note that it is bad idea to apply CHECKHELODOMAIN to very wide range because some `good honest' clients don't send correct FQDN. Apply this for block that is apparently allocated to end-user. This rule is weeker than you imagine, because most decisions of rejection are done by other rules before this rule is applied.
Note that this is not a virus scanner. Most virus-infected PC sends malicious email with infected person's email addresses. Introduction of antibadmail does not mean unnecessity of virus scanner. But `contents filter' including virus scanners always waste tremendous computing resources which are essentially unnecessary.
You'll find 60%-99% of undesirable emails are comfortably rejected by antibadmail. Save your mail server's resources!
Antibadmail should be invoked by modified version of tcpserver, which can set environment variables for both TCPREMOTEHOST match and TCPREMOTEIP match.
cvs -d :pserver:anonymous@yatex.org:/qmail \
co -r paranoid+bsd ucspi-tcp
cd ucspi-tcp
vi conf-home
(edit conf-home to define installation prefix)
make && make setup check
NOTE: If you use FreeBSD, checkout
cvs -d :pserver:anonymous@yatex.org:/qmail \
co -r paranoid+freebsd ucspi-tcp
instead.
You need unprivileged user for antibadmail.
groupadd abm useradd -g abm abm
User name `abm' is arbitrary. Suppose uid and gid of `abm' user are 250 and 25 respectively. Replace uid=250 and gid=25 as described below with real values on your host.
Then, build antibadmail main programs.
gtar zxpf antibadmail-VERSION.tar.gz cd antibadmail-VERSION make all install
At the beginning of `make', you have a chance to determine installation prefix of antibadmail. Assume prefix is `/var/qmail` in latter of documetation.
The final step is to wrap running smtpd:
Change smtp daemon port other than 25. 10025 for example here.
Start antibadmail as follows;
HOSTANDIP=1 RELAYCHECK=1 tcpserver -u 250 -g 25 -x /etc/smtp.cdb 0 25 \ antibadmail mconnect 127.0.0.1 10025
Make sure antibadmail and mconnect command are located in
$PATH. `mconnect' is a SMTP connection client, which comes
with ucspi-tcp. /etc/smtp.cdb
is the
tcpserver's connection control rule database. If you are
not familiar with tcpserver, see the tcpserver rule section below.
Put list of domain names your server can accept.
If your server can accept(or relay) foo.example.com and
*.bar.example.net, create empty files below in
/var/qmail/control/rcpthostsdir/
foo.example.com .bar.example.net
Note that no at-marks(@) are necessary for domain patterns, unlike patterns for bad*dir described below. RELAYCHECK=1 on a startup command line specifies enabling acceptable RCPT-TO domain check. Even if RELAYCHECK=1, when the client pass SMTP-AUTH, any RCPT-TO domain the client send will be accepted by antibadmail.
If you alter acceptable domains by "POP before SMTP" control, please ask it at the abmusers ML.
First, genuine netqmail is strongly recommended. If you have old qmail-1.03 plus many spam-control patches such as qmail badrcpt to patch, qmpatch or so, replace it with netqmail. Now is the chance to shift. And if you are using ancient inetd+tcpwrapper for qmail-smtpd, replace it with tcpserver.
The qmail-smtpd daemon program is well designed to be wrapped by others. All you have to do is to add antibadmail to starting script. For example, you may already have script like this;
tcpserver -u 250 -g 25 -x /etc/smtp.cdb 0 25 qmail-smtpd
Rewrite it as follows;
HOSTANDIP=1 tcpserver -u 250 -g 25 -x /etc/smtp.cdb 0 25 \ antibadmail qmail-smtpd
That's all. Never fail to replace tcpserver with modified version described above.
If you are not familiar with tcpserver yet, try this simplest rule
file /etc/smtp
.
127.0.0.1:allow,RELAYCLIENT="" 10.0.0.:allow,RELAYCLIENT="" all:allow
where 10.0.0. is IP-address prefix of your LAN. RELAYCLIENT="" means setting environment variable like that at invocation of antibadmail when smtp connection comes from corresponding address. Like qmail-smtpd, antibadmail assume that the client is located in LAN when the environment variable RELAYCLIENT is set, so that connection at that time must not be abusing. Antibadmail accepts all message when RELAYCLIENT set.
If you wrote rule database in /etc/smtp
, you have to
convert it to cdb-format as follows.
cd /etc tcprules smtp.cdb tmp < smtp
After starting tcpserver+antibadmail, try `telnet localhost smtp' to confirm it is running. If the SMTP greeting message of original smtp-daemon shows up, almost all goes well.
To record the rejecting/accepting result, add the following line to
/etc/syslog.conf
.
local1.info /var/log/smtp-stat
It is more desirable to add a notation for log rotation to
/etc/newsyslog.conf
(BSD) or
/etc/logrotate.conf
(Linux).
Antibadmail refers `datadir' database structure. Datadir is maildir-similar structure where an entity exists in a form of `file in a directory' instead of `line in a file'. By default, antibadmail referes three directories.
/var/qmail/control/badhelodir/
Contains files whose names are patterns of SMTP-HELO string for rejection
/var/qmail/control/badmailfromdir/
Contains files whose names are patterns of envelope sender for rejection
/var/qmail/control/badrcpttodir/
Contains files whose names are patterns of envelope recipient for rejection
Again, you can change the prefix /var/qmail/control
by
build time setting or environment variable $CONTROLDIR at running time.
A filename should be the form of one of as follows;
For badhelodir, badmailfromdir and badrcpttodir, reject all clients which send parameter same as `name'.
For badhelodir and badmailfromdir, reject all clients which send parameter whose domain ends with `.name'. That is, wildcard matching with `*.name'.
For badmailfromdir, reject all clients which send MAIL-FROM parameter whose domain part is the same as `@name'. That is, wildcard matching with `*@name'.
The policy of antibadmail is ``Don't inspect contents''.
However, as to badmail forwarded by (friendly) SMTP server, we can find rejection ground only in message header.
Antibadmail can reject mails by mail header pattern. Rejection by header is a `last resort', and can't be diverted once message header matches with a pattern even if the pattern is misspelled. Use with great care. Header inspection defaults to ON. To disable header check, set environment variable HEADERCHECK to 0 at invocation of antibadmail.
HEADERCHECK=0 tcpserver ..... antibadmail .....
When HEADERCHECK is enabled, antibadmail receives DATA, it reads header patterns from regular data-directory. The datadir structure for header rejection is little bit different from above. Datadir for one header pattern consists of as follows;
$CONTROLDIR/badhdrdir/FieldName/EntryName/p* $CONTROLDIR/badhdrdir/FieldName/EntryName/v*:VAR $CONTROLDIR/badhdrdir/FieldName/EntryName/errmsg
where FieldName is header-field name with all lower case, EntryName is arbitrary name for pattern set.
Any file whose name begins with `p' is evaluated as pattern to be compared with the value of FieldName. A pattern must be written in a line. Patterns more than one line are AND-ed sequentially left-to-right. Patterns in different files are OR-ed.
Any file whose name begins with `v' and ends with `:VAR' is evaluated only when environment variable `VAR' is set. You can specify very strict rule for particular hosts by which tcpserver sets environment variable VAR. Typically, you might set $REQPTR (see above) for those hosts which is located in unfamiliar country to you. You'd better have v-somename:REQPTR files in pattern directories.
SMTP error message to be sent for clients when their sending header matches with pattern.
Suppose you have been receiving many spams via smtp server, which is in the office you previously belonged. Messages to your old address are forwarded to current address. In case as this, antibadmail can reject forwarded spam by seeing headers. If your old server's FQDN is `oldserver.you.used', messages with these header can be assumed to be spam.
Received: from hogehoge.com (HELO oldserver.you.used) ....(1) or Received: from unknown .... by oldserver.you.used ....(2)
where `....' is any string. Both (1) and (2) are received header attached by oldserver. Let's think about (1) first. It is the typical received header of spam. So we define the first pattern as follows;
(HELO oldserer.you.used)
Why is this bad pattren? Because "HELO oldserver.you.used" was told by spamming server when it connects to oldserver.you.used. Sending opponent's name as HELO is typical spamming behavior.
Then, think about pattern for (2). It's as follows;
from unknown by oldserver.you.used
Note that pattern(2) is written in two lines so that both string ("from unknwn" and "by oldserver.you.used") must match with received header. Now define this rule set name as `foo'
--- File: $CONTROLDIR/badhdrdir/received/foo/ptn-1 --- (HELO oldserer.you.used) --- File: $CONTROLDIR/badhdrdir/received/foo/ptn-2 --- from unknwon by oldserer.you.used --- File: $CONTROLDIR/badhdrdir/received/foo/errmsg --- We cannot receive suspicious messages.
refuses the messages which have received-header that matches with "(HELO oldserer.you.used)", or matches with both "from unknwon" and "by oldserer.you.used", returning the SMTP error message of "We cannot receive suspicious messages.".
When you are aware of the power of header rejection, you might want to describe patterns more precisely. The first character of each line determines the matching method. There are five methods for matching.
Pattern line | Meaning |
---|---|
=STRING | Whole line is exactly same as STRING |
^STRING | Line is beginning with STRING |
$STRING | Line is ending with STRING |
/REGEX | Line is matching with regular expression REGEX |
:STRING | Line has the part which match with STRING exactly |
STRING | Same as above |
Note that all header field contents will be joined into one line, converted all lower case. Therefore all matching will be done in case-insensitive.
Regular expression engine is supplied by libc of your driving operating system. So it is different from that of Perl, Emacs-Lisp, (GNU)egrep which you may be experienced with. If you want to examine how regexp pattern matches with, use debugging mode of header module. It is obtained by typing this;
make h
Using h command interactively as follows.
./h Received: from hogehoge.blah.example.org (HELO oldserver.you.used) by oldserver.you.used
The `h' command acquires all patterns in $CONTROLDIR/badhdrdir/*/* and apply all patterns over given strings from stdin. To change badhdrdir, set that directory to environment variable BADHDRDIR.
Be aware that although regular expression is friendly, using regexp easily causes configuration errors. It is difficult enough to confuse system administrators. Absolutely NO errors for mail configurations!
You might want to reject all false `*@hotmail.com' mails. But you might want to receive `*@hotmail.com' from real hotmail server. In this case, do as follows;
touch /var/qmail/control/badmailfromdir/@hotmail.com
=.hotmail.com:allow,GOODMAILFROM="@hotmail.com"
If you want to receive any message from certain server, Set environment variable RELIABLECLIENT for the server.
=smtp.server.you.wantto.rely:allow,RELIABLECLIENT=""
Antibadmail stops all rejection check except extremely insecure parameter when RELIABLECLIENT is set.
If you or users of your SMTP server want to receive all email even if the sender's SMTP server has wrong DNS-record settings. Suppose when you apply web-shoping, auction, mail-magazine or so. Those sites as a whole are held in ill-mannered service provider. Many of them don't have correct settings of DNS(A and PTR record) nor SMTP-HELO. Althogh antibadmail reject emails from those incorrect servers by default, you can stop rejection upon certain receipient addresses.
You can make `soiled recipient address' as follows.
Create datadir for soiled recipients.
mkdir /var/qmail/control/soiledrcpttodir
Make the entry of recipient address for no rejection.
mkdir /var/qmail/control/soiledrcpttodir/local-foo@your.domain
Then antibadmail will pass all emails for `local-foo@your.domain'.
`Domain specific control' is also available. If you and/or unprivileged users on your server hold virtualdomain, @v.example.com for example, create directory with that name and touch any files whose names are local-part for which you want to omit spam control.
mkdir /var/qmail/control/soiledrcpttodir/@v.example.com cd /var/qmail/control/soiledrcpttodir/@v.example.com touch foo bar- ./-bar-baz ./'!bar-foo' ls !bar-foo -bar-baz bar- foo
In this case above, each address are treated as follows.
local-part | spam-inspection | receive/reject |
---|---|---|
foo | no (omitted) | receive |
bar-baz | yes | depends on other parameters |
bar-foo | no | REJECT |
bar-any | no (omitted) | receive |
Filenames are recognized as follows.
No spam inspection for name@domain.
-
Wildcard. No spam inspection for any name-*@domain. It should work fine with qmail's address extension.
-
name
DO spam inspection for name@domain.
Minus sign stands for `remove(-) from soiled entry'.
Note that, this doesn't mean all messages to
name will be delivered. They all will undergo
spam inspection. Note also that, this minus sign
can be combined with wildcard of `-
'.
!
name
Reject name@domain immediately even if it might be clean message.
ALL
Through all if local-part doesn't match any name in this directory.
Note that rejection avoidance don't occur when smtp client sends parameter which matches strictly with entry of one of badhelodir, badmailfromdir and badrcpttodir.
For qmail users and admininstrators of secondary SMTP server, it was long time worry to stop mails to non-existent recipient. Both qmail-smtpd and secondary SMTP server don't know the existence of recipient(RCPT TO) address. Now antibadmail can drop mails for non-existent recipient.
The recipient existence check is automatically done by antibadmail. If recipient mailbox DOES NOT EXIST SURELY on the host, antibadmail reject it. Note that antibadmail checks the availability of recipient addresses with unprivileged uid, therefore all directories that contain dot-qmail files should be world-cd'able(eXecutable). If you are using vpopmail, its default settings of virtual domain holding directories are not world-cd'able. In that case, chmod +x on those directories.
You can have running remote recipient checker. Currently this checker supports the case you are running qmail on primary SMTP server.
The `./qserver/' directory of the antibadmail source distribution contains the client/server scripts to check the existence of recipient on (remote)primary host. Two steps to set up. Suppose you administrate mail domain `@example.com' and its primary SMTP server has IP-address[192.168.1.1].
cd qserver; make
To allow client to connect, add client's IP-address to LOCAL.tcprule file amd type `make' again.
./run
If you have running daemontools on the host,
ln -s $PWD /service
is enough.
cd qserver make all install mkdir $CONTROLDIR/rq
Create $CONTROLDIR/rq/example.co.jp
with content as below;
#!/bin/sh rq 192.168.1.1
Then antibadmail will automatically execute
rq/example.co.jp
when it receives
*@example.co.jp as RCPT TO parameter. If the script
returns 0, antibadmail reject request of SMTP-client.
You had better make sure the `run' script works fine and tcp connection from client is surely allowed on primary SMTP host by doing as follows:
secondary% telnet 192.168.1.1 9999 Trying 192.168.1.1... Connected to tmax. Escape character is '^]'. foobarbazhogehoge NG root OK Maybe
Note that antibadmail NEVER REJECT non-existent recipient WHEN IT FAILS TO CONNECT TO REMOTE `./run' server. Please make sure well of `./run' server's availability beforehand.
When each variables in this table is set, antibadmail alter the action. These variables can be set via antibadmail start-up script or tcpserver according to client's IP-address/hostname.
Variable | Action when set | Negation |
---|---|---|
RELAYCLIENT RELIABLECLIENT | Accept all message except when the client sends seriously bad parameter. | no |
CHECKHELODOMAIN CHD | Expect HELO paramter has correct DNS record | yes |
REJECTNODOTHELO |
Reject HELO without dots. | yes |
REJECTIPINHELO |
Reject HELO which contains client IP address that is presumably hostname with dynamically allocated IP address. | yes |
PERMIT_STATIC |
In the case of REJECTIPINHELO , permit if client's
PTR-record has substring "static". | yes |
PASSKNOWNNODOTHELO |
By default, antibadmail rejects no-dot HELO from unknwon host. Set this variable when overlook it. | yes |
PASSUNKOWNIPHELO |
By default, antibadmail rejects IP-address formed HELO from unknown host. Settng this variable passes it. | yes |
NOMFDCHECK |
Stop MAIL-FROM domain check. | yes |
PERMIT_NXRCPT |
By default, antibadmail disconnect session when clients sends non-exixtent RCPT for protection from `random dictionary attack'. When a good user sends to multiple recipients with some of them misspelled, the SMTP session will end in rejection. To rescue this, set this variable. But it is subject to dictionary attack. | yes |
BADHOST | Reject. | yes |
NOTERM |
Keep SMTP session after it is proved to be spam. | yes |
QUICKREJECT |
Reset TCP quickly before all SMTP parameters are accepted. | yes |
Negating effect of each variable can be accomplished by set its value
to "0"
.
The public spam rejection database is available via anoncvs.
cvs -d :pserver:anonymous@yatex.org:/qmail co spamdb
Or just type
make spamdb
In the top directory of antibadmail source.
This database is in plain text format, not datadir structure. You can convert plain text database to datadir struct by f2d command, which comes with antibadmail package.
You can convert, for example, badmailfrom file from spamdb to badmailfromdir/ structure by executing f2d as follows.
f2d -d ./badmailfromdir badmailfrom
Or just type `make' in spamdb/ directory.
Note that ./badmailfromdir/ and badmailfrom is accessible from working directory.
cd $CONTROLDIR ln -s $SPAMDBDIR/bad*dir .
Finally, create a Makefile to merge your site's smtp-rule and spamdb's smtp-badhost referring an example Makefile in spamdb/Makefile.tcprule.
TR = tcprules OWNER = qmaild #OWNER = abm SRC = smtp smtp-badhost all: smtp.cdb smtp.cdb: ${SRC} (cat ${SRC} ; \ echo all:allow ) | ${TR} $@ smtp.tmp # chown ${OWNER} smtp.cdb
Locate this as Makefile in smtp starting directory(eg. /service/smtpd).
cd /service/smtpd ln -s $CONTROLDIR/smtp-badhost make
Any database which has multiple records in a file always suffers from these difficulties;
With `Datadir' structure, there's no need for file locking because all the updation on an entity can be done without referring any other entities. All addition/deletion operation is automatically atomic because they are file creation or file deletion.
There is Mailing List for discussing about development and trouble shooting related to antibadmail. Please join it to nourish antibadmail!
To join the antibadmail users ML(abmusers), send your self introduction(more than 5 lines) to abmusers@ml.gentei.org with subject="subscribe". Here is an example.
To: abmusers@ml.gentei.org
Subject: subscribe
--
(Self-introduction more than 5 lines)
I'm newbie administrator of FOO company.
I love email!
I don't like spam!
---
YourMail@foo.comp....
Do not mimic above. :)
This program is free software and comes with absolutely NO WARRANTY. The author is not responsible for any possible defects caused by this software. You can freely modify this program for your convenience. But if you want to publish modified program, please tell me before announcement. Take it easy to write me comments and bug-reports.
yuuji@gentei.org
Sorry, Japanese only below.