6 #include "validatoremail_p.h"
7 #include <QRegularExpression>
18 ValidatorRule(*new ValidatorEmailPrivate(field, threshold, options, messages, defValKey))
30 const QString v =
value(params);
59 ValidatorEmailDiagnoseStruct diag;
61 if (ValidatorEmailPrivate::checkEmail(v, d->options, d->threshold, &diag)) {
62 if (!diag.literal.isEmpty()) {
63 result.
value.setValue<QString>(diag.localpart + QLatin1Char(
'@') + diag.literal);
65 result.
value.setValue<QString>(diag.localpart + QLatin1Char(
'@') + diag.domain);
71 result.
extra = QVariant::fromValue<QList<Diagnose>>(diag.returnStatus);
90 bool ValidatorEmailPrivate::checkEmail(
const QString &address, ValidatorEmail::Options options,
ValidatorEmail::Category threshold, ValidatorEmailDiagnoseStruct *diagnoseStruct)
96 EmailPart context = ComponentLocalpart;
97 QList<EmailPart> contextStack{context};
98 EmailPart contextPrior = ComponentLocalpart;
103 QString parseLocalPart;
105 QString parseLiteral;
106 QMap<int, QString> atomListLocalPart;
107 QMap<int, QString> atomListDomain;
108 int elementCount = 0;
110 bool hypenFlag =
false;
111 bool endOrDie =
false;
115 const QString stringSpecials = QStringLiteral(
"()<>[]:;@\\,.\"");
122 const int atPos = address.lastIndexOf(QLatin1Char(
'@'));
125 const QString local = address.left(atPos);
126 const QString domain = address.mid(atPos + 1);
127 bool asciiDomain =
true;
128 for (
const QChar &ch : domain) {
129 const ushort &uc = ch.unicode();
139 email = local + QLatin1Char(
'@') + QString::fromLatin1(QUrl::toAce(domain));
148 const int rawLength = email.length();
150 for (
int i = 0; i < rawLength; i++) {
157 case ComponentLocalpart:
176 if (token == QLatin1Char(
'(')) {
177 if (elementLen == 0) {
185 contextStack.push_back(context);
186 context = ContextComment;
187 }
else if (token == QLatin1Char(
'.')) {
188 if (elementLen == 0) {
200 parseLocalPart += token;
201 atomListLocalPart[elementCount] = QString();
202 }
else if (token == QLatin1Char(
'"')) {
203 if (elementLen == 0) {
208 parseLocalPart += token;
209 atomListLocalPart[elementCount] += token;
212 contextStack.push_back(context);
213 context = ContextQuotedString;
217 }
else if ((token == QChar(QChar::CarriageReturn)) || (token == QChar(QChar::Space)) || (token == QChar(QChar::Tabulation))) {
218 if ((token == QChar(QChar::CarriageReturn)) && ((++i == rawLength) || (email[i] != QChar(QChar::LineFeed)))) {
223 if (elementLen == 0) {
229 contextStack.push_back(context);
230 context = ContextFWS;
232 }
else if (token == QLatin1Char(
'@')) {
234 if (contextStack.size() != 1) {
236 qCCritical(C_VALIDATOR,
"ValidatorEmail: Unexpected item on context stack");
240 if (parseLocalPart.isEmpty()) {
242 }
else if (elementLen == 0) {
244 }
else if (parseLocalPart.size() > 64) {
249 }
else if ((contextPrior == ContextComment) || (contextPrior == ContextFWS)) {
263 context = ComponentDomain;
264 contextStack.clear();
265 contextStack.push_back(context);
284 switch (contextPrior) {
289 case ContextQuotedString:
294 qCCritical(C_VALIDATOR,
"ValidatorEmail: More atext found where none is allowed, but unrecognised prior context.");
298 contextPrior = context;
299 const ushort uni = token.unicode();
301 if (!allowUtf8Local) {
302 if ((uni < 33) || (uni > 126) || stringSpecials.contains(token)) {
306 if (!token.isLetterOrNumber()) {
307 if ((uni < 33) || (uni > 126) || stringSpecials.contains(token)) {
313 parseLocalPart += token;
314 atomListLocalPart[elementCount] += token;
323 case ComponentDomain:
363 if (token == QLatin1Char(
'(')) {
364 if (elementLen == 0) {
374 contextStack.push_back(context);
375 context = ContextComment;
376 }
else if (token == QLatin1Char(
'.')) {
377 if (elementLen == 0) {
380 }
else if (hypenFlag) {
396 if (elementLen > 63) {
404 atomListDomain[elementCount] = QString();
405 parseDomain += token;
407 }
else if (token == QLatin1Char(
'[')) {
408 if (parseDomain.isEmpty()) {
411 contextStack.push_back(context);
412 context = ComponentLiteral;
413 parseDomain += token;
414 atomListDomain[elementCount] += token;
415 parseLiteral = QString();
419 }
else if ((token == QChar(QChar::CarriageReturn)) || (token == QChar(QChar::Space)) || (token == QChar(QChar::Tabulation))) {
420 if ((token == QChar(QChar::CarriageReturn)) && ((++i == rawLength) || email[i] != QChar(QChar::LineFeed))) {
425 if (elementLen == 0) {
432 contextStack.push_back(context);
433 context = ContextFWS;
461 switch (contextPrior) {
466 case ComponentLiteral:
471 qCCritical(C_VALIDATOR,
"ValidatorEmail: More atext found where none is allowed, but unrecognised prior context.");
476 const ushort uni = token.unicode();
479 if ((uni < 33) || (uni > 126) || stringSpecials.contains(token)) {
481 }
else if (token == QLatin1Char(
'-')) {
482 if (elementLen == 0) {
487 }
else if (!(((uni > 47) && (uni < 58)) || ((uni > 64) && (uni < 91)) || ((uni > 96) && (uni < 123)))) {
492 parseDomain += token;
493 atomListDomain[elementCount] += token;
501 case ComponentLiteral:
511 if (token == QLatin1Char(
']')) {
512 if (
static_cast<int>(*std::max_element(returnStatus.constBegin(), returnStatus.constEnd())) <
static_cast<int>(
ValidatorEmail::Deprecated)) {
568 QString addressLiteral = parseLiteral;
570 QRegularExpression ipv4Regex(QStringLiteral(
"\\b(?:(?: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]?)$"));
571 QRegularExpressionMatch ipv4Match = ipv4Regex.match(addressLiteral);
572 if (ipv4Match.hasMatch()) {
573 index = addressLiteral.lastIndexOf(ipv4Match.captured());
575 addressLiteral = addressLiteral.mid(0, index) + QLatin1String(
"0:0");
582 }
else if (QString::compare(addressLiteral.left(5), QLatin1String(
"IPv6:")) != 0) {
585 QString ipv6 = addressLiteral.mid(5);
586 const QStringList matchesIP = ipv6.split(QLatin1Char(
':'));
587 int groupCount = matchesIP.size();
588 index = ipv6.indexOf(QLatin1String(
"::"));
592 if (groupCount != maxGroups) {
596 if (index != ipv6.lastIndexOf(QLatin1String(
"::"))) {
599 if ((index == 0) || (index == (ipv6.length() - 2))) {
603 if (groupCount > maxGroups) {
605 }
else if (groupCount == maxGroups) {
611 if (ipv6.size() == 1 && ipv6[0] == QLatin1Char(
':') || ipv6[0] == QLatin1Char(
':') && ipv6[1] != QLatin1Char(
':')) {
613 }
else if (ipv6.right(2).at(1) == QLatin1Char(
':') && ipv6.right(2).at(0) != QLatin1Char(
':')) {
616 int unmatchedChars = 0;
617 for (
const QString &ip : matchesIP) {
618 if (!ip.contains(QRegularExpression(QStringLiteral(
"^[0-9A-Fa-f]{0,4}$")))) {
622 if (unmatchedChars != 0) {
634 parseDomain += token;
635 atomListDomain[elementCount] += token;
637 contextPrior = context;
638 context = contextStack.takeLast();
639 }
else if (token == QLatin1Char(
'\\')) {
641 contextStack.push_back(context);
642 context = ContextQuotedPair;
643 }
else if ((token == QChar(QChar::CarriageReturn)) || (token == QChar(QChar::Space)) || (token == QChar(QChar::Tabulation))) {
644 if ((token == QChar(QChar::CarriageReturn)) && ((++i == rawLength) || (email[i] != QChar(QChar::LineFeed)))) {
650 contextStack.push_back(context);
651 context = ContextFWS;
667 const ushort uni = token.unicode();
670 if ((uni > 127) || (uni == 0) || (uni == QLatin1Char(
'['))) {
673 }
else if ((uni < 33) || (uni == 127)) {
677 parseLiteral += token;
678 parseDomain += token;
679 atomListDomain[elementCount] += token;
687 case ContextQuotedString:
695 if (token == QLatin1Char(
'\\')) {
696 contextStack.push_back(context);
697 context = ContextQuotedPair;
698 }
else if ((token == QChar(QChar::CarriageReturn)) || (token == QChar(QChar::Tabulation))) {
701 if ((token == QChar(QChar::CarriageReturn)) && ((++i == rawLength) || (email[i] != QChar(QChar::LineFeed)))) {
715 parseLocalPart += QChar(QChar::Space);
716 atomListLocalPart[elementCount] += QChar(QChar::Space);
720 contextStack.push_back(context);
721 context = ContextFWS;
723 }
else if (token == QLatin1Char(
'"')) {
724 parseLocalPart += token;
725 atomListLocalPart[elementCount] +=token;
727 contextPrior = context;
728 context = contextStack.takeLast();
743 const ushort uni = token.unicode();
745 if (!allowUtf8Local) {
746 if ((uni > 127) || (uni == 0) || (uni == 10)) {
748 }
else if ((uni < 32) || (uni == 127)) {
752 if (!token.isLetterOrNumber()) {
753 if ((uni > 127) || (uni == 0) || (uni == 10)) {
755 }
else if ((uni < 32) || (uni == 127)) {
761 parseLocalPart += token;
762 atomListLocalPart[elementCount] += token;
778 case ContextQuotedPair:
796 const ushort uni = token.unicode();
800 }
else if (((uni < 31) && (uni != 9)) || (uni == 127)) {
811 contextPrior = context;
812 context = contextStack.takeLast();
817 case ContextQuotedString:
818 parseLocalPart += QLatin1Char(
'\\');
819 parseLocalPart += token;
820 atomListLocalPart[elementCount] += QLatin1Char(
'\\');
821 atomListLocalPart[elementCount] += token;
824 case ComponentLiteral:
825 parseDomain += QLatin1Char(
'\\');
826 parseDomain += token;
827 atomListDomain[elementCount] += QLatin1Char(
'\\');
828 atomListDomain[elementCount] += token;
833 qCCritical(C_VALIDATOR,
"ValidatorEmail: Quoted pair logic invoked in an invalid context.");
847 if (token == QLatin1Char(
'(')) {
849 contextStack.push_back(context);
850 context = ContextComment;
851 }
else if (token == QLatin1Char(
')')) {
852 contextPrior = context;
853 context = contextStack.takeLast();
869 }
else if (token == QLatin1Char(
'\\')) {
870 contextStack.push_back(context);
871 context = ContextQuotedPair;
872 }
else if ((token == QChar(QChar::CarriageReturn)) || (token == QChar(QChar::Space)) || (token == QChar(QChar::Tabulation))) {
873 if ((token == QChar(QChar::CarriageReturn)) && ((++i == rawLength) || (email[i] != QChar(QChar::LineFeed)))) {
879 contextStack.push_back(context);
880 context = ContextFWS;
897 const ushort uni = token.unicode();
899 if ((uni > 127) || (uni == 0) || (uni == 10)) {
902 }
else if ((uni < 32) || (uni == 127)) {
925 if (tokenPrior == QChar(QChar::CarriageReturn)) {
926 if (token == QChar(QChar::CarriageReturn)) {
931 if (crlf_count > 0) {
932 if (++crlf_count > 1) {
940 if (token == QChar(QChar::CarriageReturn)) {
941 if ((++i == rawLength) || (email[i] != QChar(QChar::LineFeed))) {
945 }
else if ((token != QChar(QChar::Space)) && (token != QChar(QChar::Tabulation))) {
946 if (tokenPrior == QChar(QChar::CarriageReturn)) {
951 if (crlf_count > 0) {
955 contextPrior = context;
956 context = contextStack.takeLast();
981 qCCritical(C_VALIDATOR,
"ValidatorEmail: Unknown context");
985 if (
static_cast<int>(*std::max_element(returnStatus.constBegin(), returnStatus.constEnd())) >
static_cast<int>(
ValidatorEmail::RFC5322)) {
991 if (
static_cast<int>(*std::max_element(returnStatus.constBegin(), returnStatus.constEnd())) <
static_cast<int>(
ValidatorEmail::RFC5322)) {
992 if (context == ContextQuotedString) {
994 }
else if (context == ContextQuotedPair) {
996 }
else if (context == ContextComment) {
998 }
else if (context == ComponentLiteral) {
1000 }
else if (token == QChar(QChar::CarriageReturn)) {
1002 }
else if (parseDomain.isEmpty()) {
1004 }
else if (elementLen == 0) {
1006 }
else if (hypenFlag) {
1008 }
else if (parseDomain.size() > 255) {
1012 }
else if ((parseLocalPart.size() + 1 + parseDomain.size()) > 254) {
1032 }
else if (elementLen > 63) {
1038 bool dnsChecked =
false;
1040 if (checkDns && (
static_cast<int>(*std::max_element(returnStatus.constBegin(), returnStatus.constEnd())) <
static_cast<int>(threshold))) {
1054 if (elementCount == 0) {
1055 parseDomain += QLatin1Char(
'.');
1058 QDnsLookup mxLookup(QDnsLookup::MX, parseDomain);
1060 QObject::connect(&mxLookup, &QDnsLookup::finished, &mxLoop, &QEventLoop::quit);
1061 QTimer::singleShot(3100, &mxLookup, &QDnsLookup::abort);
1065 if ((mxLookup.error() == QDnsLookup::NoError) && !mxLookup.mailExchangeRecords().empty()) {
1069 QDnsLookup aLookup(QDnsLookup::A, parseDomain);
1071 QObject::connect(&aLookup, &QDnsLookup::finished, &aLoop, &QEventLoop::quit);
1072 QTimer::singleShot(3100, &aLookup, &QDnsLookup::abort);
1076 if ((aLookup.error() == QDnsLookup::NoError) && !aLookup.hostAddressRecords().empty()) {
1116 if (!dnsChecked && (
static_cast<int>(*std::max_element(returnStatus.constBegin(), returnStatus.constEnd())) <
static_cast<int>(
ValidatorEmail::DNSWarn))) {
1117 if (elementCount == 0) {
1121 if (QStringLiteral(
"0123456789").contains(atomListDomain[elementCount][0])) {
1126 if (returnStatus.size() != 1) {
1127 QList<ValidatorEmail::Diagnose> _rs;
1128 for (
int j = 0; j < returnStatus.size(); ++j) {
1136 std::sort(returnStatus.begin(), returnStatus.end(), std::greater<ValidatorEmail::Diagnose>());
1141 if (diagnoseStruct) {
1142 diagnoseStruct->finalStatus = finalStatus;
1143 diagnoseStruct->returnStatus = returnStatus;
1144 diagnoseStruct->localpart = parseLocalPart;
1145 diagnoseStruct->domain = parseDomain;
1146 diagnoseStruct->literal = parseLiteral;
1149 ret = (
static_cast<int>(finalStatus) <
static_cast<int>(threshold));
1158 if (
label.isEmpty()) {
1161 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid. Please note that this does not mean that both the address and the domain actually exist. This address could be issued by the domain owner without breaking the rules of any RFCs.");
1164 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Could not find an MX record for this address’ domain but an A record does exist.");
1167 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Could neither find an MX record nor an A record for this address’ domain.");
1170 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid but at a Top Level Domain.");
1173 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid but the Top Level Domain begins with a number.");
1176 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid but contains a quoted string.");
1179 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid but uses an IP address instead of a domain name.");
1182 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid but uses an IP address that contains a :: only eliding one zero group. All implementations must accept and be able to handle any legitimate RFC 4291 format.");
1185 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains comments.");
1188 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains folding white spaces like line breaks.");
1191 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The local part is in a deprecated form.");
1194 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains an obsolete form of folding white spaces.");
1197 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A quoted string contains a deprecated character.");
1200 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A quoted pair contains a deprecated character.");
1203 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains a comment in a position that is deprecated.");
1206 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A comment contains a deprecated character.");
1209 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains a comment or folding white space around the @ sign.");
1212 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is RFC 5322 compliant but contains domain characters that are not allowed by DNS.");
1215 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is too long.");
1218 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The local part of the address is too long.");
1221 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain part is too long.");
1224 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain part contains an element that is too long.");
1227 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain literal is not a valid RFC 5321 address literal.");
1230 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain literal is not a valid RFC 5321 domain literal and it contains obsolete characters.");
1233 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 literal address contains the wrong number of groups.");
1236 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 literal address contains too many :: sequences.");
1239 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address contains an illegal group of characters.");
1242 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address has too many groups.");
1245 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address starts with a single colon.");
1248 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address ends with a single colon.");
1251 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A domain literal contains a character that is not allowed.");
1254 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address has no local part.");
1257 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address has no domain part.");
1260 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address must not contain consecutive dots.");
1263 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains text after a comment or folding white space.");
1266 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains text after a quoted string.");
1269 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Extra characters were found after the end of the domain literal.");
1272 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The Address contains a character that is not allowed in a quoted pair.");
1275 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains a character that is not allowed.");
1278 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A quoted string contains a character that is not allowed.");
1281 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A comment contains a character that is not allowed.");
1284 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address can not end with a backslash.");
1287 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Neither part of the address may begin with a dot.");
1290 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Neither part of the address may end with a dot.");
1293 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A domain or subdomain can not begin with a hyphen.");
1296 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A domain or subdomain can not end with a hyphen.");
1299 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Unclosed quoted string. (Missing double quotation mark)");
1302 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Unclosed comment. (Missing closing parantheses)");
1305 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Domain literal is missing its closing bracket.");
1308 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Folding white space contains consecutive line break sequences (CRLF).");
1311 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Folding white space ends with a line break sequence (CRLF).");
1314 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains a carriage return (CR) that is not followed by a line feed (LF).");
1317 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A fatal error occured while parsing the address.");
1329 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid. Please note that this does not mean that both the address and the domain actually exist. This address could be issued by the domain owner without breaking the rules of any RFCs.").arg(
label);
1332 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Could not find an MX record for the address’ domain in the “%1” field but an A record does exist.").arg(
label);
1335 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Could neither find an MX record nor an A record for address’ domain in the “%1” field.").arg(
label);
1338 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid but at a Top Level Domain.").arg(
label);
1341 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid but the Top Level Domain begins with a number.").arg(
label);
1344 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid but contains a quoted string.").arg(
label);
1347 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid but uses an IP address instead of a domain name.").arg(
label);
1350 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid but uses an IP address that contains a :: only eliding one zero group. All implementations must accept and be able to handle any legitimate RFC 4291 format.").arg(
label);
1353 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains comments.").arg(
label);
1356 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains folding white spaces like line breaks.").arg(
label);
1359 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The local part of the address in the “%1” field is in a deprecated form.").arg(
label);
1362 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains an obsolete form of folding white spaces.").arg(
label);
1365 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A quoted string in the address in the “%1” field contains a deprecated character.").arg(
label);
1368 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A quoted pair in the address in the “%1” field contains a deprecate character.").arg(
label);
1371 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains a comment in a position that is deprecated.").arg(
label);
1374 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A comment in the address in the “%1” field contains a deprecated character.").arg(
label);
1377 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains a comment or folding white space around the @ sign.").arg(
label);
1380 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is RFC 5322 compliant but contains domain charachters that are not allowed by DNS.").arg(
label);
1383 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is too long.").arg(
label);
1386 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The local part of the address in the “%1” field is too long.").arg(
label);
1389 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain part of the address in the “%1” field is too long.").arg(
label);
1392 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain part of the address in the “%1” field contains an element that is too long.").arg(
label);
1395 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain literal of the address in the “%1” field is not a valid RFC 5321 address literal.").arg(
label);
1398 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The domain literal of the address in the “%1” field is not a valid RFC 5321 domain literal and it contains obsolete characters.").arg(
label);
1401 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 literal of the address in the “%1” field contains the wrong number of groups.").arg(
label);
1404 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 literal of the address in the “%1” field contains too many :: sequences.").arg(
label);
1407 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address of the email address in the “%1” field contains an illegal group of characters.").arg(
label);
1410 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address of the email address in the “%1” field has too many groups.").arg(
label);
1413 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address of the email address in the “%1” field starts with a single colon.").arg(
label);
1416 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The IPv6 address of the email address in the “%1” field ends with a single colon.").arg(
label);
1419 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A domain literal of the address in the “%1” field contains a character that is not allowed.").arg(
label);
1422 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field has no local part.").arg(
label);
1425 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field has no domain part.").arg(
label);
1428 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field must not contain consecutive dots.").arg(
label);
1431 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains text after a comment or folding white space.").arg(
label);
1434 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains text after a quoted string.").arg(
label);
1437 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Extra characters were found after the end of the domain literal of the address in the “%1” field.").arg(
label);
1440 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains a character that is not allowed in a quoted pair.").arg(
label);
1443 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains a character that is not allowed.").arg(
label);
1446 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A quoted string in the address in the “%1” field contains a character that is not allowed.").arg(
label);
1449 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A comment in the address in the “%1” field contains a character that is not allowed.").arg(
label);
1452 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field can't end with a backslash.").arg(
label);
1455 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Neither part of the address in the “%1” field may begin with a dot.").arg(
label);
1458 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Neither part of the address in the “%1” field may end with a dot.").arg(
label);
1461 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A domain or subdomain of the address in the “%1” field can not begin with a hyphen.").arg(
label);
1464 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A domain or subdomain of the address in the “%1” field can not end with a hyphen.").arg(
label);
1467 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Unclosed quoted string in the address in the “%1” field. (Missing double quotation mark)").arg(
label);
1470 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Unclosed comment in the address in the “%1” field. (Missing closing parantheses)").arg(
label);
1473 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Domain literal of the address in the “%1” field is missing its closing bracket.").arg(
label);
1476 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Folding white space in the address in the “%1” field contains consecutive line break sequences (CRLF).").arg(
label);
1479 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Folding white space in the address in the “%1” field ends with a line break sequence (CRLF).").arg(
label);
1482 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains a carriage return (CR) that is not followed by a line feed (LF).").arg(
label);
1485 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"A fatal error occured while parsing the address in the “%1” field.").arg(
label);
1498 if (
label.isEmpty()) {
1501 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid.");
1504 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid but a DNS check was not successful.");
1507 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid for SMTP but has unusual elements.");
1510 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is valid within the message but can not be used unmodified for the envelope.");
1513 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address contains deprecated elements but my still be valid in restricted contexts.");
1516 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address is only valid according to the broad definition of RFC 5322. It is otherwise invalid.");
1519 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"Address is invalid for any purpose.");
1525 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid.").arg(
label);
1528 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid but a DNS check was not successful.").arg(
label);
1531 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid for SMTP but has unusual elements.").arg(
label);
1534 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is valid within the message but can not be used unmodified for the envelope.").arg(
label);
1537 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field contains deprecated elements but my still be valid in restricted contexts.").arg(
label);
1540 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is only valid according to the broad definition of RFC 5322. It is otherwise invalid.").arg(
label);
1543 ret = c->
translate(
"Cutelyst::ValidatorEmail",
"The address in the “%1” field is invalid for any purpose.").arg(
label);
1554 const quint8 diag =
static_cast<quint8
>(diagnose);
1556 if (diag <
static_cast<quint8
>(
Valid)) {
1558 }
else if (diag <
static_cast<quint8
>(
DNSWarn)) {
1560 }
else if (diag <
static_cast<quint8
>(
RFC5321)) {
1562 }
else if (diag <
static_cast<quint8
>(
CFWS)) {
1564 }
else if (diag <
static_cast<quint8
>(
Deprecated)) {
1566 }
else if (diag <
static_cast<quint8
>(
RFC5322)) {
1581 bool ValidatorEmail::validate(
const QString &email, Category threshold, Options options, QList<Cutelyst::ValidatorEmail::Diagnose> *diagnoses)
1585 ValidatorEmailDiagnoseStruct diag;
1586 ret = ValidatorEmailPrivate::checkEmail(email, options, threshold, &diag);
1589 *diagnoses = diag.returnStatus;
1595 #include "moc_validatoremail.cpp"
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Checks if the value is a valid email address according to specific RFCs.
static QString categoryString(Context *c, Category category, const QString &label=QString())
Returns a descriptive and translated string for the category.
static QString diagnoseString(Context *c, Diagnose diagnose, const QString &label=QString())
Returns a descriptive and translated string for the diagnose.
static Category category(Diagnose diagnose)
Returns the category the diagnose belongs to.
~ValidatorEmail() override
Deconstructs the email validator.
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error if validation failed.
Diagnose
Single diagnose values that show why an address is not valid.
@ ErrorUnclosedDomLiteral
ValidatorEmail(const QString &field, Category threshold=RFC5321, Options options=NoOption, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new email validator.
Category
Validation category, used as threshold to define valid addresses.
Base class for all validator rules.
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
void defaultValue(Context *c, ValidatorReturnType *result, const char *validatorName) const
I a defValKey has been set in the constructor, this will try to get the default value from the stash ...
QString value(const ParamsMultiMap ¶ms) const
Returns the value of the field from the input params.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
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.
QMultiMap< QString, QString > ParamsMultiMap
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.