@depup/nodemailer 7.0.12-depup.0

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.
Files changed (47) hide show
  1. package/.gitattributes +6 -0
  2. package/.ncurc.js +9 -0
  3. package/.prettierignore +8 -0
  4. package/.prettierrc +12 -0
  5. package/.prettierrc.js +10 -0
  6. package/.release-please-config.json +9 -0
  7. package/CHANGELOG.md +929 -0
  8. package/CODE_OF_CONDUCT.md +76 -0
  9. package/LICENSE +16 -0
  10. package/README.md +86 -0
  11. package/SECURITY.txt +22 -0
  12. package/eslint.config.js +88 -0
  13. package/lib/addressparser/index.js +383 -0
  14. package/lib/base64/index.js +139 -0
  15. package/lib/dkim/index.js +253 -0
  16. package/lib/dkim/message-parser.js +155 -0
  17. package/lib/dkim/relaxed-body.js +154 -0
  18. package/lib/dkim/sign.js +117 -0
  19. package/lib/fetch/cookies.js +281 -0
  20. package/lib/fetch/index.js +280 -0
  21. package/lib/json-transport/index.js +82 -0
  22. package/lib/mail-composer/index.js +629 -0
  23. package/lib/mailer/index.js +441 -0
  24. package/lib/mailer/mail-message.js +316 -0
  25. package/lib/mime-funcs/index.js +625 -0
  26. package/lib/mime-funcs/mime-types.js +2113 -0
  27. package/lib/mime-node/index.js +1316 -0
  28. package/lib/mime-node/last-newline.js +33 -0
  29. package/lib/mime-node/le-unix.js +43 -0
  30. package/lib/mime-node/le-windows.js +52 -0
  31. package/lib/nodemailer.js +157 -0
  32. package/lib/punycode/index.js +460 -0
  33. package/lib/qp/index.js +227 -0
  34. package/lib/sendmail-transport/index.js +210 -0
  35. package/lib/ses-transport/index.js +234 -0
  36. package/lib/shared/index.js +754 -0
  37. package/lib/smtp-connection/data-stream.js +108 -0
  38. package/lib/smtp-connection/http-proxy-client.js +143 -0
  39. package/lib/smtp-connection/index.js +1865 -0
  40. package/lib/smtp-pool/index.js +652 -0
  41. package/lib/smtp-pool/pool-resource.js +259 -0
  42. package/lib/smtp-transport/index.js +421 -0
  43. package/lib/stream-transport/index.js +135 -0
  44. package/lib/well-known/index.js +47 -0
  45. package/lib/well-known/services.json +611 -0
  46. package/lib/xoauth2/index.js +427 -0
  47. package/package.json +47 -0
@@ -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,234 @@
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
+ const MimeNode = require('../mime-node');
8
+
9
+ /**
10
+ * Generates a Transport object for AWS SES
11
+ *
12
+ * @constructor
13
+ * @param {Object} optional config parameter
14
+ */
15
+ class SESTransport extends EventEmitter {
16
+ constructor(options) {
17
+ super();
18
+ options = options || {};
19
+
20
+ this.options = options || {};
21
+ this.ses = this.options.SES;
22
+
23
+ this.name = 'SESTransport';
24
+ this.version = packageData.version;
25
+
26
+ this.logger = shared.getLogger(this.options, {
27
+ component: this.options.component || 'ses-transport'
28
+ });
29
+ }
30
+
31
+ getRegion(cb) {
32
+ if (this.ses.sesClient.config && typeof this.ses.sesClient.config.region === 'function') {
33
+ // promise
34
+ return this.ses.sesClient.config
35
+ .region()
36
+ .then(region => cb(null, region))
37
+ .catch(err => cb(err));
38
+ }
39
+ return cb(null, false);
40
+ }
41
+
42
+ /**
43
+ * Compiles a mailcomposer message and forwards it to SES
44
+ *
45
+ * @param {Object} emailMessage MailComposer object
46
+ * @param {Function} callback Callback function to run when the sending is completed
47
+ */
48
+ send(mail, callback) {
49
+ let statObject = {
50
+ ts: Date.now(),
51
+ pending: true
52
+ };
53
+
54
+ let fromHeader = mail.message._headers.find(header => /^from$/i.test(header.key));
55
+ if (fromHeader) {
56
+ let mimeNode = new MimeNode('text/plain');
57
+ fromHeader = mimeNode._convertAddresses(mimeNode._parseAddresses(fromHeader.value));
58
+ }
59
+
60
+ let envelope = mail.data.envelope || mail.message.getEnvelope();
61
+ let messageId = mail.message.messageId();
62
+
63
+ let recipients = [].concat(envelope.to || []);
64
+ if (recipients.length > 3) {
65
+ recipients.push('...and ' + recipients.splice(2).length + ' more');
66
+ }
67
+ this.logger.info(
68
+ {
69
+ tnx: 'send',
70
+ messageId
71
+ },
72
+ 'Sending message %s to <%s>',
73
+ messageId,
74
+ recipients.join(', ')
75
+ );
76
+
77
+ let getRawMessage = next => {
78
+ // do not use Message-ID and Date in DKIM signature
79
+ if (!mail.data._dkim) {
80
+ mail.data._dkim = {};
81
+ }
82
+ if (mail.data._dkim.skipFields && typeof mail.data._dkim.skipFields === 'string') {
83
+ mail.data._dkim.skipFields += ':date:message-id';
84
+ } else {
85
+ mail.data._dkim.skipFields = 'date:message-id';
86
+ }
87
+
88
+ let sourceStream = mail.message.createReadStream();
89
+ let stream = sourceStream.pipe(new LeWindows());
90
+ let chunks = [];
91
+ let chunklen = 0;
92
+
93
+ stream.on('readable', () => {
94
+ let chunk;
95
+ while ((chunk = stream.read()) !== null) {
96
+ chunks.push(chunk);
97
+ chunklen += chunk.length;
98
+ }
99
+ });
100
+
101
+ sourceStream.once('error', err => stream.emit('error', err));
102
+
103
+ stream.once('error', err => {
104
+ next(err);
105
+ });
106
+
107
+ stream.once('end', () => next(null, Buffer.concat(chunks, chunklen)));
108
+ };
109
+
110
+ setImmediate(() =>
111
+ getRawMessage((err, raw) => {
112
+ if (err) {
113
+ this.logger.error(
114
+ {
115
+ err,
116
+ tnx: 'send',
117
+ messageId
118
+ },
119
+ 'Failed creating message for %s. %s',
120
+ messageId,
121
+ err.message
122
+ );
123
+ statObject.pending = false;
124
+ return callback(err);
125
+ }
126
+
127
+ let sesMessage = {
128
+ Content: {
129
+ Raw: {
130
+ // required
131
+ Data: raw // required
132
+ }
133
+ },
134
+ FromEmailAddress: fromHeader ? fromHeader : envelope.from,
135
+ Destination: {
136
+ ToAddresses: envelope.to
137
+ }
138
+ };
139
+
140
+ Object.keys(mail.data.ses || {}).forEach(key => {
141
+ sesMessage[key] = mail.data.ses[key];
142
+ });
143
+
144
+ this.getRegion((err, region) => {
145
+ if (err || !region) {
146
+ region = 'us-east-1';
147
+ }
148
+
149
+ const command = new this.ses.SendEmailCommand(sesMessage);
150
+ const sendPromise = this.ses.sesClient.send(command);
151
+
152
+ sendPromise
153
+ .then(data => {
154
+ if (region === 'us-east-1') {
155
+ region = 'email';
156
+ }
157
+
158
+ statObject.pending = true;
159
+ callback(null, {
160
+ envelope: {
161
+ from: envelope.from,
162
+ to: envelope.to
163
+ },
164
+ messageId: '<' + data.MessageId + (!/@/.test(data.MessageId) ? '@' + region + '.amazonses.com' : '') + '>',
165
+ response: data.MessageId,
166
+ raw
167
+ });
168
+ })
169
+ .catch(err => {
170
+ this.logger.error(
171
+ {
172
+ err,
173
+ tnx: 'send'
174
+ },
175
+ 'Send error for %s: %s',
176
+ messageId,
177
+ err.message
178
+ );
179
+ statObject.pending = false;
180
+ callback(err);
181
+ });
182
+ });
183
+ })
184
+ );
185
+ }
186
+
187
+ /**
188
+ * Verifies SES configuration
189
+ *
190
+ * @param {Function} callback Callback function
191
+ */
192
+ verify(callback) {
193
+ let promise;
194
+ if (!callback) {
195
+ promise = new Promise((resolve, reject) => {
196
+ callback = shared.callbackPromise(resolve, reject);
197
+ });
198
+ }
199
+
200
+ const cb = err => {
201
+ if (err && !['InvalidParameterValue', 'MessageRejected'].includes(err.code || err.Code || err.name)) {
202
+ return callback(err);
203
+ }
204
+ return callback(null, true);
205
+ };
206
+
207
+ const sesMessage = {
208
+ Content: {
209
+ Raw: {
210
+ Data: Buffer.from('From: <invalid@invalid>\r\nTo: <invalid@invalid>\r\n Subject: Invalid\r\n\r\nInvalid')
211
+ }
212
+ },
213
+ FromEmailAddress: 'invalid@invalid',
214
+ Destination: {
215
+ ToAddresses: ['invalid@invalid']
216
+ }
217
+ };
218
+
219
+ this.getRegion((err, region) => {
220
+ if (err || !region) {
221
+ region = 'us-east-1';
222
+ }
223
+
224
+ const command = new this.ses.SendEmailCommand(sesMessage);
225
+ const sendPromise = this.ses.sesClient.send(command);
226
+
227
+ sendPromise.then(data => cb(null, data)).catch(err => cb(err));
228
+ });
229
+
230
+ return promise;
231
+ }
232
+ }
233
+
234
+ module.exports = SESTransport;