欢迎光临
我们一直在努力

编程实现邮件地址有效性检测-.NET教程,Asp.Net开发

建站超值云服务器,限时71元/月

编者按:检测邮件地址的有效性可应用于防止垃圾邮件、用户非法注册等方面,本文将以编程的方式进行探讨,相信能给大家一些启示。

编程实现邮件地址有效性检测

文/brain

这个vb6com组件提供了一项即时邮件查询的功能。它有效的避免了向一个不存在的账户发送邮件的情况。例如,在asp页面里面检查用户输入的邮件地址是否正确,并避免在你的用户数据库里面存储相关的错误信息。

主要内容

工作原理

让我们首先来看一下这个组件是如何进行工作的。

首先给定一个e-mail地址(例如:someone@somewhere.com),然后它会执行如下的步骤:

1、  将用户名(someone)从域名(somewhere.com)中分离出来;

2、  在dns(域名服务器)上进行查询:域名是否可用;

3、  如果dns做出响应,它将在服务器上对mx进行查询(mail exchanger邮件交换服务器),并试着与在这个域中每一个mx建立会话,直到建立会话成功;

4、  通过使用smtp协议,它使用vrfy命令和mail handshake(helo,mailt from,rcpt to)来验证用户名在该域中的存在;

5、  随后组件将返回测试的结果,并给出四种可能的结果:

l     “域”不存在。服务器做出否定响应。

l     “域”存在,但是无法查询用户名(见注释)。服务器做出部分确认响应。

l     “域”存在,但是用户名不存在。服务器做出否定响应。

l     “域”和用户名都存在。服务器做出完全确认响应。

注释:

如果“域”存在,但是mx(邮件交换服务器)并不存在于该域中(典型特征是二级域名由isp掌握着),这样通过smtp协议将会无效,应为那些服务器被指派去接受子域中的邮件,并且根本不会检查用户名。所以组建的程序设计,从这里跳出并返回出部分确认响应。

组件特征

l   在本地机器上查找dns。所以必须保持计算机与互联网的连接以确保组建的正常工作

l   通过simplednsrosolover组件(见credits)发送dns请求

l   使用upd协议接收dns响应

l   经过标准的winsock.ocx接口,建立smtp会话

l   提供小型的可执行文件(编译为一个小于50kb的activex dll 动态连接库文件)

l   无任何用户接口,需要activex组建支持的语言(例如,vbscript, asp, vc++等等)

l   使用vb6.0 service pack 4(已测试) 环境下编译,当然也可以在以前的支持winsock.ocx的vb版本中编译(例如vb5.0)

安装方法

l   将压缩包释放到你选定的目录中;

l   将vfabemailutils.dll拷贝到你的系统目录下:

对于windows nt:c:\winnt ystem32\

对于windows 9 x:c:\windows ystem\

l   在注册表中注册组件:

在运行中输入:regsvr32 c:\winnt ystem32\vfabemailutils.dll

l   重要提示:

为确保组件的正常运行,你必须安装simple dns resolver v1.0(emmanuel kartmann’s)。相关信息,请看下面的credits。

使用方法

l   创建一个组建的应用实例

l   加入属性:
emailaddr
smtptimeout
dns server address(仅限windows9x)

l   调用checkdomain 方法

l   测试result属性,如果返回的结果不等于vfbinvaliddomain (1)则可以进行如下操作

l   调用checkusername 方法

l   然后测试result属性来返回最终结果:
vfabnotverify = 0
vfabinvaliddomain = 1
vfabvaliddomain = 2
vfabvaliddomaininvalidaccount = 3
vfabvaliddomainvalidaccount = 4

示例代码

dim ovfab

set ovfab=createobject("vfabemailutils.emailcheck")              创建对象

ovfab.emailaddr = request.form("email")

从asp页面获得邮件地址以进行测试,

并指派给该对象中的emailaddr属性

ovfab.checkdomain                                           检查域是否存在

if ovfab.result <> 1 then

如果存在则对用户名进行检测

ovfab.smtptimeout = 10                                  给该对象10秒钟的时间用来连接远程smtp服务器

ovfab.checkusername                                    尝试进行smtp会话,测试用户名

end if

……                                                        在这里可以用html格式显示会话纪录

ovfab.clear                                                  关闭连接, 清除日志, 恢复初始状态

组件文档

方法(表1):

名称

描述

checkdomain()

检查邮件地址中的域名部分是否是有效的(存在的)域名

checkusername()

通过smtp协议检查用户名是否是该域中的有效邮件账号

clear()

在结束任务之后,关闭连接, 清除日志, 恢复初始状态

表1

属性(表2):

名称

类型

可读

可写

描述

emailaddr

string

yes

yes

指定要检验的邮件地址

result

integer

yes

no

从checkdomain 和(或)checkusername 方法中获得处理结果

smtptimeout

integer

yes

yes

获得/设置timeout(超时-秒计)等待smtp连接

dnsserver

string

yes

no

设置域名服务器的ip地址(win9x中为必选项,windows nt 中为可选项)

realname

string

yes

no

在checkusername()被执行后,如果smtp服务器提供的话,获得用户的真实名称

domainname

string

yes

no

获得emailaddr中的域名部分

username

string

yes

no

获得emailaddr中的用户名部分

log(blnhtml)

string

yes

no

检索会话日志(客户段与服务器的所有信息交换)如果可选参数被设为true,它将重新以html格式排列断点以便阅读。

smtpserver

string

yes

no

在域中获得完整地邮件交换服务器列表

表2

下面将对主要代码进行分析:

1、检测域名有效性:

public enum emailverifiedconst                     创建一个枚举类型

……                                        包含result属性来返回最终结果

end enum

 

dim withevents owinsock as winsock                创建一个包含事件的winsock对象,事件dataarrival在下面被定义

……

public sub checkdomain()                           声明定义checkdomain方法

dim odns as new simplednsresolverlib.simplednsclient

基于simplednsresolverlib建立对象odns

intpos = instr(stremailaddr, "@")                 计算用户名的长度

if intpos = 0 then                              如果返回的结果是0

err.raise vbobjecterror + 699, , "请指定有效的邮件地址!"

exit sub                                  并从sub过程中跳出

end if

strusername = left(stremailaddr, intpos – 1)        获得用户名

strdomainname = mid(stremailaddr, intpos + 1)     获得域名

……

odns.separator = ", "                           设置各地址之间的分隔符为”,”

intresult = emailverifiedconst.vfabinvaliddomain   以枚举emailverifiedconst中的成员vfabinvaliddomain赋初值给intresult

strlog = strlog & "dns   -> query: mx records for " & strdomainname & vbcrlf        进行日志记录

on error resume next                           发生错误继续

odns.getemailservers strdomainname, strsmtpservers  利用odns对象的getmailserver方法给strsmtpservers赋值

if err <> 0 then                               

err.raise vbobjecterror + 698, , err.description

end if

strlog = strlog & "dns   <- " & strsmtpservers & vbcrlf  进行日志记录

if strsmtpservers <> "" then

intresult = emailverifiedconst.vfabvaliddomain    以枚举emailverifiedconst中的成员vfabvaliddomain赋值给intre、sult

end if

end sub

2、检测用户名的有效性:

public sub checkusername()                        声明定义checkusername()方法

dim strhost as string, i as integer, intoldstep as integer

i = 1                                         在这里定义循环初始值,并以之为计数标志分割strsmtpservers

……

do while true                                 开始进行循环1

    strhost = trim(ltrim(token(strsmtpservers, ",", i)))

                                             以”,”为分隔符分离字符串中的所有地址,使之各个独立,

i是计数标志,下面对token()的声明定义中再作解释。

    if strhost = "" then                         如果发现在“,”后有空地址

        exit do                               跳出循环

    end if

    if instr(strhost, strdomainname) > 0 then      如果域名以前的部分不是空

        with owinsock                        设置owinsock对象所使用的

            .protocol = scktcpprotocol          协议为tcp

            .remotehost = strhost              主机地址为strhost的值

            .remoteport = 25                   通信端口为25

            .connect                         并进行连接

            dbltimeout = intsmtptimeout       设置超时

            intstep = 1                        将步骤索引intstep设为1

            do while .state <> sckconnected     如果套接字状态是非连接,开始循环2

                sleep 100                    延迟100ms

                doevents               执行owinsock包含事件dataarrival

                                            dataarrival事件是用来对接收到的

                                            做出反应用的;事件的定义在下面可以找到

                                            该事件发生之后,会影响intstep、连接状态等

                dbltimeout = dbltimeout – 0.1  超时减0.1秒

           
loop

            if .state <> sckconnected then       如果套接字状态是非连接

                exit sub                     跳出函数体,结束对该方法的调用

            end if

            do while true                    循环3

                select case intstep             依据步骤intstep进行判断

                ……

                case 2

                    senddata "vrfy " & strusername & "@" & strdomainname & vbcrlf  发送待确认请求

                case 3

                    .close                   关闭套接字

                    exit do                  并结束循环3

                ……                        在这里可以使用mail handshake 方式 相应的步骤 4、5、6

                end select

                intoldstep = intstep            保护现场 保存intstep当前值

                dbltimeout = intsmtptimeout

                                            设置超时

                do while intstep = intoldstep and dbltimeout > 0                如果没有发生连接超时 进行循环4

                    sleep 100                延时100ms

                    doevents                执行owinsock包含事件dataarrival

                    dbltimeout = dbltimeout – 0.1

               
loop

                if dbltimeout < 0 then         如果发生超时

                    intstep = 0               设置intstep为0

                    exit do                  并跳出循环3

                end if

            
loop

            if intstep = 3 then                 如果intstep=3即 已套接字关闭

                exit do                      跳出循环1

            end if

            .close                           关闭套接字

            sleep 1000

        end with

    end if

    i = i + 1                                 对计数标志i进行自增运算,以保证可以读到下一个地址

loop

end sub

3、分割邮件地址,用于输入多个邮件地址时,这正是上面使用的token函数的定义

private function token(byval strinput as string, strsep as string, byval intoccur as integer) as string  声明定义函数token

dim i as long, intlen as integer

strinput = strsep & strinput & strsep                使strinput被赋值,格式为“,strsmtpservers,”

intlen = len(strsep)                             获得字符串的长度

for i = 1 to len(strinput)                         在这里取出我们需要的地址 以checkdomain中

                                              的i为参数,这里的i为循环标志

    if mid(strinput, i, intlen) = strsep then intoccur = intoccur – i  如果第i位取得的字符正好是分隔符,则以i与intoccur比较

    if intoccur = 0 then                         如果这里取得的地址也在第i位(checkdomain中,即intoccur)

        token = mid(strinput, i + 1)               则可以在这里取得一个独立的邮件地址

        if len(token) > 0 then

            i = instr(token, strsep)

            if i > 1 then

                token = left(token, i – 1)

            end if

        end if

        exit for

    end if

next i

end function

例如,strsmtpservers中的字符串为 brain@123.com,someone@somewhere.com,sherlock@holmes.com 则由strinput = strsep & strinput & strsep处理过 就变为:

,brain@123.com,someone@somewhere.com,sherlock@holmes.com,

再求得字符串的长度57,由1到57进行for循环。在循环中检索,如果发现第i位就是“,”则要求checkdomain中的i(intoccur计数标志)减1,如果发现“,”所在那位数正是checkdomain中的i。例如,“,”在第15位,checkdomain中的i刚好也是15,将在strsmtpservers中取得字符串

someone@somewhere.com,sherlock@holmes.com,

放在token中,token不为空,则在token中寻找第一个“,”并取得前面的内容重新赋给token。即

someone@somewhere.com

总结:

这个应用组件在很大程度上依赖由emmanuel kartmann 编写的simple dns resolver。请到他的主页上去查找更多关于dns构建和该组件的的细节。

这个组件的作用是在web页面上用来对邮件地址的有效性进行检测。当然主要是应用于asp,可能asp对对象的支持优于其他,易于编写,而且vbscript能在其间发挥更出色的作用。在对使用socket方面进行连接也用比较传统的方法,具有一定的代表性。

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 编程实现邮件地址有效性检测-.NET教程,Asp.Net开发
分享到: 更多 (0)