mirror of
https://github.com/dawidd6/action-send-mail.git
synced 2026-10-19 14:04:32 +07:00
node_modules: update (#349)
Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
1 parent
9d0c26ec8b
commit
0a1f5db16c
36 files changed
+1934
-648
No files matched your search
+97
-22
@@ -64,6 +64,35 @@ const QUOTED_STRING = /^"(?:[^"\\]|\\[\s\S])*"$/;
|
||||
// else goes into angle brackets so that the header can not be read as more addresses than
|
||||
// the envelope carries
|
||||
const PLAIN_ADDRESS = /^[^\s"(),:;<>@[\\\]]+@[^\s"(),:;<>@[\\\]]+$/;
|
||||
/**
|
||||
* A domain literal that ends an address, see _normalizeAddress
|
||||
*/
|
||||
const DOMAIN_LITERAL_TAIL = /@(\[[^[\]\\]*\])$/;
|
||||
/**
|
||||
* Removes the whitespace inside every <...> of a References value. A "<" with no ">" after
|
||||
* it is left as it is. An index scan, the regex /<[^>]*>/g rescans the rest of the value
|
||||
* from every such "<"
|
||||
*
|
||||
* @param value References header value
|
||||
* @returns The value with the msg-ids closed up
|
||||
*/
|
||||
function stripWhitespaceInAngleBrackets(value) {
|
||||
let result = '';
|
||||
let pos = 0;
|
||||
for (;;) {
|
||||
const open = value.indexOf('<', pos);
|
||||
if (open < 0) {
|
||||
break;
|
||||
}
|
||||
const close = value.indexOf('>', open + 1);
|
||||
if (close < 0) {
|
||||
break;
|
||||
}
|
||||
result += value.slice(pos, open) + value.slice(open, close + 1).replace(/\s/g, '');
|
||||
pos = close + 1;
|
||||
}
|
||||
return result + value.slice(pos);
|
||||
}
|
||||
// domainToASCII and domainToUnicode are WHATWG host parsers rather than plain IDNA
|
||||
// mappers, so they do more than map: they cut the host at '/', '\\', '?' and '#', drop C0
|
||||
// controls, and percent-decode. Handing them 'evil.example/mail.corp.example' returns the
|
||||
@@ -71,6 +100,13 @@ const PLAIN_ADDRESS = /^[^\s"(),:;<>@[\\\]]+@[^\s"(),:;<>@[\\\]]+$/;
|
||||
// unroutable garbage into mail for a domain the sender never named. None of these
|
||||
// characters are legal in a domain, so keep them away from the mapper.
|
||||
const URL_PARSER_UNSAFE = /[/\\?#%\x00-\x20\x7F]/;
|
||||
// RFC 1035 bounds a label at 63 octets and a domain at 253. An A-label is never shorter than
|
||||
// the code points it encodes, so anything past these bounds could not have become a valid
|
||||
// domain whichever way it is encoded. The bundled codec is super-linear in the length of a
|
||||
// label, a 60 KB label of distinct code points took seconds to encode, several times per
|
||||
// address, so it is only handed what could be a domain
|
||||
const MAX_DOMAIN_LENGTH = 253;
|
||||
const MAX_LABEL_LENGTH = 63;
|
||||
// pipeline() needs a callback to not throw, the errors it sees reach the last stream anyway
|
||||
const PIPELINE_NOOP = () => false;
|
||||
// The error a node streaming into an output that was destroyed stops with
|
||||
@@ -79,6 +115,27 @@ function abortedError() {
|
||||
err.code = errors.ESTREAM;
|
||||
return err;
|
||||
}
|
||||
/**
|
||||
* Checks a domain against the DNS length limits, counted in code points per label and in
|
||||
* total. The label separators are the ones the bundled codec splits on.
|
||||
*
|
||||
* @param domain Domain to check
|
||||
* @return true if a label or the domain as a whole is too long to be a valid domain
|
||||
*/
|
||||
function exceedsDomainLimits(domain) {
|
||||
let total = 0;
|
||||
let label = 0;
|
||||
for (const char of domain) {
|
||||
total++;
|
||||
if (char === '.' || char === '。' || char === '.' || char === '。') {
|
||||
label = 0;
|
||||
}
|
||||
else if (++label > MAX_LABEL_LENGTH) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return total > MAX_DOMAIN_LENGTH;
|
||||
}
|
||||
/**
|
||||
* Encodes a domain the way browsers, the WHATWG URL Standard and DNS facing resolvers do,
|
||||
* which is with UTS-46 mapping applied before the Punycode step.
|
||||
@@ -110,6 +167,10 @@ function normalizeDomain(domain, toUnicode) {
|
||||
return mapped;
|
||||
}
|
||||
}
|
||||
if (exceedsDomainLimits(domain)) {
|
||||
// too long to be a domain whichever way it is encoded, keep it as supplied
|
||||
return domain;
|
||||
}
|
||||
return toUnicode ? punycode.toUnicode(domain) : punycode.toASCII(domain);
|
||||
}
|
||||
/**
|
||||
@@ -614,6 +675,17 @@ class MimeNode {
|
||||
/[\u0080-\uFFFF]/.test(this.content)) {
|
||||
structured.params.charset = 'utf-8';
|
||||
}
|
||||
if (this.filename) {
|
||||
// the name parameter is derived from the filename below, so a name that
|
||||
// arrived inside the content type is dropped first (a plain parameter or
|
||||
// rfc2231 continuation sections), otherwise the header carries two and a
|
||||
// receiver that reads the first sees a name the filename does not match
|
||||
for (const paramKey of Object.keys(structured.params)) {
|
||||
if (/^name(\*|$)/i.test(paramKey)) {
|
||||
delete structured.params[paramKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
value = mimeFuncs.buildHeaderValue(structured);
|
||||
if (this.filename) {
|
||||
// add support for non-compliant clients like QQ webmail
|
||||
@@ -1223,12 +1295,12 @@ class MimeNode {
|
||||
_normalizeHeaderKey(key) {
|
||||
key = (key || '')
|
||||
.toString()
|
||||
// no newlines in keys
|
||||
.replace(/\r?\n|\r/g, ' ')
|
||||
// a field name is printable ascii without the colon, so a control char or DEL
|
||||
// can only be dropped, there is no quoting construct around a field name
|
||||
.replace(/[\x00-\x1f\x7f]/g, '')
|
||||
.trim()
|
||||
// a field name is printable ascii without the colon, so a control char, DEL,
|
||||
// whitespace or a colon can only be dropped, there is no quoting construct
|
||||
// around a field name. A colon or a space left in place ends the name early on
|
||||
// the wire: the key 'From: ceo@example.com (' with the value ')' was emitted as a
|
||||
// second From header that neither setHeader() nor the Bcc filter could match
|
||||
.replace(/[\s\x00-\x20\x7f:]/g, '')
|
||||
.toLowerCase()
|
||||
// use uppercase words, except MIME
|
||||
.replace(/^X-SMTPAPI$|^(MIME|DKIM|ARC|BIMI)\b|^[a-z]|-(SPF|FBL|ID|MD5)$|-[a-z]/gi, c => c.toUpperCase())
|
||||
@@ -1314,26 +1386,26 @@ class MimeNode {
|
||||
}
|
||||
return value;
|
||||
// space separated list of values enclosed in <>
|
||||
case 'References':
|
||||
value = [].concat
|
||||
.apply([], [].concat(value || '').map(elm => {
|
||||
elm = (elm || '')
|
||||
case 'References': {
|
||||
const ids = [];
|
||||
for (const entry of [].concat(value || '')) {
|
||||
const elm = (entry || '')
|
||||
.toString()
|
||||
.replace(/\r?\n|\r/g, ' ')
|
||||
.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
|
||||
.trim();
|
||||
return elm.replace(/<[^>]*>/g, str => str.replace(/\s/g, '')).split(/\s+/);
|
||||
}))
|
||||
.map(elm => {
|
||||
if (elm.charAt(0) !== '<') {
|
||||
elm = '<' + elm;
|
||||
for (let id of stripWhitespaceInAngleBrackets(elm).split(/\s+/)) {
|
||||
if (id.charAt(0) !== '<') {
|
||||
id = '<' + id;
|
||||
}
|
||||
if (id.charAt(id.length - 1) !== '>') {
|
||||
id = id + '>';
|
||||
}
|
||||
ids.push(id);
|
||||
}
|
||||
if (elm.charAt(elm.length - 1) !== '>') {
|
||||
elm = elm + '>';
|
||||
}
|
||||
return elm;
|
||||
});
|
||||
return value.join(' ').trim();
|
||||
}
|
||||
return ids.join(' ').trim();
|
||||
}
|
||||
case 'Date':
|
||||
if (Object.prototype.toString.call(value) === '[object Date]') {
|
||||
return value.toUTCString().replace(/GMT/, '+0000');
|
||||
@@ -1412,7 +1484,10 @@ class MimeNode {
|
||||
// callers use an empty value to detect a missing address
|
||||
return address;
|
||||
}
|
||||
const lastAt = address.lastIndexOf('@');
|
||||
// dtext includes '@', so a domain literal is split off at the '@' in front of it and
|
||||
// not at the last one, which delivered 'a@[x@evil.com]' to evil.com
|
||||
const literal = address.charAt(address.length - 1) === ']' ? DOMAIN_LITERAL_TAIL.exec(address) : null;
|
||||
const lastAt = literal ? address.length - literal[1].length - 1 : address.lastIndexOf('@');
|
||||
if (lastAt < 0) {
|
||||
// Bare username, there is no domain to split off
|
||||
return this._normalizeLocalPart(address);
|
||||
|
||||
Reference in new issue
Block a user