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()) {
64 result.
extra = QVariant::fromValue<QList<Diagnose>>(diag.returnStatus);
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;
130 int elementCount = 0;
132 bool hyphenFlag =
false;
133 bool endOrDie =
false;
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) {
206 contextStack.push_back(context);
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;
240 contextStack.push_back(context);
241 context = ContextQuotedString;
253 if (elementLen == 0) {
261 contextStack.push_back(context);
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();
297 contextStack.push_back(context);
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)) {
339 returnStatus.push_back(
344 if ((uni < ValidatorEmailPrivate::asciiExclamationMark) ||
345 (uni > ValidatorEmailPrivate::asciiTilde) ||
346 ValidatorEmailPrivate::stringSpecials.contains(token)) {
347 returnStatus.push_back(
353 parseLocalPart += token;
354 atomListLocalPart[elementCount] += token;
362 case ComponentDomain:
403 if (elementLen == 0) {
407 returnStatus.push_back((elementCount == 0)
416 contextStack.push_back(context);
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
'[') {
456 contextStack.push_back(context);
457 context = ComponentLiteral;
458 parseDomain += token;
459 atomListDomain[elementCount] += token;
460 parseLiteral.
clear();
472 if (elementLen == 0) {
473 returnStatus.push_back((elementCount == 0)
482 contextStack.push_back(context);
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) {
538 returnStatus.push_back(
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(),
572 returnStatus.constEnd())) <
628 qsizetype index = -1;
629 QString addressLiteral = parseLiteral;
632 ValidatorEmailPrivate::ipv4Regex.match(addressLiteral);
637 addressLiteral.
mid(0, index) +
647 addressLiteral.
left(5),
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) {
674 returnStatus.push_back(
681 if ((ipv6.
size() == 1 && ipv6[0] == u
':') ||
682 (ipv6[0] == u
':' && ipv6[1] != u
':')) {
683 returnStatus.push_back(
686 }
else if (ipv6.
right(2).
at(1) == u
':' && ipv6.
right(2).
at(0) != u
':') {
687 returnStatus.push_back(
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;
712 context = contextStack.takeLast();
713 }
else if (token == u
'\\') {
715 contextStack.push_back(context);
716 context = ContextQuotedPair;
726 contextStack.push_back(context);
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
'\\') {
772 contextStack.push_back(context);
773 context = ContextQuotedPair;
798 contextStack.push_back(context);
799 context = ContextFWS;
801 }
else if (token == u
'"') {
802 parseLocalPart += token;
803 atomListLocalPart[elementCount] += token;
805 contextPrior = context;
806 context = contextStack.takeLast();
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)) {
835 returnStatus.push_back(
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;
896 context = contextStack.takeLast();
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.";
935 contextStack.push_back(context);
936 context = ContextComment;
937 }
else if (token == u
')') {
938 contextPrior = context;
939 context = contextStack.takeLast();
957 }
else if (token == u
'\\') {
958 contextStack.push_back(context);
959 context = ContextQuotedPair;
969 contextStack.push_back(context);
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) {
1025 returnStatus.push_back(
1044 crlf_count = std::ranges::min(crlf_count, 0);
1046 contextPrior = context;
1047 context = contextStack.takeLast();
1073 qCCritical(C_VALIDATOR) <<
"ValidatorEmail: Unknown context";
1077 if (
static_cast<int>(
1078 *std::ranges::max_element(returnStatus.constBegin(), returnStatus.constEnd())) >
1085 if (
static_cast<int>(
1086 *std::ranges::max_element(returnStatus.constBegin(), returnStatus.constEnd())) <
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;
1221 *std::ranges::max_element(returnStatus.constBegin(), returnStatus.constEnd())) <
1223 if (elementCount == 0) {
1227 if (u
"0123456789"_s.contains(atomListDomain[elementCount][0])) {
1232 if (returnStatus.size() != 1) {
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);
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);
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()) {
1819 diag.returnStatus.removeAll(RFC5321TLD);
1820 diag.returnStatus.removeAll(RFC5321TLDNumeric);
1822 } else if (h.preference() == 0 &&
1823 (h.exchange().isEmpty() || h.exchange() ==
"."_L1)) {
1826 diag.returnStatus.append(DnsMxDisabled);
1830 diag.sortReturnStatus();
1831 cb(diag.isBelowThreshold(threshold), diag.cleanedEmail, diag.returnStatus);
1838 [aLookup, cb, diag, threshold]()
mutable {
1840 if (!aLookup->hostAddressRecords().empty()) {
1841 diag.returnStatus.append(DnsWarnNoMxRecord);
1843 diag.returnStatus.append(DnsNoRecordFound);
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
Checks if the value is a valid email address according to specific RFCs.
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={})
Base class for all validator rules.
QString validationError(Context *c, const QVariant &errorData={}) const
QString label(const Context *c) const
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
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::parameter_type value)
bool contains(const AT &value) const const
qsizetype size() const const
QString toString(QDate date, QLocale::FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString captured(QStringView 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 c, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString right(qsizetype n) const const
qsizetype size() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
const QChar * unicode() const const
QByteArray toAce(const QString &domain, QUrl::AceProcessingOptions options)
void setValue(QVariant &&value)
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.