最近在做一个小插件里边有个需求是判断邮箱地址是否真实存在,防止插件给不存在的邮箱地址发送邮件。
以往都是对邮箱地址的格式进行判断,这种意义不大,导致了很多邮件被退回而被封SMTP。后来发现可以利用TCP对邮件服务器进行发送邮件测试,原理和正常发送邮件一样,只是在最后一步提前退出流程就能达到验证目标邮箱的真实性的目的。
经过测试QQ邮箱,成功率大概在90%左右,直接上代码:
TcpClient tClient = new TcpClient("mx1.qq.com", 25);
string CRLF = "\r\n";
byte[] dataBuffer;
string ResponseString;
NetworkStream netStream = tClient.GetStream();
StreamReader reader = new StreamReader(netStream);
ResponseString = reader.ReadLine();
dataBuffer = BytesFromString("HELO anan.com" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
ResponseString = reader.ReadLine();
//如果需要登录验证则使用AUTH LOGIN命令登陆
dataBuffer = BytesFromString("MAIL FROM:<web@anan.com>" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
ResponseString = reader.ReadLine();
ResponseString = null;
dataBuffer = BytesFromString("RCPT TO:<" + textBox_MailAddress.Text.Trim() + ">" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
//await Task.Delay(5000);
//以下循环100次对数据进行验证
for (int i = 0; i < 100; i++)
{
ResponseString = reader.ReadLine();
if (ResponseString.Contains("250 OK 1") || ResponseString.Contains("550"))
{
break;
}
}
//这里开始判断
if (GetResponseCode(ResponseString) == 550)
{
//不存在
}
else if (ResponseString == "250 OK 1")
{
//存在
}
else
{
//其他处理
}
dataBuffer = BytesFromString("QUITE" + CRLF);
netStream.Write(dataBuffer, 0, dataBuffer.Length);
tClient.Close();
这里代码重要的是在发送RCPT TO
后一定要等待,最好是循环判断是否返回250 ok
或者550
。