I have been using the SURBLE script and it filters out a lot of SPAM. I noticed that the SPAM I still receive either has an invalid sender address or an empty sender address. (When I disable "allow empty sender address" some servers who do active sender validation reject my mail.) Therefore I put this check in a script. As for the active sender validation I wrote a program in C# with "Microsoft Visual C# 2005 Express Edition" (free).
The input to the executable is "sTo sFrom sMX sHostname"
sTo = address to validate
sFrom = address to identify yourselve
sMX = a comma seperated list of Mail servers handling sTo
sHostname = the server internet hostname
The output is an integer error code
0 = valid address
anything else, no valid address (see source)
I named the executable ValidateEmail.exe
If you want to use the script, modify the paths in the script to point to a valid location (see script)
I Have my source here:
ftp://vandelande.com/ValidateEmail/
This is the script
Code: Select all
Sub OnAcceptMessage(oClient, oMessage)
' add strSource = "[YASU]" in the messages rejected by SURBLE script
strSource = "[none]"
' Insert SURBLE script
' End SURBLE script
dim oUtil
Set oUtil = CreateObject("hMailServer.Utilities")
'Check for an empty sender address
If InStr(1 , oMessage.FromAddress , "@" , 1 ) >= 1 Then
Result.Value = 0 'deliver the message
Else
Result.Value = 1 'reject the message
strSource = "[No sender]"
End If
If Result.Value = 0 Then
mail = oUtil.GetMailServer(oMessage.FromAddress)
mail = Replace(mail, " ", "", 1, -1, 1)
' sFrom = "ValidateEmail@yourdomain.com"
sFrom = ""
sTo = oMessage.FromAddress
sMX = mail
'SLocalHost = "your domain"
slocalHost = "yourdomain.com"
'sLogDir is not used yet
sLogDir = "c:\logs\"
ValidSender = oShell.Run("E:\hMailServer\Events\ValidateEmail.exe " & sTo & " " & sFrom & " " & sMX & " " & sLocalHost & " " & sLogDir , 0, TRUE)
If ValidSender = 0 Then
strSource = "[valid sender address] " & ValidSender
Else
Result.Value = 1
strSource = "[no valid sender address] " & ValidSender
End If
End If
' Write a log file of the results
If Result.Value = 1 Then
SET oFs = CreateObject("Scripting.FileSystemObject")
SET oFil = ofs.OpenTextFile("C:\Logs\hMailserver\rejected_" & Date() & ".log", 8, True) 'open for append, create if not exists
oFil.WriteLine(Now() & " Mail From : " & "<" & oMessage.FromAddress & "> " & strSource )
oFil.Close
SET oFil = Nothing
SET oFs = Nothing
Else
SET oFs = CreateObject("Scripting.FileSystemObject")
SET oFil = ofs.OpenTextFile("C:\Logs\hMailserver\accepted_" & Date() & ".log", 8, True) 'open for append, create if not exists
oFil.WriteLine(Now() & " Mail From : " & "<" & oMessage.FromAddress & "> " & strSource )
oFil.Close
SET oFil = Nothing
SET oFs = Nothing
End If
End Sub
Code: Select all
Set oMessage = CreateObject("hMailServer.Utilities")
Set oShell = CreateObject("WScript.Shell")
' sTo = "busscranford@legislator.com"
sTo = "aideblast@columnist.com"
sTo = "alginateboogie@catlover.com"
sTo = "cliqueambulatory@scientist.com"
sFrom = "" ' add your email address
mail = oMessage.GetMailServer(sTo)
mail = Replace(mail, " ", "", 1, -1, 1)
sMX = mail
sLocalhost = "yourhost" ' add your hostname
sLogDir = "E:\C#\ValidateEmail\ValidateEmail\bin\Release\"
intRetVal = oShell.Run("ValidateEmail.exe " & sTo & " " & sFrom & " " & sMX & " " & sLocalhost & " " & sLogDir, 0, TRUE)
WScript.Echo intRetVal
Code: Select all
#define TRACE_ON
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
using System.Net.NetworkInformation;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
private enum SMTPResponse : int
{
CONNECT_SUCCESS = 220,
GENERIC_SUCCESS = 250,
DATA_SUCCESS = 354,
QUIT_SUCCESS = 221
}
static bool timeout;
//[Conditional("TRACE_ON")]
static int Main(string[] args)
{
string today = DateTime.Today.ToShortDateString().Replace('/', '-');
string now = DateTime.Now.ToLongTimeString();
string To = "<" + args[0] + ">";
string From = "<" + args[1] + ">";
string MX = args[2];
string localhost = args[3];
//string LogDir = args[4];
MX = MX.Trim(',');
//String FileName = LogDir + "debug-" + today + ".log";
// check for a "no-reply" user
string[] users = To.Split('@');
string user = users[0];
user = user.ToLower();
if ((user == "no-reply") || (user == "noreply"))
return 0;
// turn the MX host IP's into an array
string[] hosts = MX.Split(',');
string host;
int i = 0;
// try a maximum of 3 MX servers (when available)
while (i < 3)
{
try
{
host = hosts[i];
try
{
IPEndPoint endPt = new IPEndPoint(IPAddress.Parse(host), 25);
Socket tcpSocket = new Socket(endPt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// SMTP time-out discussion (use 5 minuts)
// http://www.freesoft.org/CIE/RFC/1123/109.htm
// Set the timeout for synchronous receive methods to
// 1 second (1000 milliseconds.)
tcpSocket.ReceiveTimeout = 300000;
// Set the timeout for synchronous send methods
// to 1 second (1000 milliseconds.)
tcpSocket.SendTimeout = 300000;
// Set the Time to live, TTL
// to 64 hops.
tcpSocket.Ttl = 128;
// Set receive buffer size
// to 1023 bytes.
//tcpSocket.ReceiveBufferSize = 1023;
tcpSocket.Connect(endPt);
//Attempting to connect
if (!Check_Response(tcpSocket, SMTPResponse.CONNECT_SUCCESS))
{
if (timeout)
{
tcpSocket.Close();
}
else
{
tcpSocket.Close();
return 2;
}
}
//HELO server
//Senddata(s, string.Format("HELO {0}\r\n", Dns.GetHostName()));
Senddata(tcpSocket, string.Format("HELO {0}\r\n", localhost));
if (!Check_Response(tcpSocket, SMTPResponse.GENERIC_SUCCESS))
{
if (timeout)
{
tcpSocket.Close();
}
else
{
tcpSocket.Close();
return 3;
}
}
//Identify yourself
//Servers may resolve your domain and check whether
//you are listed in BlackLists etc.
Senddata(tcpSocket, string.Format("MAIL From: {0}\r\n", From));
if (!Check_Response(tcpSocket, SMTPResponse.GENERIC_SUCCESS))
{
//Senddata(tcpSocket, "QUIT\r\n", sw);
//Check_Response(tcpSocket, SMTPResponse.QUIT_SUCCESS, sw);
if (timeout)
{
tcpSocket.Close();
}
else
{
tcpSocket.Close();
return 4;
}
}
Senddata(tcpSocket, string.Format("RCPT TO: {0}\r\n", To));
if (!Check_Response(tcpSocket, SMTPResponse.GENERIC_SUCCESS))
{
//Senddata(tcpSocket, "QUIT\r\n");
if (timeout)
{
tcpSocket.Close();
}
else
{
tcpSocket.Close();
return 5;
}
}
Senddata(tcpSocket, "QUIT\r\n");
if (!timeout)
{
Check_Response(tcpSocket, SMTPResponse.QUIT_SUCCESS);
tcpSocket.Close();
return 0;
}
}
catch
{
}
}
catch
{
}
i++;
}
return 100 + i;
}
private static void Senddata(Socket tcpSocket, string msg)
{
byte[] _msg = Encoding.ASCII.GetBytes(msg);
tcpSocket.Send(_msg, 0, _msg.Length, SocketFlags.None);
}
private static bool Check_Response(Socket tcpSocket, SMTPResponse response_expected)
{
string sResponse;
int response;
int count = 0;
byte[] bytes = new byte[1024];
timeout = false;
// wait a maximum of 5 miniuts
while ((tcpSocket.Available == 0) && (count < 3000))
{
System.Threading.Thread.Sleep(100);
count++;
}
tcpSocket.Receive(bytes, 0, tcpSocket.Available, SocketFlags.None);
sResponse = Encoding.ASCII.GetString(bytes);
response = Convert.ToInt32(sResponse.Substring(0, 3));
if (response != (int)response_expected)
return false;
return true;
}
}
}
Code: Select all
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
using System.Net.NetworkInformation;
using System.IO;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
private enum SMTPResponse : int
{
CONNECT_SUCCESS = 220,
GENERIC_SUCCESS = 250,
DATA_SUCCESS = 354,
QUIT_SUCCESS = 221
}
static bool timeout;
static bool debug = true;
static int Main(string[] args)
{
string today = DateTime.Today.ToShortDateString().Replace('/', '-');
string now = DateTime.Now.ToLongTimeString();
string To = "<" + args[0] + ">";
string From = "<" + args[1] + ">";
string MX = args[2];
string localhost = args[3];
//string LogDir = args[4];
MX = MX.Trim(',');
//String FileName = LogDir + "debug-" + today + ".log";
String FileName = "debug.log";
StreamWriter sw = new StreamWriter(FileName, true); // append
if (debug) sw.Write("Start : {0} : {1} {2}" + "\r\n", now, today, To);
// check for a "no-reply" user
string[] users = To.Split('@');
string user = users[0];
user = user.ToLower();
if ((user == "no-reply") || (user == "noreply"))
return 0;
// turn the MX host IP's into an array
string[] hosts = MX.Split(',');
string host;
int i = 0;
// try a maximum of 3 MX servers (when available)
while (i < 3)
{
try
{
if (debug) sw.Write(" i = {0}, ", i);
host = hosts[i];
if (debug) sw.Write(" host = {0} \r\n", host);
try
{
IPEndPoint endPt = new IPEndPoint(IPAddress.Parse(host), 25);
Socket tcpSocket = new Socket(endPt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// SMTP time-out discussion (use 5 minuts)
// http://www.freesoft.org/CIE/RFC/1123/109.htm
// Set the timeout for synchronous receive methods to
// 1 second (1000 milliseconds.)
tcpSocket.ReceiveTimeout = 300000;
// Set the timeout for synchronous send methods
// to 1 second (1000 milliseconds.)
tcpSocket.SendTimeout = 300000;
// Set the Time to live, TTL
// to 64 hops.
tcpSocket.Ttl = 128;
// Set receive buffer size
// to 1023 bytes.
//tcpSocket.ReceiveBufferSize = 1023;
tcpSocket.Connect(endPt);
if (debug) sw.Write(" Open connection {0} \r\n", host);
//Attempting to connect
if (!Check_Response(tcpSocket, SMTPResponse.CONNECT_SUCCESS, sw))
{
if (timeout)
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
}
else
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
if (debug) sw.Close();
return 2;
}
}
//HELO server
//Senddata(s, string.Format("HELO {0}\r\n", Dns.GetHostName()));
Senddata(tcpSocket, string.Format("HELO {0}\r\n", localhost), sw);
if (!Check_Response(tcpSocket, SMTPResponse.GENERIC_SUCCESS, sw))
{
if (timeout)
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
}
else
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
if (debug) sw.Close();
return 3;
}
}
//Identify yourself
//Servers may resolve your domain and check whether
//you are listed in BlackLists etc.
Senddata(tcpSocket, string.Format("MAIL From: {0}\r\n", From), sw);
if (!Check_Response(tcpSocket, SMTPResponse.GENERIC_SUCCESS, sw))
{
//Senddata(tcpSocket, "QUIT\r\n", sw);
//Check_Response(tcpSocket, SMTPResponse.QUIT_SUCCESS, sw);
if (timeout)
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
}
else
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
if (debug) sw.Close();
return 4;
}
}
Senddata(tcpSocket, string.Format("RCPT TO: {0}\r\n", To), sw);
if (!Check_Response(tcpSocket, SMTPResponse.GENERIC_SUCCESS, sw))
{
//Senddata(tcpSocket, "QUIT\r\n", sw);
//Check_Response(tcpSocket, SMTPResponse.QUIT_SUCCESS, sw);
if (timeout)
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
}
else
{
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
if (debug) sw.Close();
return 5;
}
}
Senddata(tcpSocket, "QUIT\r\n", sw);
if (!timeout)
{
Check_Response(tcpSocket, SMTPResponse.QUIT_SUCCESS, sw);
if (debug) sw.Write(" Close connection {0} \r\n", host);
tcpSocket.Close();
if (debug) sw.Close();
return 0;
}
}
catch
{
}
}
catch
{
}
i++;
}
if (debug) sw.Write("End \r\n");
if (debug) sw.Close();
return 100 + i;
}
private static void Senddata(Socket tcpSocket, string msg, StreamWriter sw)
{
byte[] _msg = Encoding.ASCII.GetBytes(msg);
sw.Write(" msg = {0}" + "\r\n", msg);
tcpSocket.Send(_msg, 0, _msg.Length, SocketFlags.None);
}
private static bool Check_Response(Socket tcpSocket, SMTPResponse response_expected, StreamWriter sw)
{
string sResponse;
int response;
int count = 0;
byte[] bytes = new byte[1024];
timeout = false;
// wait a maximum of 5 miniuts
while ((tcpSocket.Available == 0) && (count < 3000))
{
System.Threading.Thread.Sleep(100);
count++;
}
/*if (tcpSocket.Available == 0)
{
if (debug) sw.Write(" timeout = {0} \r\n", count);
timeout = true;
return false;
}
*/
tcpSocket.Receive(bytes, 0, tcpSocket.Available, SocketFlags.None);
sResponse = Encoding.ASCII.GetString(bytes);
response = Convert.ToInt32(sResponse.Substring(0, 3));
if (debug) sw.Write(" response = {0} \r\n", response);
if (response != (int)response_expected)
return false;
return true;
}
}
}