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;