mirror of
https://github.com/eleith/emailjs.git
synced 2024-07-04 19:58:51 +00:00
113 lines
2.2 KiB
TypeScript
113 lines
2.2 KiB
TypeScript
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);
|
|
}
|
|
}
|