Skip to main content
This example shows how to create a basic SMTP server that accepts emails without authentication and saves them to disk.

Complete example

server.ts

How it works

1

Configure the server

Set authOptional: true to allow clients to send mail without authenticating.
2

Handle incoming data

The onData callback receives a ReadableStream<Uint8Array> containing the email message.
3

Process the stream

Use a for await...of loop to consume all chunks from the stream.
4

Save the email

Use Bun.write() to save the combined buffer to disk as a .eml file.
5

Complete the transaction

Call callback(null) to send a success response to the client.
You must fully consume the stream before calling the callback. Otherwise, the client will hang waiting for a response.

Testing the server

Send a test email using the mail command or telnet:
Then type:

Accessing envelope information

The session.envelope object contains metadata about the email:

Error handling

Reject the email with a custom error code:
Always consume the entire stream even if you plan to reject the message. Otherwise, the connection may hang.

Size limits

Set a maximum message size:

Next steps

Add authentication

Require users to authenticate before sending

Enable TLS

Encrypt connections with STARTTLS

Configuration reference

Explore all server options

Callbacks reference

Learn about all lifecycle callbacks