Skip to main content
The session object contains information about the current SMTP connection and transaction. It is passed to all handler methods and persists throughout the connection lifetime.

Properties

Connection Information

id
String
required
Unique session identifier (32-character random string)
session.id // => "abc123def456..."
remoteAddress
String
Client IP address (IPv4 or IPv6, without ::ffff: prefix)
session.remoteAddress // => "192.0.2.1"
remotePort
Number
Client port number
session.remotePort // => 54321
localAddress
String
Server IP address
session.localAddress // => "192.0.2.100"
localPort
Number
Server port number
session.localPort // => 25
clientHostname
String
Client hostname from reverse DNS lookup or [IP] if unavailable
session.clientHostname // => "mail.example.com" or "[192.0.2.1]"
hostNameAppearsAs
String
Hostname provided by client in HELO/EHLO command
session.hostNameAppearsAs // => "client.example.com"
openingCommand
String
The opening command used: 'HELO', 'EHLO', or 'LHLO'
session.openingCommand // => "EHLO"

Security

secure
Boolean
Whether connection is using TLS
session.secure // => true
tlsOptions
Object
TLS cipher information (if connection is secure)
session.tlsOptions // => { name: "ECDHE-RSA-AES128-GCM-SHA256", version: "TLSv1.2" }
servername
String
SNI (Server Name Indication) hostname requested by client
session.servername // => "mail.example.com"

Authentication

user
Any
User data set by successful authentication in onAuth handler. Can be username, user ID, or any object.
session.user // => "john@example.com" or { id: 123, username: "john" }

Transaction

transaction
Number
Transaction counter for this connection (incremented after each DATA command)
session.transaction // => 1
transmissionType
String
Connection type identifier
  • SMTP - Basic SMTP (HELO)
  • ESMTP - Extended SMTP (EHLO)
  • LMTP - Local Mail Transfer Protocol (LHLO)
  • ESMTPS - ESMTP over TLS
  • ESMTPSA - ESMTP over TLS with authentication
session.transmissionType // => "ESMTPSA"

Envelope

envelope
Object
Current mail transaction envelope

Proxy Information

xClient
Map
Data from XCLIENT command (if useXClient is enabled)
session.xClient.get('ADDR') // => "10.0.0.1"
session.xClient.get('NAME') // => "proxy.example.com"
xForward
Map
Data from XFORWARD command (if useXForward is enabled)
session.xForward.get('ADDR') // => "192.0.2.50"

Error Information

error
String
Last error message sent to client (if any)
session.error // => "550 5.1.1 Mailbox does not exist"

Usage Examples

Accessing Session in Handlers

const server = new SMTPServer({
  onAuth(auth, session, callback) {
    console.log('Auth attempt from:', session.remoteAddress);
    console.log('Connection type:', session.transmissionType);
    callback(null, { user: auth.username });
  },
  
  onMailFrom(address, session, callback) {
    console.log('User:', session.user);
    console.log('Sender:', address.address);
    callback();
  },
  
  onRcptTo(address, session, callback) {
    console.log('Sender was:', session.envelope.mailFrom.address);
    console.log('Adding recipient:', address.address);
    callback();
  },
  
  onData(stream, session, callback) {
    console.log('Message from:', session.envelope.mailFrom.address);
    console.log('Message to:', session.envelope.rcptTo.map(r => r.address));
    console.log('Body type:', session.envelope.bodyType);
    console.log('Transaction #:', session.transaction);
    
    stream.on('end', () => callback());
  }
});

Storing Custom Data

You can add custom properties to the session object:
const server = new SMTPServer({
  onAuth(auth, session, callback) {
    // Store custom data
    session.customData = {
      loginTime: new Date(),
      privileges: ['send', 'receive']
    };
    callback(null, { user: auth.username });
  },
  
  onMailFrom(address, session, callback) {
    // Access custom data
    if (!session.customData.privileges.includes('send')) {
      return callback(new Error('No send privilege'));
    }
    callback();
  }
});

Checking Connection Security

const server = new SMTPServer({
  onMailFrom(address, session, callback) {
    if (!session.secure) {
      const err = new Error('TLS required');
      err.responseCode = 530;
      return callback(err);
    }
    
    console.log('TLS cipher:', session.tlsOptions.name);
    callback();
  }
});

Working with Envelope Data

const server = new SMTPServer({
  onData(stream, session, callback) {
    const envelope = session.envelope;
    const metadata = {
      from: envelope.mailFrom.address,
      to: envelope.rcptTo.map(r => r.address),
      size: envelope.mailFrom.args.SIZE,
      bodyType: envelope.bodyType,
      utf8: envelope.smtpUtf8,
      secure: session.secure,
      authenticated: !!session.user,
      connectionId: session.id,
      remoteIp: session.remoteAddress,
      timestamp: new Date()
    };
    
    // Save metadata with message
    saveMessage(stream, metadata, callback);
  }
});

Session Lifecycle

  1. Connection: Session is created with connection info (id, remoteAddress, etc.)
  2. Greeting: clientHostname is resolved
  3. TLS (optional): secure, tlsOptions, servername are set
  4. HELO/EHLO: openingCommand, hostNameAppearsAs are set
  5. AUTH (optional): user is set on successful authentication
  6. MAIL FROM: envelope.mailFrom is set
  7. RCPT TO: Recipients are added to envelope.rcptTo
  8. DATA: Message is processed
  9. RSET/QUIT: Envelope is reset (RSET) or connection closes (QUIT)
The session object persists across multiple transactions on the same connection (multiple MAIL-RCPT-DATA sequences).

See Also

Build docs developers (and LLMs) love