Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const localParts = this.parseLocal();
const local = localParts.join('.');
// If there's no domain (i.e. there's no @-symbol) then there's no point
// in considering the rest. TODO: Maybe have parseLocal pushback the @?
if (this._diagnoses.hasDiagnosis(Constants.diagnoses.errNoDomain)) {
return null;
}
const { elements: domainParts, domain } = this.parseDomain();
const normalizedEmail = `${local}@${Punycode.toASCII(domain)}`;
// TODO: Should we normalize the domain one way or another?
const domainLength = /^[\x00-\x7f]+$/.test(domain) ? domain.length : Punycode.toASCII(domain).length;
const emailLength = Buffer.byteLength(local, 'utf8') + domainLength + 1;
// TODO: Add test for CFWS not impacting this?
if (emailLength > 254) {
// http://tools.ietf.org/html/rfc5321#section-4.1.2
// Forward-path = Path
//
// Path = "<" [ A-d-l ":" ] Mailbox ">"
//
// http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3
// The maximum total length of a reverse-path or forward-path is 256 octets (including the punctuation and element separators).
//
// Thus, even without (obsolete) routing information, the Mailbox can only be 254 characters long. This is confirmed by this verified
// erratum to RFC 3696:
//
// http://www.rfc-editor.org/errata_search.php?rfc=3696&eid=1690
// However, there is a restriction in RFC 2821 on the length of an address in MAIL and RCPT commands of 254 characters. Since
parseDomain(address, isSender = true) {
let domain = addressParser(address)[0].address.split('@')[1];
domain = punycode.toASCII(domain);
// check against blacklist
if (this.isBlacklisted(domain))
throw new CustomError(
`The domain ${domain} is blacklisted by ${this.config.website}`
);
// ensure fully qualified domain name
/*
if (!validator.isFQDN(domain))
throw new CustomError(
`${domain} is not a fully qualified domain name ("FQDN")`
);
*/
// prevent disposable email addresses from being used
case '.':
if (assertEnd === 'literal') {
// TODO: This isn't quite the right diagnosis
this.diagnose(Constants.diagnoses.errDotAfterDomainLiteral);
}
// Next dot-atom element
if (!element) {
// Another dot, already? Fatal error.
this.diagnose(elements.length === 0 ? Constants.diagnoses.errDotStart : Constants.diagnoses.errConsecutiveDots);
}
else if (element[element.length - 1] === '-') {
// Previous subdomain ended in a hyphen. Fatal error.
this.diagnose(Constants.diagnoses.errDomainHyphenEnd, this._reader.prevIndex - 1);
}
else if (Punycode.toASCII(element).length > 63) {
// RFC 5890 specifies that domain labels that are encoded using the Punycode algorithm
// must adhere to the <= 63 octet requirement.
// This includes string prefixes from the Punycode algorithm.
//
// https://tools.ietf.org/html/rfc5890#section-2.3.2.1
// labels 63 octets or less
this.diagnose(Constants.diagnoses.rfc5322LabelTooLong);
}
// CFWS is OK again now we're at the beginning of an element (although
// it may be obsolete CFWS)
assertEnd = null;
elements.push(element);
element = '';
if (element[element.length - 1] === '-') {
// TODO: Fix the index on this
this.diagnose(Constants.diagnoses.errDomainHyphenEnd);
}
// Per RFC 5321, domain atoms are limited to letter-digit-hyphen, so we only need to check code <= 57 to check for a digit.
// This also works with i18n domains.
if (element.codePointAt(0) <= 57) {
this.diagnose(Constants.diagnoses.rfc5321TLDNumeric);
}
if (Punycode.toASCII(element).length > 63) {
this.diagnose(Constants.diagnoses.rfc5322LabelTooLong);
}
if (Punycode.toASCII(elements.join('.')).length > 255) {
// http://tools.ietf.org/html/rfc5321#section-4.5.3.1.2
// The maximum total length of a domain name or number is 255 octets.
this.diagnose(Constants.diagnoses.rfc5322DomainTooLong);
}
}
// TODO: Also validate minDomainAtoms, tldAllow/tldForbid
return { elements, domain: elements.join('.') };
}
getPunycodeUrl: function (url) {
try {
const parsed = urlParse(url)
parsed.hostname = punycode.toASCII(parsed.hostname)
return urlFormat(parsed)
} catch (e) {
var splitUrl = url.split('@')
splitUrl = splitUrl.map(str => punycode.toASCII(str))
return splitUrl.join('@')
}
},
parseUsername(address) {
({ address } = addressParser(address)[0]);
let username = address.includes('+')
? address.split('+')[0]
: address.split('@')[0];
username = punycode.toASCII(username).toLowerCase();
return username;
}
internals.canonicalizeAtom = function (atom) {
return Punycode.toASCII(atom).toLowerCase();
};