@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.
- package/.gitattributes +6 -0
- package/.ncurc.js +9 -0
- package/.prettierignore +8 -0
- package/.prettierrc +12 -0
- package/.prettierrc.js +10 -0
- package/.release-please-config.json +9 -0
- package/CHANGELOG.md +929 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/LICENSE +16 -0
- package/README.md +86 -0
- package/SECURITY.txt +22 -0
- package/eslint.config.js +88 -0
- package/lib/addressparser/index.js +383 -0
- package/lib/base64/index.js +139 -0
- package/lib/dkim/index.js +253 -0
- package/lib/dkim/message-parser.js +155 -0
- package/lib/dkim/relaxed-body.js +154 -0
- package/lib/dkim/sign.js +117 -0
- package/lib/fetch/cookies.js +281 -0
- package/lib/fetch/index.js +280 -0
- package/lib/json-transport/index.js +82 -0
- package/lib/mail-composer/index.js +629 -0
- package/lib/mailer/index.js +441 -0
- package/lib/mailer/mail-message.js +316 -0
- package/lib/mime-funcs/index.js +625 -0
- package/lib/mime-funcs/mime-types.js +2113 -0
- package/lib/mime-node/index.js +1316 -0
- package/lib/mime-node/last-newline.js +33 -0
- package/lib/mime-node/le-unix.js +43 -0
- package/lib/mime-node/le-windows.js +52 -0
- package/lib/nodemailer.js +157 -0
- package/lib/punycode/index.js +460 -0
- package/lib/qp/index.js +227 -0
- package/lib/sendmail-transport/index.js +210 -0
- package/lib/ses-transport/index.js +234 -0
- package/lib/shared/index.js +754 -0
- package/lib/smtp-connection/data-stream.js +108 -0
- package/lib/smtp-connection/http-proxy-client.js +143 -0
- package/lib/smtp-connection/index.js +1865 -0
- package/lib/smtp-pool/index.js +652 -0
- package/lib/smtp-pool/pool-resource.js +259 -0
- package/lib/smtp-transport/index.js +421 -0
- package/lib/stream-transport/index.js +135 -0
- package/lib/well-known/index.js +47 -0
- package/lib/well-known/services.json +611 -0
- package/lib/xoauth2/index.js +427 -0
- package/package.json +47 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Transform = require('stream').Transform;
|
|
4
|
+
|
|
5
|
+
class LastNewline extends Transform {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.lastByte = false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_transform(chunk, encoding, done) {
|
|
12
|
+
if (chunk.length) {
|
|
13
|
+
this.lastByte = chunk[chunk.length - 1];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.push(chunk);
|
|
17
|
+
done();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
_flush(done) {
|
|
21
|
+
if (this.lastByte === 0x0a) {
|
|
22
|
+
return done();
|
|
23
|
+
}
|
|
24
|
+
if (this.lastByte === 0x0d) {
|
|
25
|
+
this.push(Buffer.from('\n'));
|
|
26
|
+
return done();
|
|
27
|
+
}
|
|
28
|
+
this.push(Buffer.from('\r\n'));
|
|
29
|
+
return done();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = LastNewline;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const stream = require('stream');
|
|
4
|
+
const Transform = stream.Transform;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ensures that only <LF> is used for linebreaks
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} options Stream options
|
|
10
|
+
*/
|
|
11
|
+
class LeWindows extends Transform {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super(options);
|
|
14
|
+
// init Transform
|
|
15
|
+
this.options = options || {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Escapes dots
|
|
20
|
+
*/
|
|
21
|
+
_transform(chunk, encoding, done) {
|
|
22
|
+
let buf;
|
|
23
|
+
let lastPos = 0;
|
|
24
|
+
|
|
25
|
+
for (let i = 0, len = chunk.length; i < len; i++) {
|
|
26
|
+
if (chunk[i] === 0x0d) {
|
|
27
|
+
// \n
|
|
28
|
+
buf = chunk.slice(lastPos, i);
|
|
29
|
+
lastPos = i + 1;
|
|
30
|
+
this.push(buf);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (lastPos && lastPos < chunk.length) {
|
|
34
|
+
buf = chunk.slice(lastPos);
|
|
35
|
+
this.push(buf);
|
|
36
|
+
} else if (!lastPos) {
|
|
37
|
+
this.push(chunk);
|
|
38
|
+
}
|
|
39
|
+
done();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = LeWindows;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const stream = require('stream');
|
|
4
|
+
const Transform = stream.Transform;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ensures that only <CR><LF> sequences are used for linebreaks
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} options Stream options
|
|
10
|
+
*/
|
|
11
|
+
class LeWindows extends Transform {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super(options);
|
|
14
|
+
// init Transform
|
|
15
|
+
this.options = options || {};
|
|
16
|
+
this.lastByte = false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Escapes dots
|
|
21
|
+
*/
|
|
22
|
+
_transform(chunk, encoding, done) {
|
|
23
|
+
let buf;
|
|
24
|
+
let lastPos = 0;
|
|
25
|
+
|
|
26
|
+
for (let i = 0, len = chunk.length; i < len; i++) {
|
|
27
|
+
if (chunk[i] === 0x0a) {
|
|
28
|
+
// \n
|
|
29
|
+
if ((i && chunk[i - 1] !== 0x0d) || (!i && this.lastByte !== 0x0d)) {
|
|
30
|
+
if (i > lastPos) {
|
|
31
|
+
buf = chunk.slice(lastPos, i);
|
|
32
|
+
this.push(buf);
|
|
33
|
+
}
|
|
34
|
+
this.push(Buffer.from('\r\n'));
|
|
35
|
+
lastPos = i + 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (lastPos && lastPos < chunk.length) {
|
|
41
|
+
buf = chunk.slice(lastPos);
|
|
42
|
+
this.push(buf);
|
|
43
|
+
} else if (!lastPos) {
|
|
44
|
+
this.push(chunk);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.lastByte = chunk[chunk.length - 1];
|
|
48
|
+
done();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = LeWindows;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Mailer = require('./mailer');
|
|
4
|
+
const shared = require('./shared');
|
|
5
|
+
const SMTPPool = require('./smtp-pool');
|
|
6
|
+
const SMTPTransport = require('./smtp-transport');
|
|
7
|
+
const SendmailTransport = require('./sendmail-transport');
|
|
8
|
+
const StreamTransport = require('./stream-transport');
|
|
9
|
+
const JSONTransport = require('./json-transport');
|
|
10
|
+
const SESTransport = require('./ses-transport');
|
|
11
|
+
const nmfetch = require('./fetch');
|
|
12
|
+
const packageData = require('../package.json');
|
|
13
|
+
|
|
14
|
+
const ETHEREAL_API = (process.env.ETHEREAL_API || 'https://api.nodemailer.com').replace(/\/+$/, '');
|
|
15
|
+
const ETHEREAL_WEB = (process.env.ETHEREAL_WEB || 'https://ethereal.email').replace(/\/+$/, '');
|
|
16
|
+
const ETHEREAL_API_KEY = (process.env.ETHEREAL_API_KEY || '').replace(/\s*/g, '') || null;
|
|
17
|
+
const ETHEREAL_CACHE = ['true', 'yes', 'y', '1'].includes((process.env.ETHEREAL_CACHE || 'yes').toString().trim().toLowerCase());
|
|
18
|
+
|
|
19
|
+
let testAccount = false;
|
|
20
|
+
|
|
21
|
+
module.exports.createTransport = function (transporter, defaults) {
|
|
22
|
+
let urlConfig;
|
|
23
|
+
let options;
|
|
24
|
+
let mailer;
|
|
25
|
+
|
|
26
|
+
if (
|
|
27
|
+
// provided transporter is a configuration object, not transporter plugin
|
|
28
|
+
(typeof transporter === 'object' && typeof transporter.send !== 'function') ||
|
|
29
|
+
// provided transporter looks like a connection url
|
|
30
|
+
(typeof transporter === 'string' && /^(smtps?|direct):/i.test(transporter))
|
|
31
|
+
) {
|
|
32
|
+
if ((urlConfig = typeof transporter === 'string' ? transporter : transporter.url)) {
|
|
33
|
+
// parse a configuration URL into configuration options
|
|
34
|
+
options = shared.parseConnectionUrl(urlConfig);
|
|
35
|
+
} else {
|
|
36
|
+
options = transporter;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (options.pool) {
|
|
40
|
+
transporter = new SMTPPool(options);
|
|
41
|
+
} else if (options.sendmail) {
|
|
42
|
+
transporter = new SendmailTransport(options);
|
|
43
|
+
} else if (options.streamTransport) {
|
|
44
|
+
transporter = new StreamTransport(options);
|
|
45
|
+
} else if (options.jsonTransport) {
|
|
46
|
+
transporter = new JSONTransport(options);
|
|
47
|
+
} else if (options.SES) {
|
|
48
|
+
if (options.SES.ses && options.SES.aws) {
|
|
49
|
+
let error = new Error(
|
|
50
|
+
'Using legacy SES configuration, expecting @aws-sdk/client-sesv2, see https://nodemailer.com/transports/ses/'
|
|
51
|
+
);
|
|
52
|
+
error.code = 'LegacyConfig';
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
transporter = new SESTransport(options);
|
|
56
|
+
} else {
|
|
57
|
+
transporter = new SMTPTransport(options);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
mailer = new Mailer(transporter, options, defaults);
|
|
62
|
+
|
|
63
|
+
return mailer;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
module.exports.createTestAccount = function (apiUrl, callback) {
|
|
67
|
+
let promise;
|
|
68
|
+
|
|
69
|
+
if (!callback && typeof apiUrl === 'function') {
|
|
70
|
+
callback = apiUrl;
|
|
71
|
+
apiUrl = false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!callback) {
|
|
75
|
+
promise = new Promise((resolve, reject) => {
|
|
76
|
+
callback = shared.callbackPromise(resolve, reject);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (ETHEREAL_CACHE && testAccount) {
|
|
81
|
+
setImmediate(() => callback(null, testAccount));
|
|
82
|
+
return promise;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
apiUrl = apiUrl || ETHEREAL_API;
|
|
86
|
+
|
|
87
|
+
let chunks = [];
|
|
88
|
+
let chunklen = 0;
|
|
89
|
+
|
|
90
|
+
let requestHeaders = {};
|
|
91
|
+
let requestBody = {
|
|
92
|
+
requestor: packageData.name,
|
|
93
|
+
version: packageData.version
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
if (ETHEREAL_API_KEY) {
|
|
97
|
+
requestHeaders.Authorization = 'Bearer ' + ETHEREAL_API_KEY;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let req = nmfetch(apiUrl + '/user', {
|
|
101
|
+
contentType: 'application/json',
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers: requestHeaders,
|
|
104
|
+
body: Buffer.from(JSON.stringify(requestBody))
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
req.on('readable', () => {
|
|
108
|
+
let chunk;
|
|
109
|
+
while ((chunk = req.read()) !== null) {
|
|
110
|
+
chunks.push(chunk);
|
|
111
|
+
chunklen += chunk.length;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
req.once('error', err => callback(err));
|
|
116
|
+
|
|
117
|
+
req.once('end', () => {
|
|
118
|
+
let res = Buffer.concat(chunks, chunklen);
|
|
119
|
+
let data;
|
|
120
|
+
let err;
|
|
121
|
+
try {
|
|
122
|
+
data = JSON.parse(res.toString());
|
|
123
|
+
} catch (E) {
|
|
124
|
+
err = E;
|
|
125
|
+
}
|
|
126
|
+
if (err) {
|
|
127
|
+
return callback(err);
|
|
128
|
+
}
|
|
129
|
+
if (data.status !== 'success' || data.error) {
|
|
130
|
+
return callback(new Error(data.error || 'Request failed'));
|
|
131
|
+
}
|
|
132
|
+
delete data.status;
|
|
133
|
+
testAccount = data;
|
|
134
|
+
callback(null, testAccount);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return promise;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
module.exports.getTestMessageUrl = function (info) {
|
|
141
|
+
if (!info || !info.response) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
let infoProps = new Map();
|
|
146
|
+
info.response.replace(/\[([^\]]+)\]$/, (m, props) => {
|
|
147
|
+
props.replace(/\b([A-Z0-9]+)=([^\s]+)/g, (m, key, value) => {
|
|
148
|
+
infoProps.set(key, value);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (infoProps.has('STATUS') && infoProps.has('MSGID')) {
|
|
153
|
+
return (testAccount.web || ETHEREAL_WEB) + '/message/' + infoProps.get('MSGID');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return false;
|
|
157
|
+
};
|