@carlgo11/smtp-server
Advanced tools
Comparing version 0.0.2 to 0.0.3
{ | ||
"name": "@carlgo11/smtp-server", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "Simple lightweight SMTP server written in Node.js", | ||
@@ -5,0 +5,0 @@ "main": "src/core/SMTPServer.js", |
import {handleTLSConnection} from '../core/TLSServer.js'; | ||
import Logger from '../utils/logger.js'; | ||
import Logger from '../utils/Logger.js'; | ||
import Response from '../models/Response.js'; | ||
@@ -4,0 +4,0 @@ |
import net from 'net'; | ||
import Session from '../models/Session.js'; | ||
import Logger from '../utils/logger.js'; | ||
import {registerCommand, handleCommand} from '../commands/CommandHandler.js'; | ||
import _Response from '../models/Response.js'; | ||
import Logger from '../utils/Logger.js'; | ||
import reverseDNS from '../utils/reverseDNS.js'; | ||
import {handleCommand, registerCommand} from '../commands/CommandHandler.js'; | ||
import context from './ServerContext.js'; | ||
import _Response from '../models/Response.js'; | ||
import events from './Event.js'; | ||
@@ -17,2 +18,4 @@ | ||
const activeSessions = new Set(); | ||
registerCommand('EHLO', EHLO); | ||
@@ -26,3 +29,2 @@ registerCommand('STARTTLS', STARTTLS); | ||
export function startSMTPServer(options = {}) { | ||
// Create a shared context for all configurations and handlers | ||
@@ -32,10 +34,15 @@ context.setOptions(options); | ||
// Create the SMTP server | ||
const server = net.createServer((socket) => { | ||
const server = net.createServer(async (socket) => { | ||
const session = new Session(socket); | ||
// Add session to active sessions | ||
activeSessions.add(session); | ||
session.rDNS = await reverseDNS(session.clientIP); | ||
Logger.setLevel(context.logLevel) | ||
const rDNS = `<${session.rDNS}>` | ||
Logger.info(`${session.clientIP} connected ${rDNS}`, session.id); | ||
events.emit('CONNECT', session); | ||
context.onConnect(session); | ||
Logger.info(`${session.rDNS || session.clientIP}:${socket.remotePort} connected over ${socket.remoteFamily}`, session.id); | ||
// Greet the client | ||
@@ -48,3 +55,2 @@ session.send(`${session.greeting} ESMTP`, 220); | ||
Logger.debug(`C: ${message}`, session.id); | ||
handleCommand(message, session); | ||
@@ -55,24 +61,30 @@ }); | ||
context.onDisconnect(session); | ||
Logger.info('Client disconnected', session.id) | ||
Logger.info(`${session.clientIP} disconnected`, session.id); | ||
activeSessions.delete(session); | ||
}); | ||
socket.on('error', (err) => { | ||
console.error(`Error occurred with ${session.clientIP}: ${err.message}`); | ||
Logger.error(`Error occurred with ${session.clientIP}: ${err.message}`, | ||
session.id); | ||
activeSessions.delete(session); | ||
}); | ||
}); | ||
server.on('terminate', () => { | ||
terminate(); | ||
// Handle termination signals outside the connection handler | ||
const handleTermination = () => { | ||
Logger.info('Server is shutting down...'); | ||
server.close(() => { | ||
Logger.info('Server closed, no longer accepting connections.'); | ||
}); | ||
const terminate = () => { | ||
server.close(); | ||
context.onDisconnect(session); | ||
socket.write('421 4.4.2 Server shutting down\r\n', () => { | ||
socket.end(); | ||
}); | ||
// Gracefully close all active sessions | ||
for (const session of activeSessions) { | ||
session.send(new Response('Server shutting down', 421, [4, 4, 2])); | ||
session.socket.end(); | ||
activeSessions.delete(session); | ||
} | ||
}; | ||
process.on('SIGINT', () => server.emit('terminate')); | ||
process.on('SIGTERM', () => server.emit('terminate')); | ||
}); | ||
process.on('SIGINT', handleTermination); | ||
process.on('SIGTERM', handleTermination); | ||
@@ -82,3 +94,4 @@ return server; // Return the server instance for further use | ||
export const Response = _Response | ||
export const Listen = events; | ||
export const Response = _Response; | ||
export const Listen = events; | ||
export const Log = Logger; |
import tls from 'tls'; | ||
import Logger from '../utils/logger.js'; | ||
import Logger from '../utils/Logger.js'; | ||
import context from './ServerContext.js'; | ||
@@ -4,0 +4,0 @@ import events from './Event.js'; |
import os from 'os'; | ||
import * as crypto from 'node:crypto'; | ||
import Logger from '../utils/logger.js'; | ||
import Logger from '../utils/Logger.js'; | ||
import Response from './Response.js'; | ||
import * as dns from 'node:dns'; | ||
@@ -10,3 +9,5 @@ export default class Session { | ||
this.socket = socket; | ||
this.clientIP = socket.remoteAddress; | ||
this.clientIP = socket.remoteAddress.startsWith('::ffff:') ? | ||
socket.remoteAddress.slice(7): | ||
socket.remoteAddress; | ||
this.greeting = os.hostname(); | ||
@@ -20,4 +21,2 @@ this.id = crypto.randomBytes(8).toString('hex'); | ||
dns.reverse(socket.remoteAddress, (_, r) => this.rDNS = r); | ||
// Define session states | ||
@@ -24,0 +23,0 @@ this.states = { |
65303
18
564