Note
This project has been archived in April 2024 and is no longer maintained.
Embedded SMTP, POP3, and IMAP servers for integration tests in Java projects.
You have code which is sending and/or receiving emails using SMTP, POP3, or IMAP? You want to test your code against a "real" mail server in integration tests?
Run embedded in-memory mail servers as part of your integration tests and allow your test code to connect to them.
vtestmail-core
is the core module of the vtestmail
project.
It contains the implementations of the SMTP, POP3, and IMAP server.
It does not have any dependencies on other libraries.
- Java 11 or greater. Tested with Java 11, Java 17, and Java 21 in February 2024.
<dependency>
<groupId>net.markwalder</groupId>
<artifactId>vtestmail-core</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
testImplementation("net.markwalder:vtestmail-core:1.0.0")
Create a MailboxStore
and add mailboxes to save emails received by the SMTP server, and to hold emails for the POP3 or IMAP server.
MailboxStore store = new MailboxStore();
store.createMailbox("alice", "password123", "alice@localhost");
store.createMailbox("bob", "password321", "bob@localhost");
// ...
Username and password are used for authentication. The email address is used to find a mailbox for incoming emails. You can use any domain name in email addresses. Emails sent to non-existing mailboxes are silently discarded.
To start an SMTP server using the given mailbox store, bound to localhost and listening on a free port:
SmtpServer server = new SmtpServer(store);
server.start();
int port = server.getPort();
// ... use server in integration tests ...
server.stop();
To start a POP3 server using the given mailbox store, bound to localhost and listening on a free port:
Pop3Server server = new Pop3Server(store);
server.start();
int port = server.getPort();
// ... use server in integration tests ...
server.stop();
To start a IMAP server using the given mailbox store, bound to localhost and listening on a free port:
ImapServer server = new ImapServer(store);
server.start();
int port = server.getPort();
// ... use server in integration tests ...
server.stop();
You can also start multiple servers and use the same store for all of them.
Most of the following examples can be used with all mail server types (SMTP, POP3, and IMAP). For simplicity, the examples only use the SMTP server.
TODO
TODO
By default, all servers ask the operating system for a random free port when they are started.
To use a specific port, call server.setPort(int port)
before starting the server:
SmtpServer server = new SmtpServer(store);
server.setPort(2525); // run SMTP server on port 2525
server.start();
// ...
TODO
For implicit SSL/TLS where the server only accepts SSL/TLS connections (also known as SMTPS, IMAPS, or POP3S), call server.setUseSSL(true)
before starting the server:
SmtpServer server = new SmtpServer(store);
server.setUseSSL(true); // enable implicit SSL/TLS
server.start();
// ...
Clients can also switch to an SSL/TLS connection at runtime (also known as "opportunistic TLS") by sending the STARTTLS
(SMTP and IMAP) or STLS
(POP3) command.
To disable support for opportunistic TLS, disable the required command by calling server.setCommandEnabled("STARTTLS", false)
or server.setCommandEnabled("STLS", false)
.
The server will use a self-signed certificate for the domain "localhost" with a 2048-bit RSA key, valid until July 31st 2032.
The certificate and the RSA key pair are loaded from the classpath resource vtestmail.pfx
.
By default, the server uses TLS version 1.2 (TLSv1.2
) for SSL/TLS connections.
To use a different protocol, call server.setSSLProtocol(String protocol)
before starting the server:
SmtpServer server = new SmtpServer(store);
server.setSSLProtocol("TLSv1.1"); // use TLS version 1.1
server.start();
// ...
Supported protocols:
TLSv1.3
- TLS version 1.3TLSv1.2
- TLS version 1.2TLSv1.1
- TLS version 1.1TLSv1
- TLS version 1.0SSLv3
- SSL version 3
Note that the availability of a specific protocol also depends on the Java version and runtime.
TODO
TODO
TODO
TODO
Structure: MailboxStore
-> Mailbox
-> MailboxFolder
-> MailboxMessage
TODO
TODO
TODO
TODO
TODO
TODO
This project uses the Java Logging API (JUL) for logging.
The two main loggers are:
net.markwalder.vtestmail.core.MailServer
- logs startup and shutdown of servers, incoming connections, and unexpected I/O errors.net.markwalder.vtestmail.core.MailClient
- logs SMTP, IMAP, and POP3 commands (prefixed with "Client:") and responses (prefixed with "Server:").
SMTP standards:
- RFC 5321 - Simple Mail Transfer Protocol
- RFC 4954 - SMTP Service Extension for Authentication
- RFC 3207 - SMTP Service Extension for Secure SMTP over Transport Layer Security
- RFC 3463 - Enhanced Mail System Status Codes
Supported commands:
HELO
andEHLO
STARTTLS
AUTH
VRFY
MAIL FROM
RCPT TO
DATA
NOOP
RSET
QUIT
POP3 standards:
- RFC 1939 - Post Office Protocol - Version 3
- RFC 2195 - IMAP/POP AUTHorize Extension for Simple Challenge/Response
- RFC 2449 - POP3 Extension Mechanism
- RFC 2595 - Using TLS with IMAP, POP3 and ACAP
- RFC 5034 - The Post Office Protocol (POP3) Simple Authentication and Security Layer (SASL) Authentication Mechanism
Supported commands:
CAPA
STLS
AUTH
,APOP
,USER
andPASS
STAT
LIST
UIDL
TOP
RETR
DELE
NOOP
RSET
QUIT
IMAP standards:
Supported commands (work in progress):
CAPABILITY
STARTTLS
LOGIN
andAUTHENTICATE
ENABLE
SELECT
,EXAMINE
,UNSELECT
, andCLOSE
CREATE
,DELETE
, andRENAME
SUBSCRIBE
andUNSUBSCRIBE
NAMESPACE
andLIST
STATUS
SEARCH
FETCH
STORE
APPEND
COPY
MOVE
UID
EXPUNGE
IDLE
NOOP
LOGOUT
- Only one SMTP client can connect to the SMTP server at a time.
- The format of email addresses and messages is not validated.
- Messages are not queued or relayed to another SMTP server.
- Messages are either delivered to a local mailbox, or silently discarded.
- Only one POP3 client can connect to the POP3 server at a time.
- The mailbox is not exclusively locked by the server.
- The format of email messages is not validated.
- Only one IMAP client can connect to the IMAP server at a time.
- Only IMAP4rev2 (RFC 9051) is supported.
- The format of email messages is not validated.
- It is not possible to enable two or more SSL/TLS protocols.
- It is not possible to enable or disable specific cipher suites. They are automatically selected by the Java runtime.
- Stephan Markwalder - @smarkwal