Documentation Index
Fetch the complete documentation index at: https://mintlify.com/puiusabin/bun-smtp/llms.txt
Use this file to discover all available pages before exploring further.
SMTPServer is an event emitter. Use server.on(), server.once(), and server.off() to manage listeners.
listening
Emitted when the server has bound to a port and is ready to accept connections.
server.on("listening", () => {
console.log("Server is ready");
});
await server.listen(2525);
The listening event fires after server.listen() successfully binds to the port.
close
Emitted when the server has fully shut down — all connections have closed and the port has been released.
server.on("close", () => {
console.log("Server stopped");
});
server.close();
This event only fires after all active connections have finished or been forcibly terminated.
error
Emitted on server-level errors (e.g. port already in use, TLS failures). Always attach an error listener to prevent unhandled rejection crashes.
server.on("error", (err) => {
console.error("SMTP server error:", err);
console.error("Response code:", err.responseCode);
console.error("Error code:", err.code);
});
Error Object
The error object may include:
SMTP status code (e.g. 421, 451, 550).
Error code string (e.g. "EADDRINUSE", "ECONNRESET").
meta
Record<string, unknown> | undefined
Additional context about the error.
Example
const server = new SMTPServer({ /* ... */ });
server.on("error", (err) => {
if (err.code === "EADDRINUSE") {
console.error("Port is already in use");
} else if (err.responseCode === 421) {
console.error("Service not available");
} else {
console.error("Unexpected error:", err);
}
});
server.listen(2525);
Always attach an error event listener. Unhandled errors will crash your process.
connect
Emitted when a new client connection is accepted (after onConnect succeeds).
server.on("connect", (info) => {
console.log(`New connection from ${info.remoteAddress}:${info.remotePort}`);
});
ConnectionInfo
Unique connection identifier.
Reverse-DNS hostname of the client.
Hostname from HELO/EHLO (populated after the opening command).
Example
const connections = new Map();
server.on("connect", (info) => {
connections.set(info.id, {
connectedAt: Date.now(),
remoteAddress: info.remoteAddress,
});
console.log(`Active connections: ${connections.size}`);
});
server.on("close", (session) => {
connections.delete(session.id);
});
Complete Example
import { SMTPServer } from "bun-smtp";
const server = new SMTPServer({
authOptional: true,
onData(stream, session, callback) {
stream.pipeTo(new WritableStream()).then(
() => callback(null),
callback
);
},
});
// Listen for server lifecycle events
server.on("listening", () => {
console.log("SMTP server is listening on port 2525");
});
server.on("connect", (info) => {
console.log(`[${info.id}] New connection from ${info.remoteAddress}`);
});
server.on("error", (err) => {
console.error("Server error:", err.message);
if (err.responseCode) {
console.error("SMTP code:", err.responseCode);
}
});
server.on("close", () => {
console.log("Server has shut down");
});
// Start the server
server.listen(2525);
// Graceful shutdown
process.on("SIGTERM", () => {
console.log("Received SIGTERM, shutting down gracefully...");
server.close(() => {
console.log("All connections closed");
process.exit(0);
});
});
Event Method Reference
See the SMTPServer reference for details on on(), once(), and off() methods.