` Checking for valid email address (Jim Kane) - Icetips Article
Icetips - Templates, Tools & Utilities for Clarion Developers

Templates, Tools and Utilities
for Clarion Developers

Icetips Article

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 April 25, 2024, 12:24 am
This article has been viewed 35119 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

Login

User Name:

Password: