关于批量验证SMTP邮箱有效性问题的分析2014-10-11 11:02:03

( 4人已投票,[高质量] )
分享:
31.3K

SMTP邮箱验证一种很常见的功能究竟该何判断test@domain.com邮箱有效性呢?

网上也有一些邮件验证的网页,但都是一次只能验证一个,无法批量验证其有效性。

想要自已做匿名验证与发送邮件该怎么做呢,网上关于smtp的模式也有不少解释,

但是具体实现难免还有很多问题,这就是常说的Easy said than done!本文主要采用VC/MFC手段实现

Okay,开始吧,首先我们用shell脚本可以先实地测一下

>nslookup
>set type=mx
>baidu.com

接下来你会看到关于baidu的服务情况(不过百度好像没有提供邮箱服务,但服务确实存在)


你可再改用QQ.com试下

你会发现提供服务的在第四行都会有个exchanger = mx2.qq.com  (次序每次都会略有变动,都可用,可以试试)

>exit
//try again
>telnet mx2.qq.com 25(端口全是25)
//会进入到欢迎页面
220 newmx66.qq.com MX QQ Mail Server
>helo lsdkfjlksdjfl //helo 后面是不检测的
250 new....//250表示成功 5开头全是有问题...550 510...
>mail from:<wewewe@163.com>
//这里要先用别的邮箱名,不然就要auth login验证了
250 sdlkfjslfdjlkj
>rcpt to:<11123546@qq.com>
//你上QQ得就得验证QQ邮箱,你用别的试试Bad address syntax...
250 sdfsdfdsfdsf
>rcpt to:<dflkj4sdf3sdfsdf@qq.com>
550 sdfksdfjsldkfj //550说明邮箱不存在

再往下就是data输入发送的数据了记得以 .  结尾 发送的包括附件什么的网上都有具体说明,此处先不讨论


下面用vc来实现

我用基于对话框实现对邮箱地址可用性验证

里面关于Tab控件也挺烦人,不过解决后写了我的第一篇blog这是第二篇,哈哈,虽然三天两个人访问无一人留言,可是我还是要继续写啊

为了搞不清楚的新手,也方便我以后查看呐

具体实现细节也太多了,我只说些重点的,等功能加齐了界面不丑了,啥时也共享给csdn的网友们

首先是输入一个邮箱地址(abc@qq.com)//先这样做,完事再扩展读txt邮箱地址列表,简单

把地址顺@断成两部分

CString st,name,com;
st="abc@qq.com";
int pos=st.find('@',0);
name = st.Mid(0,pos);
com = st.Mid(pos+1,st.GetLength());

下面要登录到这个com的服务器去

但是要调用shell脚本有点小麻烦

当然最主流的是用CreateProcess新建进程

然后进程间通信用通道重定向,邮槽啥的我暂时也没研究,新手嘛,慢慢来

CString sd;
sd.Format("cmd /c nslookup -qt=mx %s > test.txt",com);
//这儿隐藏调用且把结果存为当前目录下的一个txt
BOOL  res  =  CreateProcess(NULL,
//每次这样调用会删除先前的内容插入新的内容
sd.GetBuffer(sd.GetLength()),
NULL,
NULL,
NULL,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
NULL,
NULL,
&si,
&pi);
if  (TRUE  ==  res)
{
WaitForSingleObject(pi.hProcess,  INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}else{
MessageBox("sorry,failed");
}

//下面要把文件的第四行给读出来

CString strSmtpAddress,tmp;
char buffer[100];
int i(0);
FILE * file =fopen("test.txt","r");
 while (!feof(file)) {
 if (fgets(buffer, 128, file) != NULL) {
  i++;
  if(i==4)
 break; 
 }
}
fclose(file);
strSmtpAddress.Format("%s",buffer);//不知还有没有比这更好的办法,- -!
int pos = strSmtpAddress.Find("exchanger",0);
tmp = strSmtpAddress.Mid(pos+12,strSmtpAddress.GetLength());
tmp.TrimRight();//右面有空格/t得去掉,不然会出问题
//tmp就是那个服务地址了就像最顶上的mx2.qq.com
//启动线程
CThread th;
th.startThread();

关于线程,我要说几句了,线程很简单,用线程启动CSocket

线程实现

UINT __cdecl MyControllingFunction( LPVOID pParam ) //定义线程一个参数
{
 CSocker csc;
 csc.Sock_Con(); //在线程函数里启动Socket
 return 1;
}
CThread::startThread()
{
 CProgressCtrl m_pro;
 AfxBeginThread(MyControllingFunction,&m_pro);
}

///////////////////////////////////////////////////////////////

CSocket实现五步走

AfxSocketInit()//初始化
Create() //创建对象
connect//连接
Send,Reveive//收发//这儿可以加while(1)实现多发送
aSocket.Close()//关闭
//想用Socket这些必须得会用,下面是我的实现方式,虽然不成熟,
//但至少能工作了,哈哈,慢慢改进吧,主要是想说明工作流程
 CSocker::Sock_Con()
 {
 AfxSocketInit();
 CSocket aSocket;
 CString strIP ;
 strIP= CPublic::strTempDomain;//我用全局传IP了其实就是刚得到的那个第四行类似mx2.qq.com的东西,还记得不
 CString strPort="25";//这端口固定了
 if(!aSocket.Create())
 {
  char szMsg[1024] = {0};
  sprintf(szMsg, "Connction failed! %d", aSocket.GetLastError());
  AfxMessageBox(szMsg);
 }
 int nPort = atoi(strPort);
 if(aSocket.Connect(strIP, nPort))
 {
  CString strText;
  CString helo,mailfrom,rcpto;
  helo = "HELO verify-email.org/r/n";//选一个不会有人注册的歪门邮址是个不为人知的小技巧(为此得困扰许久)
  mailfrom = "MAIL FROM:<check@verify-email.org>/r/n";//别用QQmail from去查qq用户的邮址,那样得登录麻烦
  rcpto = "RCPT TO:<"+CPublic::strTempAddress+">/r/n";//登录还是用code64编码登录,烦死你,转换都不好找地方
  int i;
  i = 0;
while (1)//这儿用i定义发三次helo/ mail from/ rcpt to
{
 if(i==0){
 strText = helo;}
 else if(i==1){
 strText = mailfrom;}
 else{
 strText = rcpto;}
char szRecValue[2048] = {0};
aSocket.Send(strText, strlen(strText));
Sleep(500);//这儿我调试了,发现必须得加,不加的话全是250或是很随机,初次用的可要注意线程while问题,许多都出在没有Sleep上,
aSocket.Receive((void *)szRecValue, 2048);//因为太快了,瞬间发三条,其实一条都没返回,
Sleep(100);
if(i==2){    
CPublic::strTempRecv = szRecValue;
AfxMessageBox(CPublic::strTempRecv);//这会弹出结果
}
 if(i>=2)
 break; 
i++;
}
 }
 else
 {
  char szMsg[2048] = {0}; 
  sprintf(szMsg, "failed: %d", aSocket.GetLastError()); 
  AfxMessageBox(szMsg);
 }
 aSocket.Close();
}

到这儿算是差不多了,实现了一个邮箱的验证,无论你是哪个网址的准确性有保证

但是很明显,到实用还差很远,因为我少了很多追踪异常处理

例如用户输入abc@163163.com这样可能会报错,还要对线程数进行

GetExitCodeThread(this,word);
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);

之类的,都要加的,验证能验了,发送之类的也就直接加在Socket就行了;

特别是扩展N多邮件时候(我测过10W条数据),线程会太多,可以控制在50-100个左右,那时的查询速度应该还是很可观的

具体一定还有很多,自行添加处理

//特殊说明,在对大量的国外邮箱时需装vpn,不然会有很高的误差,你懂的






头像

snowcoal
  • C++
  • smtp邮箱验证
  • 邮箱有效性验证

收藏到我的私密空间

标题:关于批量验证SMTP邮箱有效性问题的分析

作者:花花世界

你暂未登录,请登录后才可收藏至您的私密空间 确认取消
雪炭网

键盘操作 更便捷 -雪炭网雪中送炭-乐趣无限

如果本站的内容有幸帮助到了您,建议您了解一下当页的广告内容哦,我们的进步离不开您的支持,Thank you~