1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.verifyMailboxSMTP = void 0;
|
7 | const net_1 = __importDefault(require("net"));
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | function isOverQuota(smtpReply) {
|
13 | return smtpReply && /(over quota)/gi.test(smtpReply);
|
14 | }
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | function isInvalidMailboxError(smtpReply) {
|
22 | return smtpReply && /^(510|511|513|550|551|553)/.test(smtpReply) && !/(junk|spam|openspf|spoofing|host|rbl.+blocked)/gi.test(smtpReply);
|
23 | }
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | function isMultilineGreet(smtpReply) {
|
30 | return smtpReply && /^(250|220)-/.test(smtpReply);
|
31 | }
|
32 | const logMethod = console.debug;
|
33 | async function verifyMailboxSMTP(params) {
|
34 |
|
35 |
|
36 | const { local, domain, mxRecords = [], timeout, debug, port = 25 } = params;
|
37 | const mxRecord = mxRecords[0];
|
38 | const log = debug ? logMethod : () => { };
|
39 | if (!mxRecord) {
|
40 | return false;
|
41 | }
|
42 | return new Promise((resolve) => {
|
43 | const socket = net_1.default.connect(port, mxRecord);
|
44 |
|
45 | let resTimeout;
|
46 | let resolved;
|
47 | const ret = (result) => {
|
48 | if (resolved)
|
49 | return;
|
50 | if (!(socket === null || socket === void 0 ? void 0 : socket.destroyed)) {
|
51 | socket === null || socket === void 0 ? void 0 : socket.write('QUIT\r\n');
|
52 | socket === null || socket === void 0 ? void 0 : socket.end();
|
53 | }
|
54 | clearTimeout(resTimeout);
|
55 | resolve(result);
|
56 | resolved = true;
|
57 | };
|
58 | const messages = [`HELO ${domain}`, `MAIL FROM: <${local}@${domain}>`, `RCPT TO: <${local}@${domain}>`];
|
59 | socket.on('data', (data) => {
|
60 | log('Mailbox: got data', data);
|
61 | if (isInvalidMailboxError(data))
|
62 | return ret(false);
|
63 | if (isOverQuota(data))
|
64 | return ret(false);
|
65 | if (!data.includes('220') && !data.includes('250'))
|
66 | return ret(null);
|
67 | if (isMultilineGreet(data))
|
68 | return;
|
69 | if (messages.length > 0) {
|
70 | const message = messages.shift();
|
71 | log('Mailbox: writing message', message);
|
72 | return socket.write(message + '\r\n');
|
73 | }
|
74 | ret(true);
|
75 | });
|
76 | socket.on('error', (err) => {
|
77 | log('Mailbox: error in socket', err);
|
78 | ret(null);
|
79 | });
|
80 | socket.on('close', (err) => {
|
81 | log('Mailbox: close socket', err);
|
82 | ret(null);
|
83 | });
|
84 | socket.on('timeout', () => {
|
85 | log('Mailbox: timeout socket');
|
86 | ret(null);
|
87 | });
|
88 | resTimeout = setTimeout(() => {
|
89 | log(`Mailbox: timed out (${timeout} ms)`);
|
90 | socket.destroy();
|
91 | ret(null);
|
92 | }, timeout);
|
93 | });
|
94 | }
|
95 | exports.verifyMailboxSMTP = verifyMailboxSMTP;
|