m0603va 1.0.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/Laba6/file1.js +23 -0
- package/Laba6/file2.js +23 -0
- package/Laba6/index.html +63 -0
- package/Laba6/m0603.js +29 -0
- package/Laba6/node_modules/.package-lock.json +83 -0
- package/Laba6/node_modules/httpntlm/.jshintrc +4 -0
- package/Laba6/node_modules/httpntlm/LICENSE +20 -0
- package/Laba6/node_modules/httpntlm/README.md +148 -0
- package/Laba6/node_modules/httpntlm/httpntlm.js +104 -0
- package/Laba6/node_modules/httpntlm/ntlm.js +390 -0
- package/Laba6/node_modules/httpntlm/package.json +33 -0
- package/Laba6/node_modules/httpreq/LICENSE +19 -0
- package/Laba6/node_modules/httpreq/README.md +383 -0
- package/Laba6/node_modules/httpreq/contributors.md +26 -0
- package/Laba6/node_modules/httpreq/lib/httpreq.js +681 -0
- package/Laba6/node_modules/httpreq/package.json +102 -0
- package/Laba6/node_modules/m0603sol/m0603.js +29 -0
- package/Laba6/node_modules/m0603sol/package.json +12 -0
- package/Laba6/node_modules/nodemailer/.gitattributes +6 -0
- package/Laba6/node_modules/nodemailer/.prettierrc.js +8 -0
- package/Laba6/node_modules/nodemailer/CHANGELOG.md +725 -0
- package/Laba6/node_modules/nodemailer/CODE_OF_CONDUCT.md +76 -0
- package/Laba6/node_modules/nodemailer/CONTRIBUTING.md +67 -0
- package/Laba6/node_modules/nodemailer/LICENSE +16 -0
- package/Laba6/node_modules/nodemailer/README.md +97 -0
- package/Laba6/node_modules/nodemailer/SECURITY.txt +22 -0
- package/Laba6/node_modules/nodemailer/lib/addressparser/index.js +313 -0
- package/Laba6/node_modules/nodemailer/lib/base64/index.js +142 -0
- package/Laba6/node_modules/nodemailer/lib/dkim/index.js +251 -0
- package/Laba6/node_modules/nodemailer/lib/dkim/message-parser.js +155 -0
- package/Laba6/node_modules/nodemailer/lib/dkim/relaxed-body.js +154 -0
- package/Laba6/node_modules/nodemailer/lib/dkim/sign.js +117 -0
- package/Laba6/node_modules/nodemailer/lib/fetch/cookies.js +281 -0
- package/Laba6/node_modules/nodemailer/lib/fetch/index.js +274 -0
- package/Laba6/node_modules/nodemailer/lib/json-transport/index.js +82 -0
- package/Laba6/node_modules/nodemailer/lib/mail-composer/index.js +558 -0
- package/Laba6/node_modules/nodemailer/lib/mailer/index.js +427 -0
- package/Laba6/node_modules/nodemailer/lib/mailer/mail-message.js +315 -0
- package/Laba6/node_modules/nodemailer/lib/mime-funcs/index.js +625 -0
- package/Laba6/node_modules/nodemailer/lib/mime-funcs/mime-types.js +2102 -0
- package/Laba6/node_modules/nodemailer/lib/mime-node/index.js +1290 -0
- package/Laba6/node_modules/nodemailer/lib/mime-node/last-newline.js +33 -0
- package/Laba6/node_modules/nodemailer/lib/mime-node/le-unix.js +43 -0
- package/Laba6/node_modules/nodemailer/lib/mime-node/le-windows.js +52 -0
- package/Laba6/node_modules/nodemailer/lib/nodemailer.js +143 -0
- package/Laba6/node_modules/nodemailer/lib/qp/index.js +219 -0
- package/Laba6/node_modules/nodemailer/lib/sendmail-transport/index.js +210 -0
- package/Laba6/node_modules/nodemailer/lib/ses-transport/index.js +349 -0
- package/Laba6/node_modules/nodemailer/lib/shared/index.js +638 -0
- package/Laba6/node_modules/nodemailer/lib/smtp-connection/data-stream.js +108 -0
- package/Laba6/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +143 -0
- package/Laba6/node_modules/nodemailer/lib/smtp-connection/index.js +1796 -0
- package/Laba6/node_modules/nodemailer/lib/smtp-pool/index.js +648 -0
- package/Laba6/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +253 -0
- package/Laba6/node_modules/nodemailer/lib/smtp-transport/index.js +416 -0
- package/Laba6/node_modules/nodemailer/lib/stream-transport/index.js +135 -0
- package/Laba6/node_modules/nodemailer/lib/well-known/index.js +47 -0
- package/Laba6/node_modules/nodemailer/lib/well-known/services.json +286 -0
- package/Laba6/node_modules/nodemailer/lib/xoauth2/index.js +376 -0
- package/Laba6/node_modules/nodemailer/package.json +46 -0
- package/Laba6/node_modules/nodemailer/postinstall.js +101 -0
- package/Laba6/node_modules/nodemailer-fetch/.eslintrc.js +56 -0
- package/Laba6/node_modules/nodemailer-fetch/.travis.yml +19 -0
- package/Laba6/node_modules/nodemailer-fetch/CHANGELOG.md +30 -0
- package/Laba6/node_modules/nodemailer-fetch/Gruntfile.js +27 -0
- package/Laba6/node_modules/nodemailer-fetch/LICENSE +16 -0
- package/Laba6/node_modules/nodemailer-fetch/README.md +55 -0
- package/Laba6/node_modules/nodemailer-fetch/lib/cookies.js +275 -0
- package/Laba6/node_modules/nodemailer-fetch/lib/fetch.js +224 -0
- package/Laba6/node_modules/nodemailer-fetch/package.json +30 -0
- package/Laba6/node_modules/nodemailer-fetch/test/cookies-test.js +391 -0
- package/Laba6/node_modules/nodemailer-fetch/test/fetch-test.js +486 -0
- package/Laba6/node_modules/nodemailer-shared/.eslintrc.js +59 -0
- package/Laba6/node_modules/nodemailer-shared/.travis.yml +18 -0
- package/Laba6/node_modules/nodemailer-shared/Gruntfile.js +27 -0
- package/Laba6/node_modules/nodemailer-shared/LICENSE +16 -0
- package/Laba6/node_modules/nodemailer-shared/README.md +14 -0
- package/Laba6/node_modules/nodemailer-shared/lib/shared.js +282 -0
- package/Laba6/node_modules/nodemailer-shared/package.json +36 -0
- package/Laba6/node_modules/nodemailer-shared/test/fixtures/message.html +1 -0
- package/Laba6/node_modules/nodemailer-shared/test/shared-test.js +291 -0
- package/Laba6/node_modules/nodemailer-smtp-transport/.eslintrc.js +59 -0
- package/Laba6/node_modules/nodemailer-smtp-transport/Gruntfile.js +27 -0
- package/Laba6/node_modules/nodemailer-smtp-transport/LICENSE +19 -0
- package/Laba6/node_modules/nodemailer-smtp-transport/README.md +7 -0
- package/Laba6/node_modules/nodemailer-smtp-transport/lib/smtp-transport.js +281 -0
- package/Laba6/node_modules/nodemailer-smtp-transport/package.json +37 -0
- package/Laba6/node_modules/nodemailer-wellknown/.travis.yml +17 -0
- package/Laba6/node_modules/nodemailer-wellknown/LICENSE +19 -0
- package/Laba6/node_modules/nodemailer-wellknown/README.md +80 -0
- package/Laba6/node_modules/nodemailer-wellknown/index.js +47 -0
- package/Laba6/node_modules/nodemailer-wellknown/package.json +26 -0
- package/Laba6/node_modules/nodemailer-wellknown/services.json +255 -0
- package/Laba6/node_modules/nodemailer-wellknown/test.js +23 -0
- package/Laba6/node_modules/smtp-connection/.eslintrc.js +56 -0
- package/Laba6/node_modules/smtp-connection/CHANGELOG.md +164 -0
- package/Laba6/node_modules/smtp-connection/Gruntfile.js +27 -0
- package/Laba6/node_modules/smtp-connection/LICENSE +19 -0
- package/Laba6/node_modules/smtp-connection/README.md +200 -0
- package/Laba6/node_modules/smtp-connection/lib/data-stream.js +111 -0
- package/Laba6/node_modules/smtp-connection/lib/smtp-connection.js +1443 -0
- package/Laba6/node_modules/smtp-connection/package.json +41 -0
- package/Laba6/node_modules/underscore/LICENSE +23 -0
- package/Laba6/node_modules/underscore/README.md +22 -0
- package/Laba6/node_modules/underscore/package.json +41 -0
- package/Laba6/node_modules/underscore/underscore-min.js +6 -0
- package/Laba6/node_modules/underscore/underscore.js +1415 -0
- package/Laba6/package-lock.json +94 -0
- package/Laba6/package.json +17 -0
- package/Laba6.txt +31 -0
- package/file1.js +23 -0
- package/file2.js +23 -0
- package/index.html +63 -0
- package/m0603.js +29 -0
- package/m0603Sol/m0603.js +29 -0
- package/m0603Sol/package.json +12 -0
- package/package.json +17 -0
@@ -0,0 +1,253 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const SMTPConnection = require('../smtp-connection');
|
4
|
+
const assign = require('../shared').assign;
|
5
|
+
const XOAuth2 = require('../xoauth2');
|
6
|
+
const EventEmitter = require('events');
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Creates an element for the pool
|
10
|
+
*
|
11
|
+
* @constructor
|
12
|
+
* @param {Object} options SMTPPool instance
|
13
|
+
*/
|
14
|
+
class PoolResource extends EventEmitter {
|
15
|
+
constructor(pool) {
|
16
|
+
super();
|
17
|
+
|
18
|
+
this.pool = pool;
|
19
|
+
this.options = pool.options;
|
20
|
+
this.logger = this.pool.logger;
|
21
|
+
|
22
|
+
if (this.options.auth) {
|
23
|
+
switch ((this.options.auth.type || '').toString().toUpperCase()) {
|
24
|
+
case 'OAUTH2': {
|
25
|
+
let oauth2 = new XOAuth2(this.options.auth, this.logger);
|
26
|
+
oauth2.provisionCallback = (this.pool.mailer && this.pool.mailer.get('oauth2_provision_cb')) || oauth2.provisionCallback;
|
27
|
+
this.auth = {
|
28
|
+
type: 'OAUTH2',
|
29
|
+
user: this.options.auth.user,
|
30
|
+
oauth2,
|
31
|
+
method: 'XOAUTH2'
|
32
|
+
};
|
33
|
+
oauth2.on('token', token => this.pool.mailer.emit('token', token));
|
34
|
+
oauth2.on('error', err => this.emit('error', err));
|
35
|
+
break;
|
36
|
+
}
|
37
|
+
default:
|
38
|
+
if (!this.options.auth.user && !this.options.auth.pass) {
|
39
|
+
break;
|
40
|
+
}
|
41
|
+
this.auth = {
|
42
|
+
type: (this.options.auth.type || '').toString().toUpperCase() || 'LOGIN',
|
43
|
+
user: this.options.auth.user,
|
44
|
+
credentials: {
|
45
|
+
user: this.options.auth.user || '',
|
46
|
+
pass: this.options.auth.pass,
|
47
|
+
options: this.options.auth.options
|
48
|
+
},
|
49
|
+
method: (this.options.auth.method || '').trim().toUpperCase() || this.options.authMethod || false
|
50
|
+
};
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
this._connection = false;
|
55
|
+
this._connected = false;
|
56
|
+
|
57
|
+
this.messages = 0;
|
58
|
+
this.available = true;
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Initiates a connection to the SMTP server
|
63
|
+
*
|
64
|
+
* @param {Function} callback Callback function to run once the connection is established or failed
|
65
|
+
*/
|
66
|
+
connect(callback) {
|
67
|
+
this.pool.getSocket(this.options, (err, socketOptions) => {
|
68
|
+
if (err) {
|
69
|
+
return callback(err);
|
70
|
+
}
|
71
|
+
|
72
|
+
let returned = false;
|
73
|
+
let options = this.options;
|
74
|
+
if (socketOptions && socketOptions.connection) {
|
75
|
+
this.logger.info(
|
76
|
+
{
|
77
|
+
tnx: 'proxy',
|
78
|
+
remoteAddress: socketOptions.connection.remoteAddress,
|
79
|
+
remotePort: socketOptions.connection.remotePort,
|
80
|
+
destHost: options.host || '',
|
81
|
+
destPort: options.port || '',
|
82
|
+
action: 'connected'
|
83
|
+
},
|
84
|
+
'Using proxied socket from %s:%s to %s:%s',
|
85
|
+
socketOptions.connection.remoteAddress,
|
86
|
+
socketOptions.connection.remotePort,
|
87
|
+
options.host || '',
|
88
|
+
options.port || ''
|
89
|
+
);
|
90
|
+
|
91
|
+
options = assign(false, options);
|
92
|
+
Object.keys(socketOptions).forEach(key => {
|
93
|
+
options[key] = socketOptions[key];
|
94
|
+
});
|
95
|
+
}
|
96
|
+
|
97
|
+
this.connection = new SMTPConnection(options);
|
98
|
+
|
99
|
+
this.connection.once('error', err => {
|
100
|
+
this.emit('error', err);
|
101
|
+
if (returned) {
|
102
|
+
return;
|
103
|
+
}
|
104
|
+
returned = true;
|
105
|
+
return callback(err);
|
106
|
+
});
|
107
|
+
|
108
|
+
this.connection.once('end', () => {
|
109
|
+
this.close();
|
110
|
+
if (returned) {
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
returned = true;
|
114
|
+
|
115
|
+
let timer = setTimeout(() => {
|
116
|
+
if (returned) {
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
// still have not returned, this means we have an unexpected connection close
|
120
|
+
let err = new Error('Unexpected socket close');
|
121
|
+
if (this.connection && this.connection._socket && this.connection._socket.upgrading) {
|
122
|
+
// starttls connection errors
|
123
|
+
err.code = 'ETLS';
|
124
|
+
}
|
125
|
+
callback(err);
|
126
|
+
}, 1000);
|
127
|
+
|
128
|
+
try {
|
129
|
+
timer.unref();
|
130
|
+
} catch (E) {
|
131
|
+
// Ignore. Happens on envs with non-node timer implementation
|
132
|
+
}
|
133
|
+
});
|
134
|
+
|
135
|
+
this.connection.connect(() => {
|
136
|
+
if (returned) {
|
137
|
+
return;
|
138
|
+
}
|
139
|
+
|
140
|
+
if (this.auth && (this.connection.allowsAuth || options.forceAuth)) {
|
141
|
+
this.connection.login(this.auth, err => {
|
142
|
+
if (returned) {
|
143
|
+
return;
|
144
|
+
}
|
145
|
+
returned = true;
|
146
|
+
|
147
|
+
if (err) {
|
148
|
+
this.connection.close();
|
149
|
+
this.emit('error', err);
|
150
|
+
return callback(err);
|
151
|
+
}
|
152
|
+
|
153
|
+
this._connected = true;
|
154
|
+
callback(null, true);
|
155
|
+
});
|
156
|
+
} else {
|
157
|
+
returned = true;
|
158
|
+
this._connected = true;
|
159
|
+
return callback(null, true);
|
160
|
+
}
|
161
|
+
});
|
162
|
+
});
|
163
|
+
}
|
164
|
+
|
165
|
+
/**
|
166
|
+
* Sends an e-mail to be sent using the selected settings
|
167
|
+
*
|
168
|
+
* @param {Object} mail Mail object
|
169
|
+
* @param {Function} callback Callback function
|
170
|
+
*/
|
171
|
+
send(mail, callback) {
|
172
|
+
if (!this._connected) {
|
173
|
+
return this.connect(err => {
|
174
|
+
if (err) {
|
175
|
+
return callback(err);
|
176
|
+
}
|
177
|
+
return this.send(mail, callback);
|
178
|
+
});
|
179
|
+
}
|
180
|
+
|
181
|
+
let envelope = mail.message.getEnvelope();
|
182
|
+
let messageId = mail.message.messageId();
|
183
|
+
|
184
|
+
let recipients = [].concat(envelope.to || []);
|
185
|
+
if (recipients.length > 3) {
|
186
|
+
recipients.push('...and ' + recipients.splice(2).length + ' more');
|
187
|
+
}
|
188
|
+
this.logger.info(
|
189
|
+
{
|
190
|
+
tnx: 'send',
|
191
|
+
messageId,
|
192
|
+
cid: this.id
|
193
|
+
},
|
194
|
+
'Sending message %s using #%s to <%s>',
|
195
|
+
messageId,
|
196
|
+
this.id,
|
197
|
+
recipients.join(', ')
|
198
|
+
);
|
199
|
+
|
200
|
+
if (mail.data.dsn) {
|
201
|
+
envelope.dsn = mail.data.dsn;
|
202
|
+
}
|
203
|
+
|
204
|
+
this.connection.send(envelope, mail.message.createReadStream(), (err, info) => {
|
205
|
+
this.messages++;
|
206
|
+
|
207
|
+
if (err) {
|
208
|
+
this.connection.close();
|
209
|
+
this.emit('error', err);
|
210
|
+
return callback(err);
|
211
|
+
}
|
212
|
+
|
213
|
+
info.envelope = {
|
214
|
+
from: envelope.from,
|
215
|
+
to: envelope.to
|
216
|
+
};
|
217
|
+
info.messageId = messageId;
|
218
|
+
|
219
|
+
setImmediate(() => {
|
220
|
+
let err;
|
221
|
+
if (this.messages >= this.options.maxMessages) {
|
222
|
+
err = new Error('Resource exhausted');
|
223
|
+
err.code = 'EMAXLIMIT';
|
224
|
+
this.connection.close();
|
225
|
+
this.emit('error', err);
|
226
|
+
} else {
|
227
|
+
this.pool._checkRateLimit(() => {
|
228
|
+
this.available = true;
|
229
|
+
this.emit('available');
|
230
|
+
});
|
231
|
+
}
|
232
|
+
});
|
233
|
+
|
234
|
+
callback(null, info);
|
235
|
+
});
|
236
|
+
}
|
237
|
+
|
238
|
+
/**
|
239
|
+
* Closes the connection
|
240
|
+
*/
|
241
|
+
close() {
|
242
|
+
this._connected = false;
|
243
|
+
if (this.auth && this.auth.oauth2) {
|
244
|
+
this.auth.oauth2.removeAllListeners();
|
245
|
+
}
|
246
|
+
if (this.connection) {
|
247
|
+
this.connection.close();
|
248
|
+
}
|
249
|
+
this.emit('close');
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
module.exports = PoolResource;
|
@@ -0,0 +1,416 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const EventEmitter = require('events');
|
4
|
+
const SMTPConnection = require('../smtp-connection');
|
5
|
+
const wellKnown = require('../well-known');
|
6
|
+
const shared = require('../shared');
|
7
|
+
const XOAuth2 = require('../xoauth2');
|
8
|
+
const packageData = require('../../package.json');
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Creates a SMTP transport object for Nodemailer
|
12
|
+
*
|
13
|
+
* @constructor
|
14
|
+
* @param {Object} options Connection options
|
15
|
+
*/
|
16
|
+
class SMTPTransport extends EventEmitter {
|
17
|
+
constructor(options) {
|
18
|
+
super();
|
19
|
+
|
20
|
+
options = options || {};
|
21
|
+
|
22
|
+
if (typeof options === 'string') {
|
23
|
+
options = {
|
24
|
+
url: options
|
25
|
+
};
|
26
|
+
}
|
27
|
+
|
28
|
+
let urlData;
|
29
|
+
let service = options.service;
|
30
|
+
|
31
|
+
if (typeof options.getSocket === 'function') {
|
32
|
+
this.getSocket = options.getSocket;
|
33
|
+
}
|
34
|
+
|
35
|
+
if (options.url) {
|
36
|
+
urlData = shared.parseConnectionUrl(options.url);
|
37
|
+
service = service || urlData.service;
|
38
|
+
}
|
39
|
+
|
40
|
+
this.options = shared.assign(
|
41
|
+
false, // create new object
|
42
|
+
options, // regular options
|
43
|
+
urlData, // url options
|
44
|
+
service && wellKnown(service) // wellknown options
|
45
|
+
);
|
46
|
+
|
47
|
+
this.logger = shared.getLogger(this.options, {
|
48
|
+
component: this.options.component || 'smtp-transport'
|
49
|
+
});
|
50
|
+
|
51
|
+
// temporary object
|
52
|
+
let connection = new SMTPConnection(this.options);
|
53
|
+
|
54
|
+
this.name = 'SMTP';
|
55
|
+
this.version = packageData.version + '[client:' + connection.version + ']';
|
56
|
+
|
57
|
+
if (this.options.auth) {
|
58
|
+
this.auth = this.getAuth({});
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
/**
|
63
|
+
* Placeholder function for creating proxy sockets. This method immediatelly returns
|
64
|
+
* without a socket
|
65
|
+
*
|
66
|
+
* @param {Object} options Connection options
|
67
|
+
* @param {Function} callback Callback function to run with the socket keys
|
68
|
+
*/
|
69
|
+
getSocket(options, callback) {
|
70
|
+
// return immediatelly
|
71
|
+
return setImmediate(() => callback(null, false));
|
72
|
+
}
|
73
|
+
|
74
|
+
getAuth(authOpts) {
|
75
|
+
if (!authOpts) {
|
76
|
+
return this.auth;
|
77
|
+
}
|
78
|
+
|
79
|
+
let hasAuth = false;
|
80
|
+
let authData = {};
|
81
|
+
|
82
|
+
if (this.options.auth && typeof this.options.auth === 'object') {
|
83
|
+
Object.keys(this.options.auth).forEach(key => {
|
84
|
+
hasAuth = true;
|
85
|
+
authData[key] = this.options.auth[key];
|
86
|
+
});
|
87
|
+
}
|
88
|
+
|
89
|
+
if (authOpts && typeof authOpts === 'object') {
|
90
|
+
Object.keys(authOpts).forEach(key => {
|
91
|
+
hasAuth = true;
|
92
|
+
authData[key] = authOpts[key];
|
93
|
+
});
|
94
|
+
}
|
95
|
+
|
96
|
+
if (!hasAuth) {
|
97
|
+
return false;
|
98
|
+
}
|
99
|
+
|
100
|
+
switch ((authData.type || '').toString().toUpperCase()) {
|
101
|
+
case 'OAUTH2': {
|
102
|
+
if (!authData.service && !authData.user) {
|
103
|
+
return false;
|
104
|
+
}
|
105
|
+
let oauth2 = new XOAuth2(authData, this.logger);
|
106
|
+
oauth2.provisionCallback = (this.mailer && this.mailer.get('oauth2_provision_cb')) || oauth2.provisionCallback;
|
107
|
+
oauth2.on('token', token => this.mailer.emit('token', token));
|
108
|
+
oauth2.on('error', err => this.emit('error', err));
|
109
|
+
return {
|
110
|
+
type: 'OAUTH2',
|
111
|
+
user: authData.user,
|
112
|
+
oauth2,
|
113
|
+
method: 'XOAUTH2'
|
114
|
+
};
|
115
|
+
}
|
116
|
+
default:
|
117
|
+
return {
|
118
|
+
type: (authData.type || '').toString().toUpperCase() || 'LOGIN',
|
119
|
+
user: authData.user,
|
120
|
+
credentials: {
|
121
|
+
user: authData.user || '',
|
122
|
+
pass: authData.pass,
|
123
|
+
options: authData.options
|
124
|
+
},
|
125
|
+
method: (authData.method || '').trim().toUpperCase() || this.options.authMethod || false
|
126
|
+
};
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Sends an e-mail using the selected settings
|
132
|
+
*
|
133
|
+
* @param {Object} mail Mail object
|
134
|
+
* @param {Function} callback Callback function
|
135
|
+
*/
|
136
|
+
send(mail, callback) {
|
137
|
+
this.getSocket(this.options, (err, socketOptions) => {
|
138
|
+
if (err) {
|
139
|
+
return callback(err);
|
140
|
+
}
|
141
|
+
|
142
|
+
let returned = false;
|
143
|
+
let options = this.options;
|
144
|
+
if (socketOptions && socketOptions.connection) {
|
145
|
+
this.logger.info(
|
146
|
+
{
|
147
|
+
tnx: 'proxy',
|
148
|
+
remoteAddress: socketOptions.connection.remoteAddress,
|
149
|
+
remotePort: socketOptions.connection.remotePort,
|
150
|
+
destHost: options.host || '',
|
151
|
+
destPort: options.port || '',
|
152
|
+
action: 'connected'
|
153
|
+
},
|
154
|
+
'Using proxied socket from %s:%s to %s:%s',
|
155
|
+
socketOptions.connection.remoteAddress,
|
156
|
+
socketOptions.connection.remotePort,
|
157
|
+
options.host || '',
|
158
|
+
options.port || ''
|
159
|
+
);
|
160
|
+
|
161
|
+
// only copy options if we need to modify it
|
162
|
+
options = shared.assign(false, options);
|
163
|
+
Object.keys(socketOptions).forEach(key => {
|
164
|
+
options[key] = socketOptions[key];
|
165
|
+
});
|
166
|
+
}
|
167
|
+
|
168
|
+
let connection = new SMTPConnection(options);
|
169
|
+
|
170
|
+
connection.once('error', err => {
|
171
|
+
if (returned) {
|
172
|
+
return;
|
173
|
+
}
|
174
|
+
returned = true;
|
175
|
+
connection.close();
|
176
|
+
return callback(err);
|
177
|
+
});
|
178
|
+
|
179
|
+
connection.once('end', () => {
|
180
|
+
if (returned) {
|
181
|
+
return;
|
182
|
+
}
|
183
|
+
|
184
|
+
let timer = setTimeout(() => {
|
185
|
+
if (returned) {
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
returned = true;
|
189
|
+
// still have not returned, this means we have an unexpected connection close
|
190
|
+
let err = new Error('Unexpected socket close');
|
191
|
+
if (connection && connection._socket && connection._socket.upgrading) {
|
192
|
+
// starttls connection errors
|
193
|
+
err.code = 'ETLS';
|
194
|
+
}
|
195
|
+
callback(err);
|
196
|
+
}, 1000);
|
197
|
+
|
198
|
+
try {
|
199
|
+
timer.unref();
|
200
|
+
} catch (E) {
|
201
|
+
// Ignore. Happens on envs with non-node timer implementation
|
202
|
+
}
|
203
|
+
});
|
204
|
+
|
205
|
+
let sendMessage = () => {
|
206
|
+
let envelope = mail.message.getEnvelope();
|
207
|
+
let messageId = mail.message.messageId();
|
208
|
+
|
209
|
+
let recipients = [].concat(envelope.to || []);
|
210
|
+
if (recipients.length > 3) {
|
211
|
+
recipients.push('...and ' + recipients.splice(2).length + ' more');
|
212
|
+
}
|
213
|
+
|
214
|
+
if (mail.data.dsn) {
|
215
|
+
envelope.dsn = mail.data.dsn;
|
216
|
+
}
|
217
|
+
|
218
|
+
this.logger.info(
|
219
|
+
{
|
220
|
+
tnx: 'send',
|
221
|
+
messageId
|
222
|
+
},
|
223
|
+
'Sending message %s to <%s>',
|
224
|
+
messageId,
|
225
|
+
recipients.join(', ')
|
226
|
+
);
|
227
|
+
|
228
|
+
connection.send(envelope, mail.message.createReadStream(), (err, info) => {
|
229
|
+
returned = true;
|
230
|
+
connection.close();
|
231
|
+
if (err) {
|
232
|
+
this.logger.error(
|
233
|
+
{
|
234
|
+
err,
|
235
|
+
tnx: 'send'
|
236
|
+
},
|
237
|
+
'Send error for %s: %s',
|
238
|
+
messageId,
|
239
|
+
err.message
|
240
|
+
);
|
241
|
+
return callback(err);
|
242
|
+
}
|
243
|
+
info.envelope = {
|
244
|
+
from: envelope.from,
|
245
|
+
to: envelope.to
|
246
|
+
};
|
247
|
+
info.messageId = messageId;
|
248
|
+
try {
|
249
|
+
return callback(null, info);
|
250
|
+
} catch (E) {
|
251
|
+
this.logger.error(
|
252
|
+
{
|
253
|
+
err: E,
|
254
|
+
tnx: 'callback'
|
255
|
+
},
|
256
|
+
'Callback error for %s: %s',
|
257
|
+
messageId,
|
258
|
+
E.message
|
259
|
+
);
|
260
|
+
}
|
261
|
+
});
|
262
|
+
};
|
263
|
+
|
264
|
+
connection.connect(() => {
|
265
|
+
if (returned) {
|
266
|
+
return;
|
267
|
+
}
|
268
|
+
|
269
|
+
let auth = this.getAuth(mail.data.auth);
|
270
|
+
|
271
|
+
if (auth && (connection.allowsAuth || options.forceAuth)) {
|
272
|
+
connection.login(auth, err => {
|
273
|
+
if (auth && auth !== this.auth && auth.oauth2) {
|
274
|
+
auth.oauth2.removeAllListeners();
|
275
|
+
}
|
276
|
+
if (returned) {
|
277
|
+
return;
|
278
|
+
}
|
279
|
+
|
280
|
+
if (err) {
|
281
|
+
returned = true;
|
282
|
+
connection.close();
|
283
|
+
return callback(err);
|
284
|
+
}
|
285
|
+
|
286
|
+
sendMessage();
|
287
|
+
});
|
288
|
+
} else {
|
289
|
+
sendMessage();
|
290
|
+
}
|
291
|
+
});
|
292
|
+
});
|
293
|
+
}
|
294
|
+
|
295
|
+
/**
|
296
|
+
* Verifies SMTP configuration
|
297
|
+
*
|
298
|
+
* @param {Function} callback Callback function
|
299
|
+
*/
|
300
|
+
verify(callback) {
|
301
|
+
let promise;
|
302
|
+
|
303
|
+
if (!callback) {
|
304
|
+
promise = new Promise((resolve, reject) => {
|
305
|
+
callback = shared.callbackPromise(resolve, reject);
|
306
|
+
});
|
307
|
+
}
|
308
|
+
|
309
|
+
this.getSocket(this.options, (err, socketOptions) => {
|
310
|
+
if (err) {
|
311
|
+
return callback(err);
|
312
|
+
}
|
313
|
+
|
314
|
+
let options = this.options;
|
315
|
+
if (socketOptions && socketOptions.connection) {
|
316
|
+
this.logger.info(
|
317
|
+
{
|
318
|
+
tnx: 'proxy',
|
319
|
+
remoteAddress: socketOptions.connection.remoteAddress,
|
320
|
+
remotePort: socketOptions.connection.remotePort,
|
321
|
+
destHost: options.host || '',
|
322
|
+
destPort: options.port || '',
|
323
|
+
action: 'connected'
|
324
|
+
},
|
325
|
+
'Using proxied socket from %s:%s to %s:%s',
|
326
|
+
socketOptions.connection.remoteAddress,
|
327
|
+
socketOptions.connection.remotePort,
|
328
|
+
options.host || '',
|
329
|
+
options.port || ''
|
330
|
+
);
|
331
|
+
|
332
|
+
options = shared.assign(false, options);
|
333
|
+
Object.keys(socketOptions).forEach(key => {
|
334
|
+
options[key] = socketOptions[key];
|
335
|
+
});
|
336
|
+
}
|
337
|
+
|
338
|
+
let connection = new SMTPConnection(options);
|
339
|
+
let returned = false;
|
340
|
+
|
341
|
+
connection.once('error', err => {
|
342
|
+
if (returned) {
|
343
|
+
return;
|
344
|
+
}
|
345
|
+
returned = true;
|
346
|
+
connection.close();
|
347
|
+
return callback(err);
|
348
|
+
});
|
349
|
+
|
350
|
+
connection.once('end', () => {
|
351
|
+
if (returned) {
|
352
|
+
return;
|
353
|
+
}
|
354
|
+
returned = true;
|
355
|
+
return callback(new Error('Connection closed'));
|
356
|
+
});
|
357
|
+
|
358
|
+
let finalize = () => {
|
359
|
+
if (returned) {
|
360
|
+
return;
|
361
|
+
}
|
362
|
+
returned = true;
|
363
|
+
connection.quit();
|
364
|
+
return callback(null, true);
|
365
|
+
};
|
366
|
+
|
367
|
+
connection.connect(() => {
|
368
|
+
if (returned) {
|
369
|
+
return;
|
370
|
+
}
|
371
|
+
|
372
|
+
let authData = this.getAuth({});
|
373
|
+
|
374
|
+
if (authData && (connection.allowsAuth || options.forceAuth)) {
|
375
|
+
connection.login(authData, err => {
|
376
|
+
if (returned) {
|
377
|
+
return;
|
378
|
+
}
|
379
|
+
|
380
|
+
if (err) {
|
381
|
+
returned = true;
|
382
|
+
connection.close();
|
383
|
+
return callback(err);
|
384
|
+
}
|
385
|
+
|
386
|
+
finalize();
|
387
|
+
});
|
388
|
+
} else if (!authData && connection.allowsAuth && options.forceAuth) {
|
389
|
+
let err = new Error('Authentication info was not provided');
|
390
|
+
err.code = 'NoAuth';
|
391
|
+
|
392
|
+
returned = true;
|
393
|
+
connection.close();
|
394
|
+
return callback(err);
|
395
|
+
} else {
|
396
|
+
finalize();
|
397
|
+
}
|
398
|
+
});
|
399
|
+
});
|
400
|
+
|
401
|
+
return promise;
|
402
|
+
}
|
403
|
+
|
404
|
+
/**
|
405
|
+
* Releases resources
|
406
|
+
*/
|
407
|
+
close() {
|
408
|
+
if (this.auth && this.auth.oauth2) {
|
409
|
+
this.auth.oauth2.removeAllListeners();
|
410
|
+
}
|
411
|
+
this.emit('close');
|
412
|
+
}
|
413
|
+
}
|
414
|
+
|
415
|
+
// expose to the world
|
416
|
+
module.exports = SMTPTransport;
|