Skip to main content

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:
message
string
Error message.
responseCode
number | undefined
SMTP status code (e.g. 421, 451, 550).
code
string | undefined
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

id
string
Unique connection identifier.
localAddress
string
Server IP address.
localPort
number
Server port.
remoteAddress
string
Client IP address.
remotePort
number
Client port.
clientHostname
string
Reverse-DNS hostname of the client.
hostNameAppearsAs
string
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.