digi-sendzi/lib/smtp.js

110 lines
4.2 KiB
JavaScript
Raw Normal View History

2024-09-30 11:42:10 +00:00
import { connect } from 'tls'; // For SSL and STARTTLS
import { Socket } from 'net'; // For non-encrypted connections (before STARTTLS)
class SMTPClient {
constructor(host, port = 587, auth) {
this.host = host;
this.port = port;
this.auth = auth;
this.socket = null;
}
connect() {
return new Promise((resolve, reject) => {
if (this.port === 465) {
// SSL connection (SMTPS)
this.socket = connect({ host: this.host, port: this.port, rejectUnauthorized: false }, () => {
console.log(`Connected to SMTP server with SSL at ${this.host}:${this.port}`);
resolve();
});
} else if (this.port === 587) {
// Non-encrypted connection, STARTTLS will be applied later
this.socket = new Socket();
this.socket.connect(this.port, this.host, () => {
console.log(`Connected to SMTP server at ${this.host}:${this.port}`);
resolve();
});
} else {
// Plain non-encrypted connection (used for ports like 2525)
this.socket = new Socket();
this.socket.connect(this.port, this.host, () => {
console.log(`Connected to SMTP server at ${this.host}:${this.port} (No SSL/TLS)`);
resolve();
});
}
this.socket.on('error', (err) => {
reject(err);
});
});
}
async sendEmail(from, to, subject, body) {
try {
if (this.port === 587) {
// If using STARTTLS
await this.sendCommand(`EHLO ${this.host}`);
await this.sendCommand(`STARTTLS`);
this.upgradeToTLS(); // Upgrade connection to TLS after STARTTLS
}
await this.sendCommand(`EHLO ${this.host}`); // Send EHLO again after STARTTLS or for SSL
await this.sendCommand(`AUTH LOGIN`);
await this.sendAuth();
await this.sendCommand(`MAIL FROM:<${from}>`);
await this.sendCommand(`RCPT TO:<${to}>`);
await this.sendCommand('DATA');
await this.sendCommand(`${body}\r\n.`);
await this.sendCommand('QUIT');
} catch (error) {
throw new Error(`Error sending email: ${error.message}`);
}
}
async sendAuth() {
const base64User = Buffer.from(this.auth.user).toString('base64');
const base64Pass = Buffer.from(this.auth.pass).toString('base64');
await this.sendCommand(base64User);
return await this.sendCommand(base64Pass);
}
sendCommand(command) {
return new Promise((resolve, reject) => {
this.socket.write(`${command}\r\n`, (err) => {
if (err) return reject(err);
this.socket.once('data', (data) => {
const response = data.toString();
console.log('SMTP Response:', response);
if (response.startsWith('250') || response.startsWith('354') || response.startsWith('235')) {
resolve(response);
} else if (response.startsWith('334')) {
resolve(); // Continue authentication
} else if (response.startsWith('221')) {
console.log('SMTP session closed successfully.');
resolve(response);
} else if (response.startsWith('220')) {
resolve(); // Initial greeting
} else {
console.error('SMTP Error:', response);
reject(new Error(`SMTP Error: ${response}`));
}
});
});
});
}
// Upgrade the current connection to TLS (STARTTLS mode)
upgradeToTLS() {
this.socket = connect({
socket: this.socket, // Upgrade the existing socket to TLS
rejectUnauthorized: false
}, () => {
console.log(`Connection upgraded to TLS`);
});
}
}
export default SMTPClient;