Skip to content

Commit c35fa0a

Browse files
authored
Merge pull request #2 from iAlex97/master
Check if socket is writeable before sending it data
2 parents d597c59 + c410abd commit c35fa0a

File tree

3 files changed

+107
-8
lines changed

3 files changed

+107
-8
lines changed

src/smtp/smtp.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,34 @@ export const checkSMTP = async (
1515
): Promise<OutputFormat> => {
1616
const timeout = 1000 * 10 // 10 seconds
1717
return new Promise(r => {
18+
let receivedData: boolean = false;
1819
const socket = net.createConnection(25, exchange)
1920
socket.setEncoding('ascii')
2021
socket.setTimeout(timeout)
2122
socket.on('error', error => {
2223
log('error', error)
2324
socket.emit('fail', error)
2425
})
25-
26+
socket.on('close', hadError => {
27+
if (!receivedData && !hadError) {
28+
socket.emit('fail', 'Mail server closed connection without sending any data.')
29+
}
30+
})
2631
socket.on('fail', msg => {
2732
r(createOutput('smtp', msg))
28-
socket.write(`quit\r\n`)
29-
socket.end()
30-
socket.destroy()
33+
if (socket.writable && !socket.destroyed) {
34+
socket.write(`quit\r\n`)
35+
socket.end()
36+
socket.destroy()
37+
}
3138
})
3239

3340
socket.on('success', () => {
34-
socket.write(`quit\r\n`)
35-
socket.end()
36-
socket.destroy()
41+
if (socket.writable && !socket.destroyed) {
42+
socket.write(`quit\r\n`)
43+
socket.end()
44+
socket.destroy()
45+
}
3746
r(createOutput())
3847
})
3948

@@ -45,7 +54,11 @@ export const checkSMTP = async (
4554
let i = 0
4655
socket.on('next', () => {
4756
if (i < 3) {
48-
socket.write(commands[i++])
57+
if (socket.writable) {
58+
socket.write(commands[i++])
59+
} else {
60+
socket.emit('fail', 'SMTP communication unexpectedly closed.')
61+
}
4962
} else {
5063
socket.emit('success')
5164
}
@@ -57,6 +70,7 @@ export const checkSMTP = async (
5770

5871
socket.on('connect', () => {
5972
socket.on('data', msg => {
73+
receivedData = true;
6074
log('data', msg)
6175
if (hasCode(msg, 220) || hasCode(msg, 250)) {
6276
socket.emit('next', msg)

test/__snapshots__/index.test.ts.snap

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,31 @@ Object {
100100
}
101101
`;
102102

103+
exports[`validation tests fails with bad mailbox 3`] = `
104+
Object {
105+
"reason": "smtp",
106+
"valid": false,
107+
"validators": Object {
108+
"disposable": Object {
109+
"valid": true,
110+
},
111+
"mx": Object {
112+
"valid": true,
113+
},
114+
"regex": Object {
115+
"valid": true,
116+
},
117+
"smtp": Object {
118+
"reason": "Mailbox not found.",
119+
"valid": false,
120+
},
121+
"typo": Object {
122+
"valid": true,
123+
},
124+
},
125+
}
126+
`;
127+
103128
exports[`validation tests fails with bad regex 1`] = `
104129
Object {
105130
"reason": "regex",
@@ -175,6 +200,31 @@ Object {
175200
}
176201
`;
177202

203+
exports[`validation tests fails without sending data 1`] = `
204+
Object {
205+
"reason": "smtp",
206+
"valid": false,
207+
"validators": Object {
208+
"disposable": Object {
209+
"valid": true,
210+
},
211+
"mx": Object {
212+
"valid": true,
213+
},
214+
"regex": Object {
215+
"valid": true,
216+
},
217+
"smtp": Object {
218+
"reason": "Mail server closed connection without sending any data.",
219+
"valid": false,
220+
},
221+
"typo": Object {
222+
"valid": true,
223+
},
224+
},
225+
}
226+
`;
227+
178228
exports[`validation tests passes when valid special char 1`] = `
179229
Object {
180230
"valid": true,
@@ -198,6 +248,29 @@ Object {
198248
}
199249
`;
200250

251+
exports[`validation tests passes when valid special char 2`] = `
252+
Object {
253+
"valid": true,
254+
"validators": Object {
255+
"disposable": Object {
256+
"valid": true,
257+
},
258+
"mx": Object {
259+
"valid": true,
260+
},
261+
"regex": Object {
262+
"valid": true,
263+
},
264+
"smtp": Object {
265+
"valid": true,
266+
},
267+
"typo": Object {
268+
"valid": true,
269+
},
270+
},
271+
}
272+
`;
273+
201274
exports[`validation tests passes when valid wildcard 1`] = `
202275
Object {
203276
"valid": true,

test/index.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ import { validate } from '../src/index'
55
const elevenSeconds = 11 * 1000
66

77
describe('validation tests', () => {
8+
it('fails without sending data', async () => {
9+
const res = await validate({
10+
11+
sender: '[email protected]',
12+
validateTypo: false,
13+
validateDisposable: false,
14+
})
15+
expect(res.valid).toBe(false)
16+
expect(res.reason).toBe('smtp')
17+
expect(res.validators.smtp?.valid).toBe(false)
18+
expect(res).toMatchSnapshot()
19+
})
820
it('fails with bad regex', async () => {
921
const res = await validate('david.gmail.com')
1022
expect(res.valid).toBe(false)

0 commit comments

Comments
 (0)