|
Add a comment to an Icetips Article
Please add your comments to this article.
Please note that you must provide both a name and a valid email address in order
for us to publish your comment. Comments are moderated and are not visible until they have been approved. Spam is never approved!
Back to article list
Search Articles
Add Comment
Printer friendly
Direct link
Email, FTP etc.: Checking for valid email address
2003-08-12 -- Jim Kane
Newsgroups: TopSpeed.Topic.Third_Party
This is what I use. I just wrote it not long ago so if anyone who uses it
has comments please send them.
I decide to use these two test and then set up a bounce box where all emails
sent out that bounce come back to a special email address. Anything comming
back to that address needs to be investigated. I usually set up an outlook
client and use ole to control outlook to find all the bounces and strip bad
emails.
jim kane
"Geoff Bomford" wrote in message
news:3f38caeb$1@news.softvelocity.com...
> Is anyone aware of a Clarion tool that can check the MX Record of an Email
> address for a valid entry?
>
> It is the sort of thing that I would expect Nettalk to be capable of - is
> it? If so, anyone care to share some code?
Editors Note: Jim attached two files with his message, dnscl.inc and dnscl.clw.
These contain an ABC compliant class and should be placed in the Clarion LibSrc
directory:
dnscl.inc:
!ABCIncludeFile
OMIT('_EndOfInclude_',_dnsclPresent_)
_dnsclPresent_ EQUATE(1)
!Other Classes
! Include('OtherClass.INC')
!Equates - will be seen by using program
dnsclType Class,type,module('dnscl.CLW'),LINK('dnscl.CLW',_ABCLinkMode_),DLL(_ABCDllMode_)
!Member Data
!dnsresult values:
! -1 : dns not tried - email syntax error
! 0 : dns tried and no error
! -2 : dns tried, no error reading records but no MX records were returned - domain does not support
email
!Anything else: win32 error 9000 -10000 are dns specific errors
!Methods - all return 0 for success if they return anything
SyntaxCheck Procedure(string pEmail,*string pErrorStr, *cstring domain),byte,private
ValidateEmailAddr Procedure(string pEMailAddr, *String pErrorstr, *long DnsResult),byte
FormatErrMsg Procedure(*string errmsg,long EC),private
end
!_EndOfInclude_
dnscl.clw:
Member
_ABCDllMode_ EQUATE(0)
_ABCLinkMode_ EQUATE(1)
Map
!Local Procedures, if any, go here
!API Prototypes
Module('api')
DnsQuery(*cstring pDomainName, ushort pWType=15, long fOptions=0, |
long plpServerList=0, *long plpResult, long Reserved=0),|
long,pascal,proc,raw,name('DnsQuery_A')
DnsRecordListFree(long plpResult, long pfreeType=1),pascal,raw,proc
getlasterror(),long,pascal
memcpy(long,long,signed),long,proc,name('_Memcpy')
lstrlen(long),SIGNED,PASCAL,NAME('lstrLenA')
FormatMessage(ulong,long,ulong,ulong,long,ulong,long),ulong,PASCAL,RAW,Name('FormatMessageA')
LocalFree(long),long,PASCAL,proc
End
end
!Includes this class and others
include('dnscl.inc')
!global data for this module
Return:Benign equate(0)
Return:Fatal equate(3)
Return:Notify equate(5)
maxemaillength equate(100)
!-------------------------------------------------------------
!---Start of dnscltype
!-------------------------------------------------------------
dnscltype.SyntaxCheck procedure(string pEmail,*string pErrorStr, *cstring
pdomain)
!purpose: do a syntax check on the email address
!input: email address,
!output: place to write an error description and the domain portion
!return value: beign-good email; Notify - bad email; Fatal - error - cant tell
AtCharIdx long,auto
L long,auto
Mailbox string(maxemaillength)
DomainPrefix string(maxemaillength)
DomainSuffix string(maxemaillength)
LastPeriodIdx long
thechar string(1)
I long
partlen long
!Match:Simple EQUATE(0)
!Match:Wild EQUATE(1)
!Match:Regular EQUATE(2)
!Match:Soundex EQUATE(3)
!Match:NoCase EQUATE(10H) ! May be added to Simple,Wild and Regular
code
L=len(clip(pEmail))
if L >MaxEmailLength then
pErrorStr='Email address too long!'
return return:notify
end
if L<3 then
pErrorstr='Email address too short.'
return return:notify
end
if pemail[1]='<<' or pEmail[L]='>' then
pErrorstr='Angle brackets arround the address must be removed.'
return return:notify
end
!find the 1st @ char
AtCharIdx=instring('@',pemail,1,1)
if ~AtCharidx or AtCharidx>=L then
pErrorstr='@ character is not in a legal place.'
return return:notify
end
Mailbox=pEmail[1 : atCharIdx-1]
pdomain=pEmail[atCharIdx + 1 : L]
!Message('email parts: ' & clip(mailbox) & ' ' & clip(DomainPrefix) & ' ' & clip(DomainSuffix))
!see http://www.netusi.com/regExp.htm
!not going to support the @[10.1.23.1] format which is legal for the domainprefix&'.'&domainsuffix
!format for the mail box name
! ^([A-Za-z0-9_]\-\.]+)
partlen=len(clip(mailbox))
loop I= 1 to partlen
thechar=upper(mailbox[i])
if (thechar>='A' and theChar<='Z') or |
(thechar>='0' and theChar<='9') or |
thechar='_' or |
theChar='-' or |
thechar='.' then
cycle !good char
else
pErrorstr='The mail box name may only contain letters, numbers, dash, underline and periods.'
Return return:notify
end
end
!find the last period in the email - must be before the @ sign
LastPeriodIdx=0
loop I= L to AtCharIdx+1 by -1
if pEmail[I]='.' then
LastPeriodidx=I
break
end
end
if ~LastPeriodIdx or L - LastPeriodIdx < 2 or L - LastPeriodIdx>4 then
pErrorstr='There must be 2 to 4 characters after the final period at the end of the email.'
return return:notify
end
!break the domain into 2 parts
DomainPrefix=pEmail[atCharIdx+1 : LastPeriodIDx-1]
DomainSuffix=pEmail[LastPeriodIdx+1 : L]
!look for the [nn.nn.nn.n]
partlen=len(clip(pDomain))
if pDomain[1]='[' and pDomain[PartLen]=']' then
!special [nn.nn.nn.n] syntax
if pDomain[2]='.' or pdomain[PartLen-1]='.' or PartLen<9 or PartLen>17 then
pErrorstr='To use an ip address for the domain the syntax is [nnn.nnn.nnn.nnn].'
return return:notify
end
Loop I=1 to partlen
thechar=pdomain[I]
if thechar='.' or (thechar>='0' and thechar<='9') then
!good char
cycle
end
pErrorstr='To use an ip address for the domain the syntax is [nnn.nnn.nnn.nnn].'
return return:notify
end
Return return:benign !no further domain check is needed
end
!format for the DomainPrefix
! (([[A-Za-z0-9_]\-]+\.)+)
L=len(clip(DomainPrefix))
loop I=1 to L
thechar=upper(domainPrefix[i])
if (thechar>='A' and theChar<='Z') or |
(thechar>='0' and theChar<='9') or |
thechar='_' or |
theChar='-' or |
thechar='.' then
cycle !good char
else
pErrorstr='The domain name before the period may only contain letters, ' &|
'numbers, dash, underline and periods.'
Return return:notify
end
end
!format for the DomainSuffix
! ([a-zA-Z]{2,4})
L=len(clip(DomainSuffix))
loop I=1 to L
thechar=upper(domainSuffix[i])
if (thechar>='A' and theChar<='Z') then
cycle !good char
else
pErrorstr='The domain name after the final period may only contain letters.'
Return return:notify
end
end
return return:benign
dnsclType.ValidateEmailAddr Procedure(string pEMailAddr, *String pErrorstr, *long
DnsResult)
DomainName cstring(maxemaillength)
!DnsResult long(-1) !return value from dnsQuery. 0=no error
lpResult long !pointer to the array of dns_recordMX's
lpRecord long !pointer to the current record being read
recordcount long !counts the number of records read
MXRecordCount long !the number of mx records read (mx = mail records)
cstringRef &cstring !cstring reference variable to make displaying the cstrings easier
dns_RecordMXType group,Type
lpNextRecord long
lpName long
wType ushort
wDataLength ushort
flags long !section:2,delete:1,charset:2,unused:3,Reserved:24
dwTtl long
dwReserved long
lpNameExchange long
wPreference ushort
pad Ushort
end
dns_RecordMx &Dns_RecordMXType
DNS_Type_MX equate(15)
res byte(return:fatal)
code
!initialize output
clear(pErrorStr)
dnsresult=-1 !not attempted
res=SELF.SyntaxCheck(pEmailAddr,pErrorStr, domainname)
if res=return:notify then
pErrorstr=clip(pErrorstr) & ' Bad email address syntax!'
end
if res then
return res
end
clear(lpResult)
clear(RecordCount)
Clear(MXRecordCount)
dnsResult = DnsQuery(domainname,DNS_Type_MX,0,0,lpResult,0)
!9002 dns server failure - tried to resolve myown domain name
!9003 means no match - name is bad
!9502 no records found for the query
!9503 means match on name but no mail server
!Message('dnsResult='&dnsresult & ' lpResult='&lpResult)
!init lpRecord to the address of the 1st record
lpRecord=lpResult
if dnsResult=0 then
loop
dns_RecordMX&=(lpResult)
if dns_recordmx.wtype=15 then
MXRecordCount+=1
!cstringRef&=(dns_RecordMX.lpName)
!Message('Name='& cstringRef)
!cstringRef&=(dns_RecordMX.lpNameExchange)
!message('Mail server='&cStringRef)
!message('timetolive='&dns_recordmx.dwttl)
!message('preference='&dns_recordmx.wPreference)
!message('DataLength='&dns_Recordmx.wDataLength)
!else
! message('wtype='&dns_recordmx.wtype)
end
recordcount+=1
if ~dns_RecordMX.lpNextRecord or dns_RecordMX.lpNextRecord=lpRecord then
!Message('done with records count='&Recordcount)
break
else
!Message('thisrec='&lprecord & ' NextRecord='&dns_RecordMX.lpNextRecord)
lpRecord=dns_RecordMX.lpNextRecord
end
end
if ~MXRecordCount then .
else
!make a message string
SeLF.formatErrMsg(pErrorStr,DnsResult)
!Message(clip(errorstr),'DNS Error')
end
!free list if any
if lpResult then
DnsRecordListFree(lpResult)
end
!show success or failure
if DNSResult=0 then
if MxRecordCount>0 then
pErrorStr='Email address is okay!'
res=return:benign !every thing good
else
!mxrecordcount<=0 and dnsresult=0
dnsresult=-2 !code for tried dns but no mx records
pErrorstr='The domain exists but does not support email.'
res=return:notify
end
elsif DNSResult=9852 or DNSResult<9000 or dnsresult>10000 then
!9852 = no network or no dns server
res=return:Fatal !wierd error like out of memory or somthing
pErrorstr='Error determining if the domain is valid. ' & clip(pErrorstr)
else
!9xxx errorcode in dns land
Res=Return:Notify !probably not a good domain
pErrorstr='Email domain bad! '& clip(pErrorstr)
end
return res
dnsclType.FormatErrMsg procedure(*string errmsg,long EC)
lpMsgBuf long,auto !Address of message string formated by FormatMessage Call
lenMsgBuf long,auto !char in cstring return by formatMessage
res byte(3)
code
If FormatMessage(1100H, | !Format_Message_Allocate_Buffer + Format_message_From_System
0, EC,0,Address(lpMsgBuf),0,0)
lenMsgBuf = lstrlen(lpmsgBuf)
If lenMsgBuf then
lenMsgBuf = choose(lenMsgBuf>size(errMsg), size(errMsg), lenmsgbuf)
Clear(errMsg)
memcpy(Address(errMsg), lpMsgBuf, lenMsgBuf)
res=0
end
If lpMsgBuf then LocalFree(lpMsgBuf). !clean up allocated memory
end
if res then errmsg='Unknown error - '&ec .
Return
Today is November 23, 2024, 3:34 am This article has been viewed 35393 times.
Google search
has resulted in 546 hits on this article since January 25, 2004.
Back to article list
Search Articles
Add Comment
Printer friendly
|
|
|