mirror of
https://github.com/dawidd6/action-send-mail.git
synced 2026-05-06 17:30:35 +07:00
node_modules: update (#290)
Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
171
node_modules/nodemailer/lib/mime-node/index.js
generated
vendored
171
node_modules/nodemailer/lib/mime-node/index.js
generated
vendored
@@ -5,7 +5,7 @@
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const punycode = require('../punycode');
|
||||
const PassThrough = require('stream').PassThrough;
|
||||
const { PassThrough } = require('stream');
|
||||
const shared = require('../shared');
|
||||
|
||||
const mimeFuncs = require('../mime-funcs');
|
||||
@@ -19,6 +19,8 @@ const LastNewline = require('./last-newline');
|
||||
const LeWindows = require('./le-windows');
|
||||
const LeUnix = require('./le-unix');
|
||||
|
||||
const FORMATTED_HEADERS = ['From', 'Sender', 'To', 'Cc', 'Bcc', 'Reply-To', 'Date', 'References'];
|
||||
|
||||
/**
|
||||
* Creates a new mime tree node. Assumes 'multipart/*' as the content type
|
||||
* if it is a branch, anything else counts as leaf. If rootNode is missing from
|
||||
@@ -54,7 +56,7 @@ class MimeNode {
|
||||
/**
|
||||
* If date headers is missing and current node is the root, this value is used instead
|
||||
*/
|
||||
this.date = new Date();
|
||||
this.date = options.parentNode ? null : new Date();
|
||||
|
||||
/**
|
||||
* Root node for current mime tree
|
||||
@@ -175,7 +177,7 @@ class MimeNode {
|
||||
options = contentType;
|
||||
contentType = undefined;
|
||||
}
|
||||
let node = new MimeNode(contentType, options);
|
||||
const node = new MimeNode(contentType, options);
|
||||
this.appendChild(node);
|
||||
return node;
|
||||
}
|
||||
@@ -256,8 +258,7 @@ class MimeNode {
|
||||
* @return {Object} current node
|
||||
*/
|
||||
setHeader(key, value) {
|
||||
let added = false,
|
||||
headerValue;
|
||||
let added = false;
|
||||
|
||||
// Allow setting multiple headers at once
|
||||
if (!value && key && typeof key === 'object') {
|
||||
@@ -280,7 +281,7 @@ class MimeNode {
|
||||
|
||||
key = this._normalizeHeaderKey(key);
|
||||
|
||||
headerValue = {
|
||||
const headerValue = {
|
||||
key,
|
||||
value
|
||||
};
|
||||
@@ -404,8 +405,8 @@ class MimeNode {
|
||||
});
|
||||
}
|
||||
|
||||
let stream = this.createReadStream();
|
||||
let buf = [];
|
||||
const stream = this.createReadStream();
|
||||
const buf = [];
|
||||
let buflen = 0;
|
||||
let returned = false;
|
||||
|
||||
@@ -445,7 +446,7 @@ class MimeNode {
|
||||
|
||||
getTransferEncoding() {
|
||||
let transferEncoding = false;
|
||||
let contentType = (this.getHeader('Content-Type') || '').toString().toLowerCase().trim();
|
||||
const contentType = (this.getHeader('Content-Type') || '').toString().toLowerCase().trim();
|
||||
|
||||
if (this.content) {
|
||||
transferEncoding = (this.getHeader('Content-Transfer-Encoding') || '').toString().toLowerCase().trim();
|
||||
@@ -475,8 +476,8 @@ class MimeNode {
|
||||
* @returns {String} Headers
|
||||
*/
|
||||
buildHeaders() {
|
||||
let transferEncoding = this.getTransferEncoding();
|
||||
let headers = [];
|
||||
const transferEncoding = this.getTransferEncoding();
|
||||
const headers = [];
|
||||
|
||||
if (transferEncoding) {
|
||||
this.setHeader('Content-Transfer-Encoding', transferEncoding);
|
||||
@@ -501,7 +502,7 @@ class MimeNode {
|
||||
|
||||
// Ensure that Content-Type is the last header for the root node
|
||||
for (let i = this._headers.length - 2; i >= 0; i--) {
|
||||
let header = this._headers[i];
|
||||
const header = this._headers[i];
|
||||
if (header.key === 'Content-Type') {
|
||||
this._headers.splice(i, 1);
|
||||
this._headers.push(header);
|
||||
@@ -514,8 +515,8 @@ class MimeNode {
|
||||
let value = header.value;
|
||||
let structured;
|
||||
let param;
|
||||
let options = {};
|
||||
let formattedHeaders = ['From', 'Sender', 'To', 'Cc', 'Bcc', 'Reply-To', 'Date', 'References'];
|
||||
const options = {};
|
||||
const formattedHeaders = FORMATTED_HEADERS;
|
||||
|
||||
if (value && typeof value === 'object' && !formattedHeaders.includes(key)) {
|
||||
Object.keys(value).forEach(key => {
|
||||
@@ -593,7 +594,7 @@ class MimeNode {
|
||||
}
|
||||
|
||||
if (typeof this.normalizeHeaderKey === 'function') {
|
||||
let normalized = this.normalizeHeaderKey(key, value);
|
||||
const normalized = this.normalizeHeaderKey(key, value);
|
||||
if (normalized && typeof normalized === 'string' && normalized.length) {
|
||||
key = normalized;
|
||||
}
|
||||
@@ -614,7 +615,7 @@ class MimeNode {
|
||||
createReadStream(options) {
|
||||
options = options || {};
|
||||
|
||||
let stream = new PassThrough(options);
|
||||
const stream = new PassThrough(options);
|
||||
let outputStream = stream;
|
||||
let transform;
|
||||
|
||||
@@ -682,13 +683,13 @@ class MimeNode {
|
||||
}
|
||||
|
||||
stream(outputStream, options, done) {
|
||||
let transferEncoding = this.getTransferEncoding();
|
||||
const transferEncoding = this.getTransferEncoding();
|
||||
let contentStream;
|
||||
let localStream;
|
||||
|
||||
// protect actual callback against multiple triggering
|
||||
let returned = false;
|
||||
let callback = err => {
|
||||
const callback = err => {
|
||||
if (returned) {
|
||||
return;
|
||||
}
|
||||
@@ -698,14 +699,14 @@ class MimeNode {
|
||||
|
||||
// for multipart nodes, push child nodes
|
||||
// for content nodes end the stream
|
||||
let finalize = () => {
|
||||
const finalize = () => {
|
||||
let childId = 0;
|
||||
let processChildNode = () => {
|
||||
const processChildNode = () => {
|
||||
if (childId >= this.childNodes.length) {
|
||||
outputStream.write('\r\n--' + this.boundary + '--\r\n');
|
||||
return callback();
|
||||
}
|
||||
let child = this.childNodes[childId++];
|
||||
const child = this.childNodes[childId++];
|
||||
outputStream.write((childId > 1 ? '\r\n' : '') + '--' + this.boundary + '\r\n');
|
||||
child.stream(outputStream, options, err => {
|
||||
if (err) {
|
||||
@@ -723,7 +724,7 @@ class MimeNode {
|
||||
};
|
||||
|
||||
// pushes node content
|
||||
let sendContent = () => {
|
||||
const sendContent = () => {
|
||||
if (this.content) {
|
||||
if (Object.prototype.toString.call(this.content) === '[object Error]') {
|
||||
// content is already errored
|
||||
@@ -736,7 +737,7 @@ class MimeNode {
|
||||
this.content.once('error', this._contentErrorHandler);
|
||||
}
|
||||
|
||||
let createStream = () => {
|
||||
const createStream = () => {
|
||||
if (['quoted-printable', 'base64'].includes(transferEncoding)) {
|
||||
contentStream = new (transferEncoding === 'base64' ? base64 : qp).Encoder(options);
|
||||
|
||||
@@ -761,10 +762,10 @@ class MimeNode {
|
||||
};
|
||||
|
||||
if (this.content._resolve) {
|
||||
let chunks = [];
|
||||
const chunks = [];
|
||||
let chunklen = 0;
|
||||
let returned = false;
|
||||
let sourceStream = this._getStream(this.content);
|
||||
const sourceStream = this._getStream(this.content);
|
||||
sourceStream.on('error', err => {
|
||||
if (returned) {
|
||||
return;
|
||||
@@ -792,9 +793,8 @@ class MimeNode {
|
||||
setImmediate(createStream);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
return setImmediate(finalize);
|
||||
}
|
||||
return setImmediate(finalize);
|
||||
};
|
||||
|
||||
if (this._raw) {
|
||||
@@ -809,7 +809,7 @@ class MimeNode {
|
||||
this._raw.removeListener('error', this._contentErrorHandler);
|
||||
}
|
||||
|
||||
let raw = this._getStream(this._raw);
|
||||
const raw = this._getStream(this._raw);
|
||||
raw.pipe(outputStream, {
|
||||
end: false
|
||||
});
|
||||
@@ -851,7 +851,7 @@ class MimeNode {
|
||||
|
||||
this._envelope.to = this._envelope.to.map(to => to.address).filter(address => address);
|
||||
|
||||
let standardFields = ['to', 'cc', 'bcc', 'from'];
|
||||
const standardFields = ['to', 'cc', 'bcc', 'from'];
|
||||
Object.keys(envelope).forEach(key => {
|
||||
if (!standardFields.includes(key)) {
|
||||
this._envelope[key] = envelope[key];
|
||||
@@ -867,10 +867,10 @@ class MimeNode {
|
||||
* @return {Object} Address object
|
||||
*/
|
||||
getAddresses() {
|
||||
let addresses = {};
|
||||
const addresses = {};
|
||||
|
||||
this._headers.forEach(header => {
|
||||
let key = header.key.toLowerCase();
|
||||
const key = header.key.toLowerCase();
|
||||
if (['from', 'sender', 'reply-to', 'to', 'cc', 'bcc'].includes(key)) {
|
||||
if (!Array.isArray(addresses[key])) {
|
||||
addresses[key] = [];
|
||||
@@ -893,12 +893,12 @@ class MimeNode {
|
||||
return this._envelope;
|
||||
}
|
||||
|
||||
let envelope = {
|
||||
const envelope = {
|
||||
from: false,
|
||||
to: []
|
||||
};
|
||||
this._headers.forEach(header => {
|
||||
let list = [];
|
||||
const list = [];
|
||||
if (header.key === 'From' || (!envelope.from && ['Reply-To', 'Sender'].includes(header.key))) {
|
||||
this._convertAddresses(this._parseAddresses(header.value), list);
|
||||
if (list.length && list[0]) {
|
||||
@@ -974,14 +974,18 @@ class MimeNode {
|
||||
});
|
||||
|
||||
return contentStream;
|
||||
} else if (typeof content.pipe === 'function') {
|
||||
}
|
||||
|
||||
if (typeof content.pipe === 'function') {
|
||||
// assume as stream
|
||||
return content;
|
||||
} else if (content && typeof content.path === 'string' && !content.href) {
|
||||
}
|
||||
|
||||
if (content && typeof content.path === 'string' && !content.href) {
|
||||
if (this.disableFileAccess) {
|
||||
contentStream = new PassThrough();
|
||||
setImmediate(() => {
|
||||
let err = new Error('File access rejected for ' + content.path);
|
||||
const err = new Error('File access rejected for ' + content.path);
|
||||
err.code = errors.EFILEACCESS;
|
||||
contentStream.emit('error', err);
|
||||
});
|
||||
@@ -989,11 +993,13 @@ class MimeNode {
|
||||
}
|
||||
// read file
|
||||
return fs.createReadStream(content.path);
|
||||
} else if (content && typeof content.href === 'string') {
|
||||
}
|
||||
|
||||
if (content && typeof content.href === 'string') {
|
||||
if (this.disableUrlAccess) {
|
||||
contentStream = new PassThrough();
|
||||
setImmediate(() => {
|
||||
let err = new Error('Url access rejected for ' + content.href);
|
||||
const err = new Error('Url access rejected for ' + content.href);
|
||||
err.code = errors.EURLACCESS;
|
||||
contentStream.emit('error', err);
|
||||
});
|
||||
@@ -1001,19 +1007,19 @@ class MimeNode {
|
||||
}
|
||||
// fetch URL
|
||||
return nmfetch(content.href, { headers: content.httpHeaders });
|
||||
} else {
|
||||
// pass string or buffer content as a stream
|
||||
contentStream = new PassThrough();
|
||||
|
||||
setImmediate(() => {
|
||||
try {
|
||||
contentStream.end(content || '');
|
||||
} catch (_err) {
|
||||
contentStream.emit('error', _err);
|
||||
}
|
||||
});
|
||||
return contentStream;
|
||||
}
|
||||
|
||||
// pass string or buffer content as a stream
|
||||
contentStream = new PassThrough();
|
||||
|
||||
setImmediate(() => {
|
||||
try {
|
||||
contentStream.end(content || '');
|
||||
} catch (_err) {
|
||||
contentStream.emit('error', _err);
|
||||
}
|
||||
});
|
||||
return contentStream;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1172,7 +1178,7 @@ class MimeNode {
|
||||
* @return {String} address string
|
||||
*/
|
||||
_convertAddresses(addresses, uniqueList) {
|
||||
let values = [];
|
||||
const values = [];
|
||||
|
||||
uniqueList = uniqueList || [];
|
||||
|
||||
@@ -1182,17 +1188,15 @@ class MimeNode {
|
||||
|
||||
if (!address.name) {
|
||||
values.push(address.address.indexOf(' ') >= 0 ? `<${address.address}>` : `${address.address}`);
|
||||
} else if (address.name) {
|
||||
} else {
|
||||
values.push(`${this._encodeAddressName(address.name)} <${address.address}>`);
|
||||
}
|
||||
|
||||
if (address.address) {
|
||||
if (!uniqueList.filter(a => a.address === address.address).length) {
|
||||
uniqueList.push(address);
|
||||
}
|
||||
if (!uniqueList.some(a => a.address === address.address)) {
|
||||
uniqueList.push(address);
|
||||
}
|
||||
} else if (address.group) {
|
||||
let groupListAddresses = (address.group.length ? this._convertAddresses(address.group, uniqueList) : '').trim();
|
||||
const groupListAddresses = (address.group.length ? this._convertAddresses(address.group, uniqueList) : '').trim();
|
||||
values.push(`${this._encodeAddressName(address.name)}:${groupListAddresses};`);
|
||||
}
|
||||
});
|
||||
@@ -1212,26 +1216,30 @@ class MimeNode {
|
||||
.replace(/[\x00-\x1F<>]+/g, ' ') // remove unallowed characters
|
||||
.trim();
|
||||
|
||||
let lastAt = address.lastIndexOf('@');
|
||||
const lastAt = address.lastIndexOf('@');
|
||||
if (lastAt < 0) {
|
||||
// Bare username
|
||||
return address;
|
||||
}
|
||||
|
||||
let user = address.substr(0, lastAt);
|
||||
let domain = address.substr(lastAt + 1);
|
||||
const domain = address.substr(lastAt + 1);
|
||||
|
||||
// Usernames are not touched and are kept as is even if these include unicode
|
||||
// Domains are punycoded by default
|
||||
// 'jõgeva.ee' will be converted to 'xn--jgeva-dua.ee'
|
||||
// non-unicode domains are left as is
|
||||
// Usernames are not touched and are kept as is even if these include unicode.
|
||||
// Domains are punycoded when the local part is ASCII ('safe@jõgeva.ee' -> 'safe@xn--jgeva-dua.ee').
|
||||
// When the local part contains non-ASCII bytes the address already requires SMTPUTF8,
|
||||
// so the domain is kept (or decoded back) as UTF-8 for symmetry on both sides of '@'.
|
||||
|
||||
let encodedDomain;
|
||||
let encodedDomain = domain;
|
||||
|
||||
try {
|
||||
encodedDomain = punycode.toASCII(domain.toLowerCase());
|
||||
if (/[\x80-\uFFFF]/.test(user)) {
|
||||
encodedDomain = punycode.toUnicode(domain.toLowerCase());
|
||||
} else {
|
||||
encodedDomain = punycode.toASCII(domain.toLowerCase());
|
||||
}
|
||||
} catch (_err) {
|
||||
// keep as is?
|
||||
// keep domain as supplied
|
||||
}
|
||||
|
||||
if (user.indexOf(' ') >= 0) {
|
||||
@@ -1285,20 +1293,25 @@ class MimeNode {
|
||||
_getTextEncoding(value) {
|
||||
value = (value || '').toString();
|
||||
|
||||
let encoding = this.textEncoding;
|
||||
let latinLen;
|
||||
let nonLatinLen;
|
||||
|
||||
if (!encoding) {
|
||||
// count latin alphabet symbols and 8-bit range symbols + control symbols
|
||||
// if there are more latin characters, then use quoted-printable
|
||||
// encoding, otherwise use base64
|
||||
nonLatinLen = (value.match(/[\x00-\x08\x0B\x0C\x0E-\x1F\u0080-\uFFFF]/g) || []).length;
|
||||
latinLen = (value.match(/[a-z]/gi) || []).length;
|
||||
// if there are more latin symbols than binary/unicode, then prefer Q, otherwise B
|
||||
encoding = nonLatinLen < latinLen ? 'Q' : 'B';
|
||||
if (this.textEncoding) {
|
||||
return this.textEncoding;
|
||||
}
|
||||
return encoding;
|
||||
|
||||
// count latin alphabet symbols and 8-bit range symbols + control symbols
|
||||
// if there are more latin characters, then use quoted-printable
|
||||
// encoding, otherwise use base64
|
||||
let nonLatinLen = 0;
|
||||
let latinLen = 0;
|
||||
for (let i = 0, len = value.length; i < len; i++) {
|
||||
const code = value.charCodeAt(i);
|
||||
if ((code >= 0x00 && code <= 0x08) || code === 0x0b || code === 0x0c || (code >= 0x0e && code <= 0x1f) || code >= 0x80) {
|
||||
nonLatinLen++;
|
||||
} else if ((code >= 0x41 && code <= 0x5a) || (code >= 0x61 && code <= 0x7a)) {
|
||||
latinLen++;
|
||||
}
|
||||
}
|
||||
// if there are more latin symbols than binary/unicode, then prefer Q, otherwise B
|
||||
return nonLatinLen < latinLen ? 'Q' : 'B';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user