node_modules: upgrade

This commit is contained in:
Dawid Dziurla
2025-06-14 22:45:43 +02:00
parent 3ead51e1f7
commit c2fddd52ad
28 changed files with 220 additions and 237 deletions

View File

@ -4,15 +4,11 @@ const EventEmitter = require('events');
const packageData = require('../../package.json');
const shared = require('../shared');
const LeWindows = require('../mime-node/le-windows');
const MimeNode = require('../mime-node');
/**
* Generates a Transport object for AWS SES
*
* Possible options can be the following:
*
* * **sendingRate** optional Number specifying how many messages per second should be delivered to SES
* * **maxConnections** optional Number specifying max number of parallel connections to SES
*
* @constructor
* @param {Object} optional config parameter
*/
@ -30,119 +26,17 @@ class SESTransport extends EventEmitter {
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'ses-transport'
});
// parallel sending connections
this.maxConnections = Number(this.options.maxConnections) || Infinity;
this.connections = 0;
// max messages per second
this.sendingRate = Number(this.options.sendingRate) || Infinity;
this.sendingRateTTL = null;
this.rateInterval = 1000; // milliseconds
this.rateMessages = [];
this.pending = [];
this.idling = true;
setImmediate(() => {
if (this.idling) {
this.emit('idle');
}
});
}
/**
* Schedules a sending of a message
*
* @param {Object} emailMessage MailComposer object
* @param {Function} callback Callback function to run when the sending is completed
*/
send(mail, callback) {
if (this.connections >= this.maxConnections) {
this.idling = false;
return this.pending.push({
mail,
callback
});
getRegion(cb) {
if (this.ses.sesClient.config && typeof this.ses.sesClient.config.region === 'function') {
// promise
return this.ses.sesClient.config
.region()
.then(region => cb(null, region))
.catch(err => cb(err));
}
if (!this._checkSendingRate()) {
this.idling = false;
return this.pending.push({
mail,
callback
});
}
this._send(mail, (...args) => {
setImmediate(() => callback(...args));
this._sent();
});
}
_checkRatedQueue() {
if (this.connections >= this.maxConnections || !this._checkSendingRate()) {
return;
}
if (!this.pending.length) {
if (!this.idling) {
this.idling = true;
this.emit('idle');
}
return;
}
let next = this.pending.shift();
this._send(next.mail, (...args) => {
setImmediate(() => next.callback(...args));
this._sent();
});
}
_checkSendingRate() {
clearTimeout(this.sendingRateTTL);
let now = Date.now();
let oldest = false;
// delete older messages
for (let i = this.rateMessages.length - 1; i >= 0; i--) {
if (this.rateMessages[i].ts >= now - this.rateInterval && (!oldest || this.rateMessages[i].ts < oldest)) {
oldest = this.rateMessages[i].ts;
}
if (this.rateMessages[i].ts < now - this.rateInterval && !this.rateMessages[i].pending) {
this.rateMessages.splice(i, 1);
}
}
if (this.rateMessages.length < this.sendingRate) {
return true;
}
let delay = Math.max(oldest + 1001, now + 20);
this.sendingRateTTL = setTimeout(() => this._checkRatedQueue(), now - delay);
try {
this.sendingRateTTL.unref();
} catch (E) {
// Ignore. Happens on envs with non-node timer implementation
}
return false;
}
_sent() {
this.connections--;
this._checkRatedQueue();
}
/**
* Returns true if there are free slots in the queue
*/
isIdle() {
return this.idling;
return cb(null, false);
}
/**
@ -151,13 +45,17 @@ class SESTransport extends EventEmitter {
* @param {Object} emailMessage MailComposer object
* @param {Function} callback Callback function to run when the sending is completed
*/
_send(mail, callback) {
send(mail, callback) {
let statObject = {
ts: Date.now(),
pending: true
};
this.connections++;
this.rateMessages.push(statObject);
let fromHeader = mail.message._headers.find(header => /^from$/i.test(header.key));
if (fromHeader) {
let mimeNode = new MimeNode('text/plain');
fromHeader = mimeNode._convertAddresses(mimeNode._parseAddresses(fromHeader.value));
}
let envelope = mail.data.envelope || mail.message.getEnvelope();
let messageId = mail.message.messageId();
@ -227,45 +125,29 @@ class SESTransport extends EventEmitter {
}
let sesMessage = {
RawMessage: {
// required
Data: raw // required
Content: {
Raw: {
// required
Data: raw // required
}
},
Source: envelope.from,
Destinations: envelope.to
FromEmailAddress: fromHeader ? fromHeader : envelope.from,
Destination: {
ToAddresses: envelope.to
}
};
Object.keys(mail.data.ses || {}).forEach(key => {
sesMessage[key] = mail.data.ses[key];
});
let ses = (this.ses.aws ? this.ses.ses : this.ses) || {};
let aws = this.ses.aws || {};
let getRegion = cb => {
if (ses.config && typeof ses.config.region === 'function') {
// promise
return ses.config
.region()
.then(region => cb(null, region))
.catch(err => cb(err));
}
return cb(null, (ses.config && ses.config.region) || 'us-east-1');
};
getRegion((err, region) => {
this.getRegion((err, region) => {
if (err || !region) {
region = 'us-east-1';
}
let sendPromise;
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
// v3 API
sendPromise = ses.send(new aws.SendRawEmailCommand(sesMessage));
} else {
// v2 API
sendPromise = ses.sendRawEmail(sesMessage).promise();
}
const command = new this.ses.SendEmailCommand(sesMessage);
const sendPromise = this.ses.sesClient.send(command);
sendPromise
.then(data => {
@ -273,7 +155,7 @@ class SESTransport extends EventEmitter {
region = 'email';
}
statObject.pending = false;
statObject.pending = true;
callback(null, {
envelope: {
from: envelope.from,
@ -309,38 +191,41 @@ class SESTransport extends EventEmitter {
*/
verify(callback) {
let promise;
let ses = (this.ses.aws ? this.ses.ses : this.ses) || {};
let aws = this.ses.aws || {};
const sesMessage = {
RawMessage: {
// required
Data: 'From: invalid@invalid\r\nTo: invalid@invalid\r\n Subject: Invalid\r\n\r\nInvalid'
},
Source: 'invalid@invalid',
Destinations: ['invalid@invalid']
};
if (!callback) {
promise = new Promise((resolve, reject) => {
callback = shared.callbackPromise(resolve, reject);
});
}
const cb = err => {
if (err && (err.code || err.Code) !== 'InvalidParameterValue') {
if (err && !['InvalidParameterValue', 'MessageRejected'].includes(err.code || err.Code || err.name)) {
return callback(err);
}
return callback(null, true);
};
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
// v3 API
sesMessage.RawMessage.Data = Buffer.from(sesMessage.RawMessage.Data);
ses.send(new aws.SendRawEmailCommand(sesMessage), cb);
} else {
// v2 API
ses.sendRawEmail(sesMessage, cb);
}
const sesMessage = {
Content: {
Raw: {
Data: Buffer.from('From: <invalid@invalid>\r\nTo: <invalid@invalid>\r\n Subject: Invalid\r\n\r\nInvalid')
}
},
FromEmailAddress: 'invalid@invalid',
Destination: {
ToAddresses: ['invalid@invalid']
}
};
this.getRegion((err, region) => {
if (err || !region) {
region = 'us-east-1';
}
const command = new this.ses.SendEmailCommand(sesMessage);
const sendPromise = this.ses.sesClient.send(command);
sendPromise.then(data => cb(null, data)).catch(err => cb(err));
});
return promise;
}