@nocobase/plugin-workflow-mailer 1.3.0-alpha.20240710084543 → 1.3.0-alpha.20240710155619
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/MailerInstruction.d.ts +352 -0
- package/dist/client/index.d.ts +14 -0
- package/dist/client/index.js +16 -0
- package/dist/externalVersion.js +16 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +48 -0
- package/dist/locale/en-US.json +19 -0
- package/dist/locale/index.d.ts +11 -0
- package/dist/locale/index.js +48 -0
- package/dist/locale/zh-CN.json +19 -0
- package/dist/node_modules/nodemailer/.gitattributes +6 -0
- package/dist/node_modules/nodemailer/.ncurc.js +7 -0
- package/dist/node_modules/nodemailer/.prettierrc.js +8 -0
- package/dist/node_modules/nodemailer/LICENSE +16 -0
- package/dist/node_modules/nodemailer/SECURITY.txt +22 -0
- package/dist/node_modules/nodemailer/lib/addressparser/index.js +313 -0
- package/dist/node_modules/nodemailer/lib/base64/index.js +142 -0
- package/dist/node_modules/nodemailer/lib/dkim/index.js +251 -0
- package/dist/node_modules/nodemailer/lib/dkim/message-parser.js +155 -0
- package/dist/node_modules/nodemailer/lib/dkim/relaxed-body.js +154 -0
- package/dist/node_modules/nodemailer/lib/dkim/sign.js +117 -0
- package/dist/node_modules/nodemailer/lib/fetch/cookies.js +281 -0
- package/dist/node_modules/nodemailer/lib/fetch/index.js +274 -0
- package/dist/node_modules/nodemailer/lib/json-transport/index.js +82 -0
- package/dist/node_modules/nodemailer/lib/mail-composer/index.js +565 -0
- package/dist/node_modules/nodemailer/lib/mailer/index.js +429 -0
- package/dist/node_modules/nodemailer/lib/mailer/mail-message.js +315 -0
- package/dist/node_modules/nodemailer/lib/mime-funcs/index.js +625 -0
- package/dist/node_modules/nodemailer/lib/mime-funcs/mime-types.js +2102 -0
- package/dist/node_modules/nodemailer/lib/mime-node/index.js +1314 -0
- package/dist/node_modules/nodemailer/lib/mime-node/last-newline.js +33 -0
- package/dist/node_modules/nodemailer/lib/mime-node/le-unix.js +43 -0
- package/dist/node_modules/nodemailer/lib/mime-node/le-windows.js +52 -0
- package/dist/node_modules/nodemailer/lib/nodemailer.js +1 -0
- package/dist/node_modules/nodemailer/lib/punycode/index.js +460 -0
- package/dist/node_modules/nodemailer/lib/qp/index.js +219 -0
- package/dist/node_modules/nodemailer/lib/sendmail-transport/index.js +210 -0
- package/dist/node_modules/nodemailer/lib/ses-transport/index.js +349 -0
- package/dist/node_modules/nodemailer/lib/shared/index.js +688 -0
- package/dist/node_modules/nodemailer/lib/smtp-connection/data-stream.js +108 -0
- package/dist/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +143 -0
- package/dist/node_modules/nodemailer/lib/smtp-connection/index.js +1825 -0
- package/dist/node_modules/nodemailer/lib/smtp-pool/index.js +648 -0
- package/dist/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +253 -0
- package/dist/node_modules/nodemailer/lib/smtp-transport/index.js +416 -0
- package/dist/node_modules/nodemailer/lib/stream-transport/index.js +135 -0
- package/dist/node_modules/nodemailer/lib/well-known/index.js +47 -0
- package/dist/node_modules/nodemailer/lib/well-known/services.json +343 -0
- package/dist/node_modules/nodemailer/lib/xoauth2/index.js +376 -0
- package/dist/node_modules/nodemailer/package.json +1 -0
- package/dist/server/MailerInstruction.d.ts +13 -0
- package/dist/server/MailerInstruction.js +119 -0
- package/dist/server/Plugin.d.ts +12 -0
- package/dist/server/Plugin.js +50 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +42 -0
- package/package.json +2 -2
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const spawn = require('child_process').spawn;
|
|
4
|
+
const packageData = require('../../package.json');
|
|
5
|
+
const shared = require('../shared');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generates a Transport object for Sendmail
|
|
9
|
+
*
|
|
10
|
+
* Possible options can be the following:
|
|
11
|
+
*
|
|
12
|
+
* * **path** optional path to sendmail binary
|
|
13
|
+
* * **newline** either 'windows' or 'unix'
|
|
14
|
+
* * **args** an array of arguments for the sendmail binary
|
|
15
|
+
*
|
|
16
|
+
* @constructor
|
|
17
|
+
* @param {Object} optional config parameter for Sendmail
|
|
18
|
+
*/
|
|
19
|
+
class SendmailTransport {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
options = options || {};
|
|
22
|
+
|
|
23
|
+
// use a reference to spawn for mocking purposes
|
|
24
|
+
this._spawn = spawn;
|
|
25
|
+
|
|
26
|
+
this.options = options || {};
|
|
27
|
+
|
|
28
|
+
this.name = 'Sendmail';
|
|
29
|
+
this.version = packageData.version;
|
|
30
|
+
|
|
31
|
+
this.path = 'sendmail';
|
|
32
|
+
this.args = false;
|
|
33
|
+
this.winbreak = false;
|
|
34
|
+
|
|
35
|
+
this.logger = shared.getLogger(this.options, {
|
|
36
|
+
component: this.options.component || 'sendmail'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (options) {
|
|
40
|
+
if (typeof options === 'string') {
|
|
41
|
+
this.path = options;
|
|
42
|
+
} else if (typeof options === 'object') {
|
|
43
|
+
if (options.path) {
|
|
44
|
+
this.path = options.path;
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(options.args)) {
|
|
47
|
+
this.args = options.args;
|
|
48
|
+
}
|
|
49
|
+
this.winbreak = ['win', 'windows', 'dos', '\r\n'].includes((options.newline || '').toString().toLowerCase());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* <p>Compiles a mailcomposer message and forwards it to handler that sends it.</p>
|
|
56
|
+
*
|
|
57
|
+
* @param {Object} emailMessage MailComposer object
|
|
58
|
+
* @param {Function} callback Callback function to run when the sending is completed
|
|
59
|
+
*/
|
|
60
|
+
send(mail, done) {
|
|
61
|
+
// Sendmail strips this header line by itself
|
|
62
|
+
mail.message.keepBcc = true;
|
|
63
|
+
|
|
64
|
+
let envelope = mail.data.envelope || mail.message.getEnvelope();
|
|
65
|
+
let messageId = mail.message.messageId();
|
|
66
|
+
let args;
|
|
67
|
+
let sendmail;
|
|
68
|
+
let returned;
|
|
69
|
+
|
|
70
|
+
const hasInvalidAddresses = []
|
|
71
|
+
.concat(envelope.from || [])
|
|
72
|
+
.concat(envelope.to || [])
|
|
73
|
+
.some(addr => /^-/.test(addr));
|
|
74
|
+
if (hasInvalidAddresses) {
|
|
75
|
+
return done(new Error('Can not send mail. Invalid envelope addresses.'));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (this.args) {
|
|
79
|
+
// force -i to keep single dots
|
|
80
|
+
args = ['-i'].concat(this.args).concat(envelope.to);
|
|
81
|
+
} else {
|
|
82
|
+
args = ['-i'].concat(envelope.from ? ['-f', envelope.from] : []).concat(envelope.to);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let callback = err => {
|
|
86
|
+
if (returned) {
|
|
87
|
+
// ignore any additional responses, already done
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
returned = true;
|
|
91
|
+
if (typeof done === 'function') {
|
|
92
|
+
if (err) {
|
|
93
|
+
return done(err);
|
|
94
|
+
} else {
|
|
95
|
+
return done(null, {
|
|
96
|
+
envelope: mail.data.envelope || mail.message.getEnvelope(),
|
|
97
|
+
messageId,
|
|
98
|
+
response: 'Messages queued for delivery'
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
sendmail = this._spawn(this.path, args);
|
|
106
|
+
} catch (E) {
|
|
107
|
+
this.logger.error(
|
|
108
|
+
{
|
|
109
|
+
err: E,
|
|
110
|
+
tnx: 'spawn',
|
|
111
|
+
messageId
|
|
112
|
+
},
|
|
113
|
+
'Error occurred while spawning sendmail. %s',
|
|
114
|
+
E.message
|
|
115
|
+
);
|
|
116
|
+
return callback(E);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (sendmail) {
|
|
120
|
+
sendmail.on('error', err => {
|
|
121
|
+
this.logger.error(
|
|
122
|
+
{
|
|
123
|
+
err,
|
|
124
|
+
tnx: 'spawn',
|
|
125
|
+
messageId
|
|
126
|
+
},
|
|
127
|
+
'Error occurred when sending message %s. %s',
|
|
128
|
+
messageId,
|
|
129
|
+
err.message
|
|
130
|
+
);
|
|
131
|
+
callback(err);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
sendmail.once('exit', code => {
|
|
135
|
+
if (!code) {
|
|
136
|
+
return callback();
|
|
137
|
+
}
|
|
138
|
+
let err;
|
|
139
|
+
if (code === 127) {
|
|
140
|
+
err = new Error('Sendmail command not found, process exited with code ' + code);
|
|
141
|
+
} else {
|
|
142
|
+
err = new Error('Sendmail exited with code ' + code);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.logger.error(
|
|
146
|
+
{
|
|
147
|
+
err,
|
|
148
|
+
tnx: 'stdin',
|
|
149
|
+
messageId
|
|
150
|
+
},
|
|
151
|
+
'Error sending message %s to sendmail. %s',
|
|
152
|
+
messageId,
|
|
153
|
+
err.message
|
|
154
|
+
);
|
|
155
|
+
callback(err);
|
|
156
|
+
});
|
|
157
|
+
sendmail.once('close', callback);
|
|
158
|
+
|
|
159
|
+
sendmail.stdin.on('error', err => {
|
|
160
|
+
this.logger.error(
|
|
161
|
+
{
|
|
162
|
+
err,
|
|
163
|
+
tnx: 'stdin',
|
|
164
|
+
messageId
|
|
165
|
+
},
|
|
166
|
+
'Error occurred when piping message %s to sendmail. %s',
|
|
167
|
+
messageId,
|
|
168
|
+
err.message
|
|
169
|
+
);
|
|
170
|
+
callback(err);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
let recipients = [].concat(envelope.to || []);
|
|
174
|
+
if (recipients.length > 3) {
|
|
175
|
+
recipients.push('...and ' + recipients.splice(2).length + ' more');
|
|
176
|
+
}
|
|
177
|
+
this.logger.info(
|
|
178
|
+
{
|
|
179
|
+
tnx: 'send',
|
|
180
|
+
messageId
|
|
181
|
+
},
|
|
182
|
+
'Sending message %s to <%s>',
|
|
183
|
+
messageId,
|
|
184
|
+
recipients.join(', ')
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
let sourceStream = mail.message.createReadStream();
|
|
188
|
+
sourceStream.once('error', err => {
|
|
189
|
+
this.logger.error(
|
|
190
|
+
{
|
|
191
|
+
err,
|
|
192
|
+
tnx: 'stdin',
|
|
193
|
+
messageId
|
|
194
|
+
},
|
|
195
|
+
'Error occurred when generating message %s. %s',
|
|
196
|
+
messageId,
|
|
197
|
+
err.message
|
|
198
|
+
);
|
|
199
|
+
sendmail.kill('SIGINT'); // do not deliver the message
|
|
200
|
+
callback(err);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
sourceStream.pipe(sendmail.stdin);
|
|
204
|
+
} else {
|
|
205
|
+
return callback(new Error('sendmail was not found'));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports = SendmailTransport;
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const EventEmitter = require('events');
|
|
4
|
+
const packageData = require('../../package.json');
|
|
5
|
+
const shared = require('../shared');
|
|
6
|
+
const LeWindows = require('../mime-node/le-windows');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generates a Transport object for AWS SES
|
|
10
|
+
*
|
|
11
|
+
* Possible options can be the following:
|
|
12
|
+
*
|
|
13
|
+
* * **sendingRate** optional Number specifying how many messages per second should be delivered to SES
|
|
14
|
+
* * **maxConnections** optional Number specifying max number of parallel connections to SES
|
|
15
|
+
*
|
|
16
|
+
* @constructor
|
|
17
|
+
* @param {Object} optional config parameter
|
|
18
|
+
*/
|
|
19
|
+
class SESTransport extends EventEmitter {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super();
|
|
22
|
+
options = options || {};
|
|
23
|
+
|
|
24
|
+
this.options = options || {};
|
|
25
|
+
this.ses = this.options.SES;
|
|
26
|
+
|
|
27
|
+
this.name = 'SESTransport';
|
|
28
|
+
this.version = packageData.version;
|
|
29
|
+
|
|
30
|
+
this.logger = shared.getLogger(this.options, {
|
|
31
|
+
component: this.options.component || 'ses-transport'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// parallel sending connections
|
|
35
|
+
this.maxConnections = Number(this.options.maxConnections) || Infinity;
|
|
36
|
+
this.connections = 0;
|
|
37
|
+
|
|
38
|
+
// max messages per second
|
|
39
|
+
this.sendingRate = Number(this.options.sendingRate) || Infinity;
|
|
40
|
+
this.sendingRateTTL = null;
|
|
41
|
+
this.rateInterval = 1000; // milliseconds
|
|
42
|
+
this.rateMessages = [];
|
|
43
|
+
|
|
44
|
+
this.pending = [];
|
|
45
|
+
|
|
46
|
+
this.idling = true;
|
|
47
|
+
|
|
48
|
+
setImmediate(() => {
|
|
49
|
+
if (this.idling) {
|
|
50
|
+
this.emit('idle');
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Schedules a sending of a message
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} emailMessage MailComposer object
|
|
59
|
+
* @param {Function} callback Callback function to run when the sending is completed
|
|
60
|
+
*/
|
|
61
|
+
send(mail, callback) {
|
|
62
|
+
if (this.connections >= this.maxConnections) {
|
|
63
|
+
this.idling = false;
|
|
64
|
+
return this.pending.push({
|
|
65
|
+
mail,
|
|
66
|
+
callback
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!this._checkSendingRate()) {
|
|
71
|
+
this.idling = false;
|
|
72
|
+
return this.pending.push({
|
|
73
|
+
mail,
|
|
74
|
+
callback
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this._send(mail, (...args) => {
|
|
79
|
+
setImmediate(() => callback(...args));
|
|
80
|
+
this._sent();
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_checkRatedQueue() {
|
|
85
|
+
if (this.connections >= this.maxConnections || !this._checkSendingRate()) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!this.pending.length) {
|
|
90
|
+
if (!this.idling) {
|
|
91
|
+
this.idling = true;
|
|
92
|
+
this.emit('idle');
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let next = this.pending.shift();
|
|
98
|
+
this._send(next.mail, (...args) => {
|
|
99
|
+
setImmediate(() => next.callback(...args));
|
|
100
|
+
this._sent();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_checkSendingRate() {
|
|
105
|
+
clearTimeout(this.sendingRateTTL);
|
|
106
|
+
|
|
107
|
+
let now = Date.now();
|
|
108
|
+
let oldest = false;
|
|
109
|
+
// delete older messages
|
|
110
|
+
for (let i = this.rateMessages.length - 1; i >= 0; i--) {
|
|
111
|
+
if (this.rateMessages[i].ts >= now - this.rateInterval && (!oldest || this.rateMessages[i].ts < oldest)) {
|
|
112
|
+
oldest = this.rateMessages[i].ts;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (this.rateMessages[i].ts < now - this.rateInterval && !this.rateMessages[i].pending) {
|
|
116
|
+
this.rateMessages.splice(i, 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (this.rateMessages.length < this.sendingRate) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let delay = Math.max(oldest + 1001, now + 20);
|
|
125
|
+
this.sendingRateTTL = setTimeout(() => this._checkRatedQueue(), now - delay);
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
this.sendingRateTTL.unref();
|
|
129
|
+
} catch (E) {
|
|
130
|
+
// Ignore. Happens on envs with non-node timer implementation
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
_sent() {
|
|
137
|
+
this.connections--;
|
|
138
|
+
this._checkRatedQueue();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Returns true if there are free slots in the queue
|
|
143
|
+
*/
|
|
144
|
+
isIdle() {
|
|
145
|
+
return this.idling;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Compiles a mailcomposer message and forwards it to SES
|
|
150
|
+
*
|
|
151
|
+
* @param {Object} emailMessage MailComposer object
|
|
152
|
+
* @param {Function} callback Callback function to run when the sending is completed
|
|
153
|
+
*/
|
|
154
|
+
_send(mail, callback) {
|
|
155
|
+
let statObject = {
|
|
156
|
+
ts: Date.now(),
|
|
157
|
+
pending: true
|
|
158
|
+
};
|
|
159
|
+
this.connections++;
|
|
160
|
+
this.rateMessages.push(statObject);
|
|
161
|
+
|
|
162
|
+
let envelope = mail.data.envelope || mail.message.getEnvelope();
|
|
163
|
+
let messageId = mail.message.messageId();
|
|
164
|
+
|
|
165
|
+
let recipients = [].concat(envelope.to || []);
|
|
166
|
+
if (recipients.length > 3) {
|
|
167
|
+
recipients.push('...and ' + recipients.splice(2).length + ' more');
|
|
168
|
+
}
|
|
169
|
+
this.logger.info(
|
|
170
|
+
{
|
|
171
|
+
tnx: 'send',
|
|
172
|
+
messageId
|
|
173
|
+
},
|
|
174
|
+
'Sending message %s to <%s>',
|
|
175
|
+
messageId,
|
|
176
|
+
recipients.join(', ')
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
let getRawMessage = next => {
|
|
180
|
+
// do not use Message-ID and Date in DKIM signature
|
|
181
|
+
if (!mail.data._dkim) {
|
|
182
|
+
mail.data._dkim = {};
|
|
183
|
+
}
|
|
184
|
+
if (mail.data._dkim.skipFields && typeof mail.data._dkim.skipFields === 'string') {
|
|
185
|
+
mail.data._dkim.skipFields += ':date:message-id';
|
|
186
|
+
} else {
|
|
187
|
+
mail.data._dkim.skipFields = 'date:message-id';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let sourceStream = mail.message.createReadStream();
|
|
191
|
+
let stream = sourceStream.pipe(new LeWindows());
|
|
192
|
+
let chunks = [];
|
|
193
|
+
let chunklen = 0;
|
|
194
|
+
|
|
195
|
+
stream.on('readable', () => {
|
|
196
|
+
let chunk;
|
|
197
|
+
while ((chunk = stream.read()) !== null) {
|
|
198
|
+
chunks.push(chunk);
|
|
199
|
+
chunklen += chunk.length;
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
sourceStream.once('error', err => stream.emit('error', err));
|
|
204
|
+
|
|
205
|
+
stream.once('error', err => {
|
|
206
|
+
next(err);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
stream.once('end', () => next(null, Buffer.concat(chunks, chunklen)));
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
setImmediate(() =>
|
|
213
|
+
getRawMessage((err, raw) => {
|
|
214
|
+
if (err) {
|
|
215
|
+
this.logger.error(
|
|
216
|
+
{
|
|
217
|
+
err,
|
|
218
|
+
tnx: 'send',
|
|
219
|
+
messageId
|
|
220
|
+
},
|
|
221
|
+
'Failed creating message for %s. %s',
|
|
222
|
+
messageId,
|
|
223
|
+
err.message
|
|
224
|
+
);
|
|
225
|
+
statObject.pending = false;
|
|
226
|
+
return callback(err);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let sesMessage = {
|
|
230
|
+
RawMessage: {
|
|
231
|
+
// required
|
|
232
|
+
Data: raw // required
|
|
233
|
+
},
|
|
234
|
+
Source: envelope.from,
|
|
235
|
+
Destinations: envelope.to
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
Object.keys(mail.data.ses || {}).forEach(key => {
|
|
239
|
+
sesMessage[key] = mail.data.ses[key];
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
let ses = (this.ses.aws ? this.ses.ses : this.ses) || {};
|
|
243
|
+
let aws = this.ses.aws || {};
|
|
244
|
+
|
|
245
|
+
let getRegion = cb => {
|
|
246
|
+
if (ses.config && typeof ses.config.region === 'function') {
|
|
247
|
+
// promise
|
|
248
|
+
return ses.config
|
|
249
|
+
.region()
|
|
250
|
+
.then(region => cb(null, region))
|
|
251
|
+
.catch(err => cb(err));
|
|
252
|
+
}
|
|
253
|
+
return cb(null, (ses.config && ses.config.region) || 'us-east-1');
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
getRegion((err, region) => {
|
|
257
|
+
if (err || !region) {
|
|
258
|
+
region = 'us-east-1';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let sendPromise;
|
|
262
|
+
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
|
|
263
|
+
// v3 API
|
|
264
|
+
sendPromise = ses.send(new aws.SendRawEmailCommand(sesMessage));
|
|
265
|
+
} else {
|
|
266
|
+
// v2 API
|
|
267
|
+
sendPromise = ses.sendRawEmail(sesMessage).promise();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
sendPromise
|
|
271
|
+
.then(data => {
|
|
272
|
+
if (region === 'us-east-1') {
|
|
273
|
+
region = 'email';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
statObject.pending = false;
|
|
277
|
+
callback(null, {
|
|
278
|
+
envelope: {
|
|
279
|
+
from: envelope.from,
|
|
280
|
+
to: envelope.to
|
|
281
|
+
},
|
|
282
|
+
messageId: '<' + data.MessageId + (!/@/.test(data.MessageId) ? '@' + region + '.amazonses.com' : '') + '>',
|
|
283
|
+
response: data.MessageId,
|
|
284
|
+
raw
|
|
285
|
+
});
|
|
286
|
+
})
|
|
287
|
+
.catch(err => {
|
|
288
|
+
this.logger.error(
|
|
289
|
+
{
|
|
290
|
+
err,
|
|
291
|
+
tnx: 'send'
|
|
292
|
+
},
|
|
293
|
+
'Send error for %s: %s',
|
|
294
|
+
messageId,
|
|
295
|
+
err.message
|
|
296
|
+
);
|
|
297
|
+
statObject.pending = false;
|
|
298
|
+
callback(err);
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
})
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Verifies SES configuration
|
|
307
|
+
*
|
|
308
|
+
* @param {Function} callback Callback function
|
|
309
|
+
*/
|
|
310
|
+
verify(callback) {
|
|
311
|
+
let promise;
|
|
312
|
+
let ses = (this.ses.aws ? this.ses.ses : this.ses) || {};
|
|
313
|
+
let aws = this.ses.aws || {};
|
|
314
|
+
|
|
315
|
+
const sesMessage = {
|
|
316
|
+
RawMessage: {
|
|
317
|
+
// required
|
|
318
|
+
Data: 'From: invalid@invalid\r\nTo: invalid@invalid\r\n Subject: Invalid\r\n\r\nInvalid'
|
|
319
|
+
},
|
|
320
|
+
Source: 'invalid@invalid',
|
|
321
|
+
Destinations: ['invalid@invalid']
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
if (!callback) {
|
|
325
|
+
promise = new Promise((resolve, reject) => {
|
|
326
|
+
callback = shared.callbackPromise(resolve, reject);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
const cb = err => {
|
|
330
|
+
if (err && (err.code || err.Code) !== 'InvalidParameterValue') {
|
|
331
|
+
return callback(err);
|
|
332
|
+
}
|
|
333
|
+
return callback(null, true);
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
if (typeof ses.send === 'function' && aws.SendRawEmailCommand) {
|
|
337
|
+
// v3 API
|
|
338
|
+
sesMessage.RawMessage.Data = Buffer.from(sesMessage.RawMessage.Data);
|
|
339
|
+
ses.send(new aws.SendRawEmailCommand(sesMessage), cb);
|
|
340
|
+
} else {
|
|
341
|
+
// v2 API
|
|
342
|
+
ses.sendRawEmail(sesMessage, cb);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return promise;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
module.exports = SESTransport;
|