wzp
2021-05-13 7d694a9113118daec5be7ac224dab46a3b20f106
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { SMTPError, SMTPErrorStates } from './error';
import type { Socket } from 'net';
import type { TLSSocket } from 'tls';
 
export class SMTPResponseMonitor {
    public readonly stop: (err?: Error) => void;
 
    constructor(
        stream: Socket | TLSSocket,
        timeout: number,
        onerror: (err: Error) => void
    ) {
        let buffer = '';
 
        const notify = () => {
            if (buffer.length) {
                // parse buffer for response codes
                const line = buffer.replace('\r', '');
                if (
                    !(
                        line
                            .trim()
                            .split(/\n/)
                            .pop()
                            ?.match(/^(\d{3})\s/) ?? false
                    )
                ) {
                    return;
                }
 
                const match = line ? line.match(/(\d+)\s?(.*)/) : null;
                const data =
                    match !== null
                        ? { code: match[1], message: match[2], data: line }
                        : { code: -1, data: line };
 
                stream.emit('response', null, data);
                buffer = '';
            }
        };
 
        const error = (err: Error) => {
            stream.emit(
                'response',
                SMTPError.create(
                    'connection encountered an error',
                    SMTPErrorStates.ERROR,
                    err
                )
            );
        };
 
        const timedout = (err?: Error) => {
            stream.end();
            stream.emit(
                'response',
                SMTPError.create(
                    'timedout while connecting to smtp server',
                    SMTPErrorStates.TIMEDOUT,
                    err
                )
            );
        };
 
        const watch = (data: string | Buffer) => {
            if (data !== null) {
                buffer += data.toString();
                notify();
            }
        };
 
        const close = (err: Error) => {
            stream.emit(
                'response',
                SMTPError.create(
                    'connection has closed',
                    SMTPErrorStates.CONNECTIONCLOSED,
                    err
                )
            );
        };
 
        const end = (err: Error) => {
            stream.emit(
                'response',
                SMTPError.create(
                    'connection has ended',
                    SMTPErrorStates.CONNECTIONENDED,
                    err
                )
            );
        };
 
        this.stop = (err) => {
            stream.removeAllListeners('response');
            stream.removeListener('data', watch);
            stream.removeListener('end', end);
            stream.removeListener('close', close);
            stream.removeListener('error', error);
 
            if (err != null && typeof onerror === 'function') {
                onerror(err);
            }
        };
 
        stream.on('data', watch);
        stream.on('end', end);
        stream.on('close', close);
        stream.on('error', error);
        stream.setTimeout(timeout, timedout);
    }
}