Santronics Software, Inc.,


The Wildcat! SMTP mail server now supports the ability to pre-process incoming mail before it is accepted for delivery by passing the email to a wcBASIC wcx application called smtpfilterhookloader.wcx

To get a better understanding on the mail flows and how a mail filter application can be used for Anti-Spam, Anti-Virus, see Using Anti-Virus/Spam Software

How does it work:

To enable this feature, go to:


and set the options:

[X] Enable SMTP Mail Filter Agent Operations
[X] Enable Receiver Bin

In general, when SMTPFILTER is not enabled,  wcSMTP will receive email in the router prespool directory where the Wildcat! SMTP router will determine how to handle the email (local delivery vs relay to another site).  

When SMTPFILTER is enabled,  wcSMTP will receive email in directory called "new" located off the primary host spool directory, i.e,   \wc6\spool\santronics\new. 

The goal of receiving the mail in this "new" directory is to allow the SMTPFILTER  process to analyze the mail.   wcSMTP does this by calling the smtpfilterhookloader.wcx application.

IMPORTANT: If smtpfilterhookloader.wcx  is not found and the Receiver Bin checkbox is checked, the email remains in the NEW directory.   WCSMTP will send a positive 250 response code to the sender indicating the mail was accepted, however, it will remain in the NEW directory.  No further processing is done. 

When email is received, the email is passed to the SMTPFILTER WCX application with complete email information allowing the filter to analyze the email before a response is sent back to the mail sender.

WCSMTP is only interested in one thing from the WCX:  whether to "Accept" or "Reject" the email.  So the WCX has the ultimate responsibility of returning the proper GlobalResult return code.  

If the mail is to be accepted, the WCX will return a value of one.  In this case,   wcSMTP will finalize the delivery by moving the email to the router prespool directory and send a positive 250 mail accepted response code to the sender. 

If the mail is to be rejected, the WCX should return zero. In this case, WCSMTP will delete the email with no further processing and send a 451 rejection response code to the sender.  

If the WCX wishes to accept the email but tell wcSMTP to not move it to the router prespool directory, then the WCX should return a value of 2 which means accept, but keep the email in the NEW directory.

SMTPFILTER Multi-Hook Loader:

SmtpFilterHookLoader.wcx is now provided with the base Wildcat! package for all our current CD and AUP subscribers.  

SmtpFilterHookLoader.wcx is designed to run multiple SmtpFilter-XXXXX.wcx applications so that you can have multiple mail filtering rules.    Read the file data\smtpfilterhookloader.ini  provided with the application to setup multiple filters.

The following is a sample SMTPFILTER application illustrating the basic outline for a smtpfilter hook.  Visit the Developer's Corner to see other examples of SMTPFILTER applications.

// file   : smtpfilter-example1.wcc
// Note: The filter is not processed unless the option in
// WCCONFIG | SMTP SERVER setup is enabled:
//    [X] Enable Receiver Bin
// Parameter 1 (paramstr(1) contains field=value information about
// the message. Use the GetParamXXX() functions to read the values.
// The possible fields are:
// field description
// ------ ------------------------------
// uid connected user id, if authenticated
// psf email temporary file name
// rsp router prespool directory
// ip connection client ip address
// hdn host domain name of ip, could be unknown if RDNS is off
// cdn envelope HELO or EHLO domain name
// from envelope MAIL FROM: address
// rcpt envelope RCPT TO: recipient address (first one)
// ruid local user recipient user id for RCPT TO:, if any
// trcpt total recipients
// brcpt total bad recipients
// You can access the field using the GetParamXXX() function like so:
// dim fname as string = GetParamStr(paramstr(1),"psf")
// dim rcpt as string = GetParamStr(paramstr(1),"rcpt")
// To make it easier to read this information, you can use the function
// sfInitializeHook() to prepare the above information in a TSmtpData
// record structure. See example below.
// After the filter analyzes and information, it must set global variable
// called GlobalResult must in order to give feedback to the smtp server:
// GlobalResult Comment
// ------------ -------
// 1 or -1 pass
// 0 rejected, email discarded
// 2 pass, however email stays in receiver bin
// 3 pass, however email was moved/deleted by filter
// However, it is suggested to use the sfSetGlobalResult() function to
// set the final result and also indicate if this is the final rule in
// a multi-smtpfilter rule filtering setup.
// sfSetGlobalResult(SF_ACCEPT) 		// accept email  1
// sfSetGlobalResult(SF_DISCARD,SF_ENDRULES) 	// reject email, 0
// sfSetGlobalResult(SF_KEEP,SF_ENDRULES) 	// keep email, 	 2
// sfSetGlobalResult(SF_DELETED,SF_ENDRULES) 	// delete email, 3

#include <smtpfilterhlp.wch>

// All smptfilter hooks should begin with the following:

Dim sd as TSmtpData

sfLog(lchInfo,"auid : "+str(sd.auid)) 	// user id, if authenticated
sfLog(lchInfo,"fname: "+sd.fname) 	// emailfile name
sfLog(lchInfo,"rpath: "+sd.rpath) 	// router prespool path
sfLog(lchInfo,"ip   : "+sd.ip) 		// client ip address
sfLog(lchInfo,"helo : "+sd.helo) 	// client domain name
sfLog(lchInfo,"host : " 	// host domain name
sfLog(lchInfo,"from : "+sd.from) 	// envelope from address
sfLog(lchInfo,"rcpt : "+sd.rcpt) 	// envelope recipient address
sfLog(lchInfo,"ruid : "+str(sd.ruid)) 	// recipient user id
sfLog(lchInfo,"trcpt: "+str(sd.trcpt)) 	// total recipients
sfLog(lchInfo,"brcpt: "+str(sd.brcpt)) 	// total bad recipients

// Set GlobalResult to finalize the handling of the message file
// based on the analysis of the email information.