6#include "validatoremail_p.h"
20 u
"\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25["
21 "0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"_s};
23const QString ValidatorEmailPrivate::stringSpecials{u
"()<>[]:;@\\,.\""_s};
30 :
ValidatorRule(*new ValidatorEmailPrivate(
field, threshold, options, messages, defValKey))
45 qCWarning(C_VALIDATOR) <<
"ValidatorEmail: using the CheckDNS option on validate() is"
46 <<
"not supported anymore. Use validateCb().";
51 ValidatorEmailDiagnoseStruct diag;
53 if (ValidatorEmailPrivate::checkEmail(v, d->options, d->threshold, &diag)) {
54 if (!diag.literal.isEmpty()) {
83 [c, cb,
this, v](
bool isValid,
86 ValidatorReturnType rt;
87 rt.extra = QVariant::fromValue<QList<Diagnose>>(diagnoses);
89 rt.value.setValue(cleanedEmail);
91 qCDebug(C_VALIDATOR).noquote() << debugString(c) << diagnoses;
93 validationError(c, QVariant::fromValue<Diagnose>(diagnoses.at(0)));
111bool ValidatorEmailPrivate::checkEmail(
const QString &address,
112 ValidatorEmail::Options options,
114 ValidatorEmailDiagnoseStruct *diagnoseStruct)
118 EmailPart context = ComponentLocalpart;
120 EmailPart contextPrior = ComponentLocalpart;
125 QString parseLocalPart;
127 QString parseLiteral;
128 QMap<int, QString> atomListLocalPart;
129 QMap<int, QString> atomListDomain;
130 int elementCount = 0;
132 bool hyphenFlag =
false;
133 bool endOrDie =
false;
144 const QString local = address.
left(atPos);
145 const QString domain = address.
mid(atPos + 1);
146 bool asciiDomain =
true;
147 for (
const QChar &ch : domain) {
148 const ushort &uc = ch.unicode();
149 if (uc > ValidatorEmailPrivate::asciiEnd) {
167 const qsizetype rawLength = email.
length();
169 for (
int i = 0; i < rawLength; i++) {
176 case ComponentLocalpart:
196 if (elementLen == 0) {
207 context = ContextComment;
208 }
else if (token == u
'.') {
209 if (elementLen == 0) {
211 returnStatus.
push_back((elementCount == 0)
226 parseLocalPart += token;
227 atomListLocalPart[elementCount].
clear();
228 }
else if (token == u
'"') {
229 if (elementLen == 0) {
232 returnStatus.
push_back((elementCount == 0)
236 parseLocalPart += token;
237 atomListLocalPart[elementCount] += token;
241 context = ContextQuotedString;
253 if (elementLen == 0) {
262 context = ContextFWS;
264 }
else if (token == u
'@') {
266 if (contextStack.
size() != 1) {
268 qCCritical(C_VALIDATOR) <<
"ValidatorEmail: Unexpected item on context stack";
272 if (parseLocalPart.
isEmpty()) {
274 }
else if (elementLen == 0) {
276 }
else if (parseLocalPart.
size() > ValidatorEmailPrivate::maxLocalPartLength) {
281 }
else if ((contextPrior == ContextComment) || (contextPrior == ContextFWS)) {
295 context = ComponentDomain;
296 contextStack.
clear();
316 switch (contextPrior) {
321 case ContextQuotedString:
326 qCCritical(C_VALIDATOR)
327 <<
"ValidatorEmail: More atext found where none is allowed, "
328 "but unrecognizes prior context";
332 contextPrior = context;
333 const char16_t uni = token.
unicode();
335 if (!allowUtf8Local) {
336 if ((uni < ValidatorEmailPrivate::asciiExclamationMark) ||
337 (uni > ValidatorEmailPrivate::asciiTilde) ||
338 ValidatorEmailPrivate::stringSpecials.contains(token)) {
344 if ((uni < ValidatorEmailPrivate::asciiExclamationMark) ||
345 (uni > ValidatorEmailPrivate::asciiTilde) ||
346 ValidatorEmailPrivate::stringSpecials.contains(token)) {
353 parseLocalPart += token;
354 atomListLocalPart[elementCount] += token;
362 case ComponentDomain:
403 if (elementLen == 0) {
407 returnStatus.
push_back((elementCount == 0)
417 context = ContextComment;
418 }
else if (token == u
'.') {
419 if (elementLen == 0) {
421 returnStatus.
push_back((elementCount == 0)
424 }
else if (hyphenFlag) {
440 if (elementLen > ValidatorEmailPrivate::maxDnsLabelLength) {
449 atomListDomain[elementCount].
clear();
450 parseDomain += token;
452 }
else if (token == u
'[') {
457 context = ComponentLiteral;
458 parseDomain += token;
459 atomListDomain[elementCount] += token;
460 parseLiteral.
clear();
472 if (elementLen == 0) {
473 returnStatus.
push_back((elementCount == 0)
483 context = ContextFWS;
511 switch (contextPrior) {
516 case ComponentLiteral:
521 qCCritical(C_VALIDATOR)
522 <<
"ValidatorEmail: More atext found where none is allowed, but"
523 <<
"unrecognised prior context.";
528 const char16_t uni = token.
unicode();
531 if ((uni < ValidatorEmailPrivate::asciiExclamationMark) ||
532 (uni > ValidatorEmailPrivate::asciiTilde) ||
533 ValidatorEmailPrivate::stringSpecials.contains(token)) {
535 }
else if (token == u
'-') {
536 if (elementLen == 0) {
542 }
else if (!(((uni >= ValidatorRulePrivate::ascii_0) &&
543 (uni <= ValidatorRulePrivate::ascii_9)) ||
544 ((uni >= ValidatorRulePrivate::ascii_A) &&
545 (uni <= ValidatorRulePrivate::ascii_Z)) ||
546 ((uni >= ValidatorRulePrivate::ascii_a) &&
547 (uni <= ValidatorRulePrivate::ascii_z)))) {
552 parseDomain += token;
553 atomListDomain[elementCount] += token;
560 case ComponentLiteral:
571 if (
static_cast<int>(*std::ranges::max_element(returnStatus.
constBegin(),
628 qsizetype index = -1;
629 QString addressLiteral = parseLiteral;
631 const QRegularExpressionMatch ipv4Match =
632 ValidatorEmailPrivate::ipv4Regex.
match(addressLiteral);
637 addressLiteral.
mid(0, index) +
647 addressLiteral.
left(5),
653 const QString ipv6 = addressLiteral.
mid(5);
654 const QStringList matchesIP = ipv6.
split(u
':');
655 qsizetype groupCount = matchesIP.
size();
660 if (groupCount != maxGroups) {
667 if ((index == 0) || (index == (ipv6.
length() - 2))) {
671 if (groupCount > maxGroups) {
673 }
else if (groupCount == maxGroups) {
681 if ((ipv6.
size() == 1 && ipv6[0] == u
':') ||
682 (ipv6[0] == u
':' && ipv6[1] != u
':')) {
686 }
else if (ipv6.
right(2).
at(1) == u
':' && ipv6.
right(2).
at(0) != u
':') {
692 std::ranges::count_if(matchesIP, [](
const QString &ip) {
693 return !ip.
contains(ValidatorEmailPrivate::ipv6PartRegex);
696 if (unmatchedChars != 0) {
708 parseDomain += token;
709 atomListDomain[elementCount] += token;
711 contextPrior = context;
713 }
else if (token == u
'\\') {
716 context = ContextQuotedPair;
727 context = ContextFWS;
743 const char16_t uni = token.
unicode();
746 if ((uni > ValidatorEmailPrivate::asciiEnd) || (uni == 0) || (uni == u
'[')) {
749 }
else if ((uni < ValidatorEmailPrivate::asciiExclamationMark) ||
750 (uni == ValidatorEmailPrivate::asciiEnd)) {
754 parseLiteral += token;
755 parseDomain += token;
756 atomListDomain[elementCount] += token;
763 case ContextQuotedString:
771 if (token == u
'\\') {
773 context = ContextQuotedPair;
799 context = ContextFWS;
801 }
else if (token == u
'"') {
802 parseLocalPart += token;
803 atomListLocalPart[elementCount] += token;
805 contextPrior = context;
821 const char16_t uni = token.
unicode();
823 if (!allowUtf8Local) {
824 if ((uni > ValidatorEmailPrivate::asciiEnd) || (uni == 0) ||
825 (uni == ValidatorEmailPrivate::asciiLF)) {
827 }
else if ((uni < ValidatorRulePrivate::asciiSpace) ||
828 (uni == ValidatorEmailPrivate::asciiEnd)) {
833 if ((uni > ValidatorEmailPrivate::asciiEnd) || (uni == 0) ||
834 (uni == ValidatorEmailPrivate::asciiLF)) {
837 }
else if ((uni < ValidatorRulePrivate::asciiSpace) ||
838 (uni == ValidatorEmailPrivate::asciiEnd)) {
844 parseLocalPart += token;
845 atomListLocalPart[elementCount] += token;
860 case ContextQuotedPair:
878 const char16_t uni = token.
unicode();
880 if (uni > ValidatorEmailPrivate::asciiEnd) {
882 }
else if (((uni < ValidatorEmailPrivate::asciiUS) &&
883 (uni != ValidatorRulePrivate::asciiTab)) ||
884 (uni == ValidatorEmailPrivate::asciiEnd)) {
895 contextPrior = context;
901 case ContextQuotedString:
902 parseLocalPart += u
'\\';
903 parseLocalPart += token;
904 atomListLocalPart[elementCount] += u
'\\';
905 atomListLocalPart[elementCount] += token;
909 case ComponentLiteral:
910 parseDomain += u
'\\';
911 parseDomain += token;
912 atomListDomain[elementCount] += u
'\\';
913 atomListDomain[elementCount] += token;
919 qCCritical(C_VALIDATOR)
920 <<
"ValidatorEmail: Quoted pair logic invoked in an invalid context.";
936 context = ContextComment;
937 }
else if (token == u
')') {
938 contextPrior = context;
957 }
else if (token == u
'\\') {
959 context = ContextQuotedPair;
970 context = ContextFWS;
987 const ushort uni = token.
unicode();
989 if ((uni > ValidatorEmailPrivate::asciiEnd) || (uni == 0) ||
990 (uni == ValidatorEmailPrivate::asciiLF)) {
993 }
else if ((uni < ValidatorRulePrivate::asciiSpace) ||
994 (uni == ValidatorEmailPrivate::asciiEnd)) {
1023 if (crlf_count > 0) {
1024 if (++crlf_count > 1) {
1044 crlf_count = std::ranges::min(crlf_count, 0);
1046 contextPrior = context;
1073 qCCritical(C_VALIDATOR) <<
"ValidatorEmail: Unknown context";
1077 if (
static_cast<int>(
1085 if (
static_cast<int>(
1088 if (context == ContextQuotedString) {
1090 }
else if (context == ContextQuotedPair) {
1092 }
else if (context == ContextComment) {
1094 }
else if (context == ComponentLiteral) {
1098 }
else if (parseDomain.
isEmpty()) {
1100 }
else if (elementLen == 0) {
1102 }
else if (hyphenFlag) {
1104 }
else if (parseDomain.
size() > ValidatorEmailPrivate::maxDomainLength) {
1108 }
else if ((parseLocalPart.
size() + 1 + parseDomain.
size()) >
1109 ValidatorEmailPrivate::maxMailboxLength) {
1129 }
else if (elementLen > ValidatorEmailPrivate::maxDnsLabelLength) {
1135 bool dnsChecked =
false;
1223 if (elementCount == 0) {
1227 if (u
"0123456789"_s.contains(atomListDomain[elementCount][0])) {
1232 if (returnStatus.
size() != 1) {
1233 QList<ValidatorEmail::Diagnose> _rs;
1241 std::ranges::sort(returnStatus, std::greater<>());
1246 if (diagnoseStruct) {
1247 diagnoseStruct->finalStatus = finalStatus;
1248 diagnoseStruct->returnStatus = returnStatus;
1249 diagnoseStruct->localpart = parseLocalPart;
1250 diagnoseStruct->domain = parseDomain;
1251 diagnoseStruct->literal = parseLiteral;
1252 if (!parseLiteral.
isEmpty()) {
1253 diagnoseStruct->cleanedEmail = parseLocalPart + u
'@' + parseLiteral;
1255 diagnoseStruct->cleanedEmail = parseLocalPart + u
'@' + parseDomain;
1259 return static_cast<int>(finalStatus) <
static_cast<int>(threshold);
1266 if (
label.isEmpty()) {
1272 return c->
qtTrId(
"cutelyst-valemail-diag-valid");
1275 return c->
qtTrId(
"cutelyst-valemail-diag-nomx");
1278 return c->
qtTrId(
"cutelyst-valemail-diag-mxdisabled");
1281 return c->
qtTrId(
"cutelyst-valemail-diag-noarec");
1284 return c->
qtTrId(
"cutelyst-valemail-diag-dnstimeout");
1287 return c->
qtTrId(
"cutelyst-valemail-diag-dnserror");
1290 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321tld");
1293 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321tldnumeric");
1296 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321quotedstring");
1299 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321addressliteral");
1304 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321ipv6deprecated");
1307 return c->
qtTrId(
"cutelyst-valemail-diag-cfwscomment");
1310 return c->
qtTrId(
"cutelyst-valemail-diag-cfwsfws");
1313 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedlocalpart");
1316 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedfws");
1319 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedqtext");
1322 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedqp");
1325 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedcomment");
1328 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedctext");
1331 return c->
qtTrId(
"cutelyst-valemail-diag-cfwsnearat");
1335 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domain");
1338 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322toolong")
1343 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322localtoolong")
1347 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domaintoolong")
1352 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322labeltoolong")
1356 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domainliteral");
1360 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domlitobsdtext");
1363 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6groupcount");
1366 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv62x2xcolon");
1369 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6badchar");
1372 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6maxgroups");
1375 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6colonstart");
1378 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6colonend");
1381 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingdtext");
1384 return c->
qtTrId(
"cutelyst-valemail-diag-errnolocalpart");
1387 return c->
qtTrId(
"cutelyst-valemail-diag-errnodomain");
1390 return c->
qtTrId(
"cutelyst-valemail-diag-errconsecutivedots");
1393 return c->
qtTrId(
"cutelyst-valemail-diag-erratextaftercfws");
1396 return c->
qtTrId(
"cutelyst-valemail-diag-erratextafterqs");
1399 return c->
qtTrId(
"cutelyst-valemail-diag-erratextafterdomlit");
1402 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingqpair");
1405 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingatext");
1408 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingqtext");
1411 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingctext");
1414 return c->
qtTrId(
"cutelyst-valemail-diag-errbackslashend");
1417 return c->
qtTrId(
"cutelyst-valemail-diag-errdotstart");
1420 return c->
qtTrId(
"cutelyst-valemail-diag-errdotend");
1423 return c->
qtTrId(
"cutelyst-valemail-diag-errdomainhyphenstart");
1426 return c->
qtTrId(
"cutelyst-valemail-diag-errdomainhyphenend");
1429 return c->
qtTrId(
"cutelyst-valemail-diag-errunclosedquotedstr");
1432 return c->
qtTrId(
"cutelyst-valemail-diag-errunclosedcomment");
1435 return c->
qtTrId(
"cutelyst-valemail-diag-erruncloseddomliteral");
1438 return c->
qtTrId(
"cutelyst-valemail-diag-errfwscrlfx2");
1441 return c->
qtTrId(
"cutelyst-valemail-diag-errfwscrlfend");
1445 return c->
qtTrId(
"cutelyst-valemail-diag-errcrnolf");
1448 return c->
qtTrId(
"cutelyst-valemail-diag-errfatal");
1460 return c->
qtTrId(
"cutelyst-valemail-diag-valid-label").
arg(
label);
1464 return c->
qtTrId(
"cutelyst-valemail-diag-nomx-label").
arg(
label);
1467 return c->
qtTrId(
"cutelyst-valemail-diag-mxdisabled-label").
arg(
label);
1471 return c->
qtTrId(
"cutelyst-valemail-diag-noarec-label").
arg(
label);
1474 return c->
qtTrId(
"cutelyst-valemail-diag-dnstimeout-label").
arg(
label);
1477 return c->
qtTrId(
"cutelyst-valemail-diag-dnserror-label").
arg(
label);
1480 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321tld-label").
arg(
label);
1484 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321tldnumeric-label").
arg(
label);
1487 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321quotedstring-label").
arg(
label);
1491 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321addressliteral-label").
arg(
label);
1496 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5321ipv6deprecated-label").
arg(
label);
1499 return c->
qtTrId(
"cutelyst-valemail-diag-cfwscomment-label").
arg(
label);
1503 return c->
qtTrId(
"cutelyst-valemail-diag-cfwsfws-label").
arg(
label);
1506 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedlocalpart-label").
arg(
label);
1510 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedfws-label").
arg(
label);
1514 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedqtext-label").
arg(
label);
1518 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedqp-label").
arg(
label);
1522 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedcomment-label").
arg(
label);
1525 return c->
qtTrId(
"cutelyst-valemail-diag-deprecatedctext-label").
arg(
label);
1529 return c->
qtTrId(
"cutelyst-valemail-diag-cfwsnearat-label").
arg(
label);
1533 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domain-label").
arg(
label);
1537 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322toolong-label")
1542 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322localtoolong-label")
1547 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domaintoolong-label")
1552 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322labeltoolong-label")
1557 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domainliteral-label").
arg(
label);
1561 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322domlitobsdtext-label").
arg(
label);
1565 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6groupcount-label").
arg(
label);
1569 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv62x2xcolon-label").
arg(
label);
1573 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6badchar-label").
arg(
label);
1576 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6maxgroups-label").
arg(
label);
1580 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6colonstart-label").
arg(
label);
1584 return c->
qtTrId(
"cutelyst-valemail-diag-rfc5322ipv6colonend-label").
arg(
label);
1588 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingdtext-label").
arg(
label);
1591 return c->
qtTrId(
"cutelyst-valemail-diag-errnolocalpart-label").
arg(
label);
1594 return c->
qtTrId(
"cutelyst-valemail-diag-errnodomain-label").
arg(
label);
1597 return c->
qtTrId(
"cutelyst-valemail-diag-errconsecutivedots-label").
arg(
label);
1601 return c->
qtTrId(
"cutelyst-valemail-diag-erratextaftercfws-label").
arg(
label);
1604 return c->
qtTrId(
"cutelyst-valemail-diag-erratextafterqs-label").
arg(
label);
1608 return c->
qtTrId(
"cutelyst-valemail-diag-erratextafterdomlit-label").
arg(
label);
1612 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingqpair-label").
arg(
label);
1615 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingatext-label").
arg(
label);
1619 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingqtext-label").
arg(
label);
1623 return c->
qtTrId(
"cutelyst-valemail-diag-errexpectingctext-label").
arg(
label);
1626 return c->
qtTrId(
"cutelyst-valemail-diag-errbackslashend-label").
arg(
label);
1629 return c->
qtTrId(
"cutelyst-valemail-diag-errdotstart-label").
arg(
label);
1632 return c->
qtTrId(
"cutelyst-valemail-diag-errdotend-label").
arg(
label);
1636 return c->
qtTrId(
"cutelyst-valemail-diag-errdomainhyphenstart-label").
arg(
label);
1640 return c->
qtTrId(
"cutelyst-valemail-diag-errdomainhyphenend-label").
arg(
label);
1644 return c->
qtTrId(
"cutelyst-valemail-diag-errunclosedquotedstr-label").
arg(
label);
1648 return c->
qtTrId(
"cutelyst-valemail-diag-errunclosedcomment-label").
arg(
label);
1652 return c->
qtTrId(
"cutelyst-valemail-diag-erruncloseddomliteral-label").
arg(
label);
1656 return c->
qtTrId(
"cutelyst-valemail-diag-errfwscrlfx2-label").
arg(
label);
1660 return c->
qtTrId(
"cutelyst-valemail-diag-errfwscrlfend-label").
arg(
label);
1664 return c->
qtTrId(
"cutelyst-valemail-diag-errcrnolf-label").
arg(
label);
1667 return c->
qtTrId(
"cutelyst-valemail-diag-errfatal-label").
arg(
label);
1676 if (
label.isEmpty()) {
1680 return c->
qtTrId(
"cutelyst-valemail-cat-valid");
1683 return c->
qtTrId(
"cutelyst-valemail-cat-dnswarn");
1686 return c->
qtTrId(
"cutelyst-valemail-cat-dnsfailed");
1689 return c->
qtTrId(
"cutelyst-valemail-cat-rfc5321");
1693 return c->
qtTrId(
"cutelyst-valemail-cat-cfws");
1697 return c->
qtTrId(
"cutelyst-valemail-cat-deprecated");
1701 return c->
qtTrId(
"cutelyst-valemail-cat-rfc5322");
1704 return c->
qtTrId(
"cutelyst-valemail-cat-invalid");
1710 return c->
qtTrId(
"cutelyst-valemail-cat-valid-label").
arg(
label);
1713 return c->
qtTrId(
"cutelyst-valemail-cat-dnswarn-label").
arg(
label);
1716 return c->
qtTrId(
"cutelyst-valemail-cat-dnsfailed-label").
arg(
label);
1719 return c->
qtTrId(
"cutelyst-valemail-cat-rfc5321-label").
arg(
label);
1727 return c->
qtTrId(
"cutelyst-valemail-cat-deprecated-label").
arg(
label);
1731 return c->
qtTrId(
"cutelyst-valemail-cat-rfc5322-label").
arg(
label);
1734 return c->
qtTrId(
"cutelyst-valemail-cat-invalid-label").
arg(
label);
1743 const auto diag =
static_cast<int>(diagnose);
1745 if (diag <
static_cast<int>(
Valid)) {
1747 }
else if (diag <
static_cast<int>(
DNSWarn)) {
1749 }
else if (diag <
static_cast<int>(
DNSFailed)) {
1751 }
else if (diag <
static_cast<int>(
RFC5321)) {
1753 }
else if (diag <
static_cast<int>(
CFWS)) {
1755 }
else if (diag <
static_cast<int>(
Deprecated)) {
1757 }
else if (diag <
static_cast<int>(
RFC5322)) {
1775 qCWarning(C_VALIDATOR) <<
"ValidatorEmail: using the CheckDNS option on validate() is"
1776 <<
"not supported anymore. Use validateCb().";
1779 ValidatorEmailDiagnoseStruct diag;
1780 bool ret = ValidatorEmailPrivate::checkEmail(email, options, threshold, &diag);
1783 *diagnoses = diag.returnStatus;
1796 ValidatorEmailDiagnoseStruct diag;
1797 const bool ret = ValidatorEmailPrivate::checkEmail(email, options, threshold, &diag);
1801 if (diag.domain.isEmpty()) {
1803 diag.returnStatus.append(
DnsError);
1804 diag.sortReturnStatus();
1805 cb(diag.isBelowThreshold(threshold), diag.cleanedEmail, diag.returnStatus);
1813 !mxLookup->mailExchangeRecords().empty()) {
1814 const auto records = mxLookup->mailExchangeRecords();
1815 for (
const auto &h : records) {
1816 if (h.preference() > 0 && !h.exchange().isEmpty()) {
1822 }
else if (h.preference() == 0 &&
1823 (h.exchange().isEmpty() || h.exchange() ==
"."_L1)) {
1830 diag.sortReturnStatus();
1831 cb(diag.isBelowThreshold(threshold), diag.cleanedEmail, diag.returnStatus);
1838 [aLookup, cb, diag, threshold]()
mutable {
1840 if (!aLookup->hostAddressRecords().empty()) {
1845 diag.sortReturnStatus();
1846 cb(diag.isBelowThreshold(threshold),
1850 switch (aLookup->error()) {
1858 diag.returnStatus.append(
DnsError);
1861 diag.sortReturnStatus();
1862 cb(diag.isBelowThreshold(threshold),
1866 aLookup->deleteLater();
1873 switch (mxLookup->error()) {
1881 diag.returnStatus.append(
DnsError);
1884 diag.sortReturnStatus();
1885 cb(diag.isBelowThreshold(threshold), diag.cleanedEmail, diag.returnStatus);
1888 mxLookup->deleteLater();
1896 cb(ret, diag.cleanedEmail, diag.returnStatus);
1900void ValidatorEmailDiagnoseStruct::sortReturnStatus()
1902 std::ranges::sort(returnStatus, std::greater<>());
1903 finalStatus = returnStatus.
at(0);
1908 return static_cast<int>(finalStatus) <
static_cast<int>(threshold);
1911#include "moc_validatoremail.cpp"
QLocale locale() const noexcept
QString qtTrId(const char *id, int n=-1) const
static QString categoryString(const Context *c, Category category, const QString &label={})
static Category category(Diagnose diagnose)
Category
Validation category, used as threshold to define valid addresses.
ValidatorEmail(const QString &field, Category threshold=RFC5321, Options options=NoOption, const ValidatorMessages &messages={}, const QString &defValKey={})
~ValidatorEmail() override
Diagnose
Single diagnose values that show why an address is not valid.
@ ErrorUnclosedDomLiteral
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
static QString diagnoseString(const Context *c, Diagnose diagnose, const QString &label={})
QString field() const noexcept
QString validationError(Context *c, const QVariant &errorData={}) const
QString label(const Context *c) const
ValidatorRule(const QString &field, const ValidatorMessages &messages={}, const QString &defValKey={}, QByteArrayView validatorName=nullptr)
std::function< void(ValidatorReturnType &&result)> ValidatorRtFn
Void callback function for validator rules that processes the ValidatorReturnType.
void defaultValue(Context *c, ValidatorReturnType *result) const
QString value(const ParamsMultiMap ¶ms) const
QMultiMap< QString, QString > ParamsMultiMap
static void validateCb(const QString &email, Category threshold, Options options, std::function< void(bool isValid, const QString &cleanedEmail, const QList< Diagnose > &diagnoses)> cb)
Checks if the email is a valid address according to the Category given in the threshold.
static bool validate(const QString &email, Category threshold=RFC5321, Options options=NoOption, QList< Diagnose > *diagnoses=nullptr)
Returns true if email is a valid address according to the Category given in the threshold.
The Cutelyst namespace holds all public Cutelyst API.
bool isLetterOrNumber(char32_t ucs4)
void append(QList< T > &&value)
QList< T >::const_reference at(qsizetype i) const const
QList< T >::const_iterator constBegin() const const
QList< T >::const_iterator constEnd() const const
bool contains(const AT &value) const const
void push_back(QList< T >::parameter_type value)
qsizetype size() const const
QList< T >::value_type takeLast()
QString toString(QDate date, QLocale::FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QRegularExpressionMatch match(QStringView subjectView, qsizetype offset, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions) const const
QString captured(QAnyStringView name) const const
bool hasMatch() const const
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) &&
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) &&
QString right(qsizetype n) &&
qsizetype size() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QByteArray toAce(const QString &domain, QUrl::AceProcessingOptions options)
QVariant fromValue(T &&value)
void setValue(QVariant &&value)
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.