簡體   English   中英

如何使用CAtlRegExp使用C ++驗證電子郵件地址

[英]How to validate e-mail address with C++ using CAtlRegExp

我需要能夠驗證C ++中各種格式的國際電子郵件地址。 我一直在網上找到許多答案並沒有解決問題,並且找到了一個對我來說很好的解決方案,我認為我可以與使用ATL服務器庫的任何人共享該解決方案。

一些背景。 我從這篇文章開始: 使用正則表達式來驗證電子郵件地址 指向http://emailregex.com/ ,該網站具有支持Internet消息格式的RFC 5322官方標准的各種語言的正則表達式。

提供的正則表達式是

(?:[a-z0-9!#$%&' + / =?^ _`{|}〜-] +(?:。[a-z0-9!#$%&' + / =?^ _` {|} 〜- ] +) |“(?:[\\ x01- \\ x08 \\ x0b \\ x0c \\ x0e- \\ x1f \\ x21 \\ x23- \\ x5b \\ x5d- \\ x7f] | \\ [\\ x01- \\ x09 \\ x0b \\ x0c \\ x0e- \\ x7f]) “)@(?:( ?: a-z0-9?。)+ a-z0-9?| [(?:( ?: 25 [0-5] | 2 [0-4] [0-9] | [01]?[0-9] [0-9]?)。){3}(?: 25 [0-5] | 2 [0-4] [0-9] | [01]?[0-9] [0-9]?| [a-z0-9-] * [a-z0-9]:(?:[\\ x01- \\ x08 \\ x0b \\ x0c \\ x0e- \\ x1f \\ x21- \\ x5a \\ x53- \\ x7f] | \\ [\\ x01- \\ x09 \\ x0b \\ x0c \\ x0e- \\ x7f])+)]])

我將C ++與ATL服務器庫一起使用 ,該曾經曾經是Visual Studio的一部分。 此后,Microsoft將其作為開放源代碼放到CodePlex上。 我們仍將其用於某些模板庫。 我的目標是修改此正則表達式,使其與CAtlRegEx一起使用

ATL中的正則表達式引擎( CAtlRegExp )非常基礎。 我能夠如下修改正則表達式:

^ {([[a-z0-9!#$%&' + / =?^ _`{|}〜\\-] +(\\。([a-z0-9!#$%&' + / =? ^ _` {|}〜\\-] +))*)@((((a-z0-9?\\。)+ a-z0-9?)|(\\ [((((2((5 [0- 5])|([[0-4] [0-9]))))((1 [0-9] [0-9])|([1-9]?[0-9]))。) ((((2((5 [0-5]] |([0-4] [0-9]])))|(1 [0-9] [0-9])|([1-9]? [0-9]))\\。)((((2((5 [0-5])|([0-4] [0-9]))))|(1 [0-9] [0-9 ])|([[1-9]?[0-9]))\\。)((2((5 [0-5])|([0-4] [0-9])))|(1 [0-9] [0-9])|([1-9]?[0-9]))]]))}} $

似乎唯一丟失的是域名中的Unicode支持,我可以通過使用IdnToAscii遵循 MSDN上“ 如何:驗證字符串是否為有效電子郵件格式”一文中的C#示例來解決。

用這種方法,用戶名和域名是從電子郵件地址中提取的。 使用IdnToAscii將域名轉換為Ascii,然后將兩者放回一起,然后通過正則表達式運行。

請注意,為了便於閱讀,省略了錯誤處理。 需要代碼以確保沒有緩沖區溢出和其他錯誤處理。 有人通過超過255個字符的電子郵件地址將導致此示例崩潰。

碼:

bool WINAPI LocalLooksLikeEmailAddress(LPCWSTR lpszEmailAddress) 
{
    bool bRetVal = true ;
    const int ccbEmailAddressMaxLen = 255 ;
    wchar_t achANSIEmailAddress[ccbEmailAddressMaxLen] = { L'\0' } ;
    ATL::CAtlRegExp<> regexp ;
    ATL::CAtlREMatchContext<> regexpMatch ;
    ATL::REParseError status  = regexp.Parse(L"^{.+}@{.+}$", FALSE) ;
    if (status == REPARSE_ERROR_OK) {
        if (regexp.Match(lpszEmailAddress, &regexpMatch) && regexpMatch.m_uNumGroups == 2) {
            const CAtlREMatchContext<>::RECHAR* szStart = 0 ;
            const CAtlREMatchContext<>::RECHAR* szEnd   = 0 ;
            regexpMatch.GetMatch(0, &szStart, &szEnd) ;
            ::wcsncpy_s(achANSIEmailAddress, szStart, (size_t)(szEnd - szStart)) ;
            regexpMatch.GetMatch(1, &szStart, &szEnd) ;
            wchar_t achDomainName[ccbEmailAddressMaxLen] = { L'\0' } ;
            ::wcsncpy_s(achDomainName, szStart, (size_t)(szEnd - szStart)) ;

            if (bRetVal) {
                wchar_t achPunycode[ccbEmailAddressMaxLen] = { L'\0' } ;
                if (IdnToAscii(0, achDomainName, -1, achPunycode, ccbEmailAddressMaxLen) == 0)
                    bRetVal = false ;
                else {
                    ::wcscat_s(achANSIEmailAddress, L"@") ;
                    ::wcscat_s(achANSIEmailAddress, achPunycode) ;
                }
            }
        }
    } 

    if (bRetVal) {
        status = regexp.Parse(
            L"^{([a-z0-9!#$%&'*+/=?^_`{|}~\\-]+(\\.([a-z0-9!#$%&'*+/=?^_`{|}~\\-]+))*)@((([a-z0-9]([a-z0-9\\-]*[a-z0-9])?\\.)+[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)|(\\[(((2((5[0-5])|([0-4][0-9])))|(1[0-9][0-9])|([1-9]?[0-9]))\\.)(((2((5[0-5])|([0-4][0-9])))|(1[0-9][0-9])|([1-9]?[0-9]))\\.)(((2((5[0-5])|([0-4][0-9])))|(1[0-9][0-9])|([1-9]?[0-9]))\\.)((2((5[0-5])|([0-4][0-9])))|(1[0-9][0-9])|([1-9]?[0-9]))\\]))}$"
            , FALSE) ;
        if (status == REPARSE_ERROR_OK) {
            bRetVal = regexp.Match(achANSIEmailAddress, &regexpMatch) != 0;
        } 
    }

    return bRetVal ;
}

值得一提的是,這種方法與C# MSDN文章中兩個電子郵件地址的結果不一致 查看http://emailregex.com上列出的原始正則表達式,表明MSDN文章弄錯了,除非最近對規范進行了更改。 我決定使用http://emailregex.com上提到的正則表達式

這是我的單元測試,使用來自MSDN文章的相同電子郵件地址

#include <Windows.h>
#if _DEBUG
#define TESTEXPR(expr) _ASSERTE(expr)
#else
#define TESTEXPR(expr) if (!(expr)) throw ;
#endif

void main()
{
    LPCWSTR validEmailAddresses[] = {   L"david.jones@proseware.com", 
                                        L"d.j@server1.proseware.com",
                                        L"jones@ms1.proseware.com", 
                                        L"j@proseware.com9", 
                                        L"js#internal@proseware.com",
                                        L"j_9@[129.126.118.1]", 
                                        L"js*@proseware.com",            // <== according to https://msdn.microsoft.com/en-us/library/01escwtf(v=vs.110).aspx this is invalid
                                                                         // but according to http://emailregex.com/ that claims to support the RFC 5322 Official standard it's not. 
                                                                         // I'm going with valid
                                        L"js@proseware.com9", 
                                        L"j.s@server1.proseware.com",
                                        L"js@contoso.中國", 
                                        NULL } ;

    LPCWSTR invalidEmailAddresses[] = { L"j.@server1.proseware.com",
                                        L"\"j\\\"s\\\"\"@proseware.com", // <== according to https://msdn.microsoft.com/en-us/library/01escwtf(v=vs.110).aspx this is valid
                                                                         // but according to http://emailregex.com/ that claims to support the RFC 5322 Official standard it's not. 
                                                                         // I'm going with Invalid
                                        L"j..s@proseware.com",
                                        L"js@proseware..com",
                                        NULL } ;

    for (LPCWSTR* emailAddress = validEmailAddresses ; *emailAddress != NULL ; ++emailAddress)
    {
        TESTEXPR(LocalLooksLikeEmailAddress(*emailAddress)) ;
    }
    for (LPCWSTR* emailAddress = invalidEmailAddresses ; *emailAddress != NULL ; ++emailAddress)
    {
        TESTEXPR(!LocalLooksLikeEmailAddress(*emailAddress)) ;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM