regex — Как проверить адрес электронной почты с C ++, используя CAtlRegExp

Мне нужно иметь возможность проверять различные форматы международных адресов электронной почты в C ++. Я нашел много ответов онлайн, не сокращайте это, и я нашел решение, которое хорошо работает для меня, которое я думал, что поделится для всех, кто использует Серверная библиотека ATL

Некоторый фон. Я начал с этого поста: Использование регулярного выражения для проверки адреса электронной почты. Который указал на http://emailregex.com/ который имел регулярное выражение на разных языках, который поддерживает RFC 5322 Официальный стандарт формата интернет-сообщений.

Предоставлено регулярное выражение

(?! [А-z0-9 # $%&’+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&’+/ = ^ _ `{|}? ~ -] +)| «(?: [\ X01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21 \ x23- \ X5b \ x5d- \ x7f] | \ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f ])«) @ (:( ?: а-z0-9) + а-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] | [а-z0-9 -] * [а-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

0

Решение

Механизм регулярных выражений (CAtlRegExp) в ATL довольно просто. Мне удалось изменить регулярное выражение следующим образом:

^ {([А-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 в доменных именах, которую я смог решить, следуя примеру C # в Как: убедиться, что строки в допустимом формате электронной почты статья на MSDN с помощью IdnToAscii.

При таком подходе имя пользователя и имя домена извлекаются из адреса электронной почты. Доменное имя преобразуется в Ascii с помощью IdnToAscii и затем эти два собраны вместе, а затем побежал через регулярное выражение.

Обратите внимание, что обработка ошибок была опущена для удобства чтения. Код необходим, чтобы убедиться, что нет переполнения буфера и другой обработки ошибок. Кто-то, передавший адрес электронной почты длиной более 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)) ;
}
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector