mirror of
https://github.com/dawidd6/action-send-mail.git
synced 2026-09-17 09:06:48 +07:00
node_modules: update (#322)
Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
+341
@@ -0,0 +1,341 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const shared = __importStar(require("../shared/index.js"));
|
||||
const index_js_1 = __importDefault(require("../mime-node/index.js"));
|
||||
const mimeFuncs = __importStar(require("../mime-funcs/index.js"));
|
||||
// Only an own key counts as already set. `key in obj` also matches every member of
|
||||
// Object.prototype, which silently drops a transporter default legitimately named
|
||||
// toString or constructor.
|
||||
const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
||||
class MailMessage {
|
||||
constructor(mailer, data) {
|
||||
this.mailer = mailer;
|
||||
this.data = {};
|
||||
this.message = null;
|
||||
data = data || {};
|
||||
const options = mailer.options || {};
|
||||
const defaults = mailer._defaults || {};
|
||||
shared.copyOwnKeys(this.data, data);
|
||||
this.data.headers = this.data.headers || {};
|
||||
// Apply defaults. `_defaults` is caller supplied too, it is the second argument of
|
||||
// createTransport, so it needs the same treatment as `data` above
|
||||
shared.copyOwnKeys(this.data, defaults, key => hasOwn(this.data, key));
|
||||
// headers is a special case. Allow setting individual default headers
|
||||
shared.copyOwnKeys(this.data.headers, defaults.headers, key => hasOwn(this.data.headers, key));
|
||||
// force specific keys from transporter options
|
||||
['disableFileAccess', 'disableUrlAccess', 'normalizeHeaderKey', 'maxRecipients'].forEach(key => {
|
||||
if (key in options) {
|
||||
this.data[key] = options[key];
|
||||
}
|
||||
});
|
||||
// The access flags are a sandbox rather than a message field, so `defaults` counts as
|
||||
// transporter configuration for them. For a transporter plugin it is the only channel
|
||||
// there is, createTransport leaves `options` undefined for one, and the defaults copy
|
||||
// above yields to anything the message already set, which let message data switch the
|
||||
// sandbox back off. Closing is one way here, same as in resolveContent below: either
|
||||
// side may switch a flag on, neither can switch off what the other closed.
|
||||
['disableFileAccess', 'disableUrlAccess'].forEach(key => {
|
||||
if (!(key in options) && hasOwn(defaults, key)) {
|
||||
this.data[key] = this.data[key] || defaults[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
resolveContent(data, key, options, callback) {
|
||||
// Most plugins call this with the legacy (data, key, callback) signature, which carries
|
||||
// no access policy. The policy belongs to the message, so apply it here. Explicit
|
||||
// options may only tighten it, never reopen what the transporter closed.
|
||||
if (!callback && typeof options === 'function') {
|
||||
callback = options;
|
||||
options = false;
|
||||
}
|
||||
options = options || {};
|
||||
const policy = {
|
||||
disableFileAccess: this.data.disableFileAccess || options.disableFileAccess,
|
||||
disableUrlAccess: this.data.disableUrlAccess || options.disableUrlAccess
|
||||
};
|
||||
return shared.resolveContent(data, key, policy, callback);
|
||||
}
|
||||
resolveAll(callback) {
|
||||
const keys = [
|
||||
[this.data, 'html'],
|
||||
[this.data, 'text'],
|
||||
[this.data, 'watchHtml'],
|
||||
[this.data, 'amp'],
|
||||
[this.data, 'icalEvent']
|
||||
];
|
||||
if (this.data.alternatives && this.data.alternatives.length) {
|
||||
this.data.alternatives.forEach((alternative, i) => {
|
||||
keys.push([this.data.alternatives, i]);
|
||||
});
|
||||
}
|
||||
if (this.data.attachments && this.data.attachments.length) {
|
||||
this.data.attachments.forEach((attachment, i) => {
|
||||
if (!attachment.filename) {
|
||||
attachment.filename =
|
||||
(attachment.path || attachment.href || '').split('/').pop().split('?').shift() ||
|
||||
'attachment-' + (i + 1);
|
||||
if (attachment.filename.indexOf('.') < 0) {
|
||||
attachment.filename += '.' + mimeFuncs.detectExtension(attachment.contentType);
|
||||
}
|
||||
}
|
||||
if (!attachment.contentType) {
|
||||
attachment.contentType = mimeFuncs.detectMimeType(attachment.filename || attachment.path || attachment.href || 'bin');
|
||||
}
|
||||
keys.push([this.data.attachments, i]);
|
||||
});
|
||||
}
|
||||
const mimeNode = new index_js_1.default();
|
||||
const addressKeys = ['from', 'to', 'cc', 'bcc', 'sender', 'replyTo'];
|
||||
addressKeys.forEach(address => {
|
||||
let value;
|
||||
if (this.message) {
|
||||
value = [].concat(mimeNode._parseAddresses(this.message.getHeader(address === 'replyTo' ? 'reply-to' : address)) || []);
|
||||
}
|
||||
else if (this.data[address]) {
|
||||
value = [].concat(mimeNode._parseAddresses(this.data[address]) || []);
|
||||
}
|
||||
if (value && value.length) {
|
||||
this.data[address] = value;
|
||||
}
|
||||
else if (address in this.data) {
|
||||
this.data[address] = null;
|
||||
}
|
||||
});
|
||||
const singleKeys = ['from', 'sender'];
|
||||
singleKeys.forEach(address => {
|
||||
if (this.data[address]) {
|
||||
this.data[address] = this.data[address].shift();
|
||||
}
|
||||
});
|
||||
let pos = 0;
|
||||
const resolveNext = () => {
|
||||
if (pos >= keys.length) {
|
||||
return callback(null, this.data);
|
||||
}
|
||||
const args = keys[pos++];
|
||||
if (!args[0] || !args[0][args[1]]) {
|
||||
return resolveNext();
|
||||
}
|
||||
shared.resolveContent(...args, { disableFileAccess: this.data.disableFileAccess, disableUrlAccess: this.data.disableUrlAccess }, (err, value) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
const node = {
|
||||
content: value
|
||||
};
|
||||
if (args[0][args[1]] && typeof args[0][args[1]] === 'object' && !Buffer.isBuffer(args[0][args[1]])) {
|
||||
// The keys are the caller's, so copying them takes the same "__proto__"
|
||||
// rule as the constructor. `key in node` stays as the already-set test
|
||||
// here, unlike for the defaults: it also skips the Object.prototype
|
||||
// member names, and letting message data land a `toString` string on a
|
||||
// node only buys a TypeError the first time something stringifies it.
|
||||
shared.copyOwnKeys(node, args[0][args[1]], key => key in node || ['content', 'path', 'href', 'raw'].includes(key));
|
||||
}
|
||||
args[0][args[1]] = node;
|
||||
resolveNext();
|
||||
});
|
||||
};
|
||||
setImmediate(() => resolveNext());
|
||||
}
|
||||
normalize(callback) {
|
||||
const envelope = this.message.getEnvelope();
|
||||
const messageId = this.message.messageId();
|
||||
this.resolveAll((err, data) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
data.envelope = envelope;
|
||||
data.messageId = messageId;
|
||||
['html', 'text', 'watchHtml', 'amp'].forEach(key => {
|
||||
if (data[key] && data[key].content) {
|
||||
if (typeof data[key].content === 'string') {
|
||||
data[key] = data[key].content;
|
||||
}
|
||||
else if (Buffer.isBuffer(data[key].content)) {
|
||||
data[key] = data[key].content.toString();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (data.icalEvent && Buffer.isBuffer(data.icalEvent.content)) {
|
||||
data.icalEvent.content = data.icalEvent.content.toString('base64');
|
||||
data.icalEvent.encoding = 'base64';
|
||||
}
|
||||
if (data.alternatives && data.alternatives.length) {
|
||||
data.alternatives.forEach((alternative) => {
|
||||
if (alternative && alternative.content && Buffer.isBuffer(alternative.content)) {
|
||||
alternative.content = alternative.content.toString('base64');
|
||||
alternative.encoding = 'base64';
|
||||
}
|
||||
});
|
||||
}
|
||||
if (data.attachments && data.attachments.length) {
|
||||
data.attachments.forEach((attachment) => {
|
||||
if (attachment && attachment.content && Buffer.isBuffer(attachment.content)) {
|
||||
attachment.content = attachment.content.toString('base64');
|
||||
attachment.encoding = 'base64';
|
||||
}
|
||||
});
|
||||
}
|
||||
data.normalizedHeaders = {};
|
||||
Object.keys(data.headers || {}).forEach(key => {
|
||||
if (shared.isProtoKey(key)) {
|
||||
return;
|
||||
}
|
||||
let value = [].concat(data.headers[key] || []).shift();
|
||||
value = (value && value.value) || value;
|
||||
if (value) {
|
||||
if (['references', 'in-reply-to', 'message-id', 'content-id'].includes(key)) {
|
||||
value = this.message._encodeHeaderValue(key, value);
|
||||
}
|
||||
data.normalizedHeaders[key] = value;
|
||||
}
|
||||
});
|
||||
if (data.list && typeof data.list === 'object') {
|
||||
const listHeaders = this._getListHeaders(data.list);
|
||||
listHeaders.forEach(entry => {
|
||||
data.normalizedHeaders[entry.key] = entry.value.map(val => (val && val.value) || val).join(', ');
|
||||
});
|
||||
}
|
||||
if (data.references) {
|
||||
data.normalizedHeaders.references = this.message._encodeHeaderValue('references', data.references);
|
||||
}
|
||||
if (data.inReplyTo) {
|
||||
data.normalizedHeaders['in-reply-to'] = this.message._encodeHeaderValue('in-reply-to', data.inReplyTo);
|
||||
}
|
||||
return callback(null, data);
|
||||
});
|
||||
}
|
||||
setMailerHeader() {
|
||||
if (!this.message || !this.data.xMailer) {
|
||||
return;
|
||||
}
|
||||
this.message.setHeader('X-Mailer', this.data.xMailer);
|
||||
}
|
||||
setPriorityHeaders() {
|
||||
if (!this.message || !this.data.priority) {
|
||||
return;
|
||||
}
|
||||
switch ((this.data.priority || '').toString().toLowerCase()) {
|
||||
case 'high':
|
||||
this.message.setHeader('X-Priority', '1 (Highest)');
|
||||
this.message.setHeader('X-MSMail-Priority', 'High');
|
||||
this.message.setHeader('Importance', 'High');
|
||||
break;
|
||||
case 'low':
|
||||
this.message.setHeader('X-Priority', '5 (Lowest)');
|
||||
this.message.setHeader('X-MSMail-Priority', 'Low');
|
||||
this.message.setHeader('Importance', 'Low');
|
||||
break;
|
||||
default:
|
||||
// do not add anything, since all messages are 'Normal' by default
|
||||
}
|
||||
}
|
||||
setListHeaders() {
|
||||
if (!this.message || !this.data.list || typeof this.data.list !== 'object') {
|
||||
return;
|
||||
}
|
||||
// add optional List-* headers
|
||||
this._getListHeaders(this.data.list).forEach(listHeader => {
|
||||
listHeader.value.forEach(value => {
|
||||
this.message.addHeader(listHeader.key, value);
|
||||
});
|
||||
});
|
||||
}
|
||||
/** @internal */
|
||||
_getListHeaders(listData) {
|
||||
// make sure an url looks like <protocol:url>
|
||||
return Object.keys(listData).map(key => ({
|
||||
key: 'list-' + key.toLowerCase().trim(),
|
||||
value: [].concat(listData[key] || []).map(value => ({
|
||||
prepared: true,
|
||||
foldLines: true,
|
||||
value: []
|
||||
.concat(value || [])
|
||||
.map(value => {
|
||||
if (typeof value === 'string') {
|
||||
value = {
|
||||
url: value
|
||||
};
|
||||
}
|
||||
if (value && value.url) {
|
||||
// strip CR/LF so a comment can't inject extra header lines. DEL is neither
|
||||
// qtext nor ctext, so it can not be carried literally by either construct
|
||||
// and has to become an encoded word like any other non-plaintext value
|
||||
let comment = (value.comment || '').toString().replace(/\r?\n|\r/g, ' ');
|
||||
const needsEncoding = !mimeFuncs.isPlainText(comment) || /\x7f/.test(comment);
|
||||
if (key.toLowerCase().trim() === 'id') {
|
||||
// List-ID: "comment" <domain>, where an unescaped quote or a trailing
|
||||
// backslash in the comment would swallow the <domain> behind it
|
||||
comment = needsEncoding ? mimeFuncs.encodeWord(comment) : mimeFuncs.quoteString(comment);
|
||||
// List-ID expects a bare domain-like identifier, so strip the
|
||||
// scheme prefix that _formatListUrl adds or passes through
|
||||
return ((value.comment ? comment + ' ' : '') + this._formatListUrl(value.url).replace(/^<[^:]+:\/{0,2}/, '<'));
|
||||
}
|
||||
// List-*: <http://domain> (comment)
|
||||
// the ctext specials go out as quoted-pairs, otherwise a ")" closes the
|
||||
// comment early and leaves the rest as junk, an unpaired "(" opens a
|
||||
// nested comment that never closes, and a trailing backslash escapes
|
||||
// the closing ")" so the comment swallows whatever follows it
|
||||
comment = needsEncoding ? mimeFuncs.encodeWord(comment) : comment.replace(/[()\\]/g, '\\$&');
|
||||
return this._formatListUrl(value.url) + (value.comment ? ' (' + comment + ')' : '');
|
||||
}
|
||||
return '';
|
||||
})
|
||||
.filter(value => value)
|
||||
.join(', ')
|
||||
}))
|
||||
}));
|
||||
}
|
||||
/** @internal */
|
||||
_formatListUrl(url) {
|
||||
// a url has no way to carry a control char or DEL, and the angle brackets around it
|
||||
// are not a quoting construct, so anything left here lands in the header raw
|
||||
url = url.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '').replace(/[\s<]+|[\s>]+/g, '');
|
||||
if (/^(https?|mailto|ftp):/.test(url)) {
|
||||
return '<' + url + '>';
|
||||
}
|
||||
if (/^[^@]+@[^@]+$/.test(url)) {
|
||||
return '<mailto:' + url + '>';
|
||||
}
|
||||
return '<http://' + url + '>';
|
||||
}
|
||||
}
|
||||
exports.default = MailMessage;
|
||||
module.exports = exports.default;
|
||||
Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
|
||||
Reference in New Issue
Block a user