Skip to content

Inbox API

The Inbox class represents a test email inbox with methods for receiving and managing emails.

public class Inbox

An inbox has a unique email address that can receive emails. Emails are end-to-end encrypted and can only be decrypted by this inbox’s private key.

PropertyTypeDescription
emailAddressStringFull email address for this inbox
hashStringUnique identifier hash
expiresAtInstantWhen the inbox expires
serverSigPkStringServer’s signature public key
public String getEmailAddress()
public String getHash()
public Instant getExpiresAt()
public String getServerSigPk()

Lists all emails in the inbox with full content.

public List<Email> listEmails()

Returns: List of fully hydrated Email objects including body text, HTML, headers, attachments, links, and authentication results.

Throws:

  • ApiException - on API errors
  • NetworkException - on network connectivity issues
  • DecryptionException - on decryption failure

Example:

List<Email> emails = inbox.listEmails();
for (Email email : emails) {
System.out.println(email.getSubject());
System.out.println(email.getText()); // Full content available
}

Lists all emails returning only metadata (no body content). More efficient when you only need basic email information.

public List<EmailMetadata> listEmailsMetadataOnly()

Returns: List of EmailMetadata objects containing id, from, subject, receivedAt, and isRead.

Throws:

  • ApiException - on API errors
  • NetworkException - on network connectivity issues
  • DecryptionException - on decryption failure

Example:

List<EmailMetadata> emails = inbox.listEmailsMetadataOnly();
for (EmailMetadata meta : emails) {
System.out.println(meta.getId() + ": " + meta.getSubject());
if (!meta.isRead()) {
// Fetch full email only if needed
Email full = inbox.getEmail(meta.getId());
}
}

Gets a specific email by ID with full content.

public Email getEmail(String emailId)

Parameters:

  • emailId - Unique email identifier

Returns: Email with full content (body, attachments, headers, auth results)

Throws:

  • EmailNotFoundException - if email doesn’t exist
  • ApiException - on API errors
  • DecryptionException - on decryption failure

Example:

Email email = inbox.getEmail("email-123");
System.out.println(email.getText());
System.out.println(email.getHtml());

Gets the raw RFC822 MIME content.

public String getRawEmail(String emailId)

Parameters:

  • emailId - Unique email identifier

Returns: Raw email as string including all headers and MIME boundaries

Throws:

  • EmailNotFoundException - if email doesn’t exist
  • ApiException - on API errors

Example:

String raw = inbox.getRawEmail("email-123");
// Parse with javax.mail or similar library

Wait for any email to arrive.

public Email waitForEmail()
public Email waitForEmail(EmailFilter filter)
public Email waitForEmail(EmailFilter filter, Duration timeout)
public Email waitForEmail(WaitOptions options)

Parameters:

  • filter - Optional filter criteria (default: any email)
  • timeout - Maximum wait time (default: from config)
  • options - WaitOptions with filter, timeout, and poll interval

Returns: The matching email

Throws:

  • TimeoutException - if no matching email arrives within timeout

Examples:

// Wait for any email
Email email = inbox.waitForEmail();
// With filter
Email welcome = inbox.waitForEmail(EmailFilter.subjectContains("Welcome"));
// With timeout
Email order = inbox.waitForEmail(
EmailFilter.from("orders@"),
Duration.ofSeconds(60)
);
// With full options
Email verification = inbox.waitForEmail(
WaitOptions.builder()
.filter(EmailFilter.subjectContains("Verify"))
.timeout(Duration.ofSeconds(30))
.pollInterval(Duration.ofMillis(500))
.build()
);

Wait for multiple emails to arrive.

public List<Email> waitForEmailCount(int count)
public List<Email> waitForEmailCount(int count, Duration timeout)

Parameters:

  • count - Number of emails to wait for
  • timeout - Maximum wait time (default: from config)

Returns: List of received emails

Throws:

  • TimeoutException - if count not reached within timeout

Example:

// Wait for 3 emails
List<Email> emails = inbox.waitForEmailCount(3, Duration.ofSeconds(60));
assertEquals(3, emails.size());

Wait for email, returning null on timeout instead of throwing exception.

public Email awaitEmail()
public Email awaitEmail(EmailFilter filter)
public Email awaitEmail(EmailFilter filter, Duration timeout)

Parameters:

  • filter - Optional filter criteria (default: any email)
  • timeout - Maximum wait time (default: from config)

Returns: The matching email, or null if timeout

Example:

Email email = inbox.awaitEmail(
EmailFilter.subjectContains("Optional"),
Duration.ofSeconds(10)
);
if (email != null) {
// Process email
} else {
// No email received - continue without it
}

Subscribe to new email notifications.

public Subscription onNewEmail(Consumer<Email> callback)

Parameters:

  • callback - Consumer called when new emails arrive

Returns: Subscription handle to unsubscribe

Example:

Subscription sub = inbox.onNewEmail(email -> {
System.out.println("New email: " + email.getSubject());
email.markAsRead();
});
// Later, when done
sub.unsubscribe();

Marks an email as read.

public void markEmailAsRead(String emailId)

Parameters:

  • emailId - Email to mark

Throws:

  • EmailNotFoundException - if email doesn’t exist
  • ApiException - on API errors

Note: Prefer using email.markAsRead() on the Email object.

Deletes a specific email.

public void deleteEmail(String emailId)

Parameters:

  • emailId - Email to delete

Throws:

  • EmailNotFoundException - if email doesn’t exist
  • ApiException - on API errors

Note: Prefer using email.delete() on the Email object.

Deletes this inbox and all its emails.

public void delete()

Throws:

  • InboxNotFoundException - if inbox doesn’t exist
  • ApiException - on API errors

Example:

// Cleanup when done
inbox.delete();

Returns the synchronization status of this inbox.

public SyncStatus getSyncStatus()

Returns: SyncStatus with email count and hash (useful for checking if new emails arrived)

PropertyTypeDescription
emailCountintTotal number of emails in the inbox
emailsHashStringHash of all email IDs (changes when emails are added/removed)
lastUpdatedStringTimestamp of last sync

Example:

SyncStatus status = inbox.getSyncStatus();
System.out.println("Email count: " + status.getEmailCount());
System.out.println("Emails hash: " + status.getEmailsHash());
System.out.println("Last updated: " + status.getLastUpdated());

Exports this inbox’s credentials for later import.

public ExportedInbox export()

Returns: ExportedInbox containing credentials

Security Warning: Contains private keys - store securely!

Example:

ExportedInbox exported = inbox.export();
// Equivalent to: client.exportInbox(inbox)

Filter for matching emails based on various criteria.

public final class EmailFilter
EmailFilter.any() // Matches all emails
EmailFilter.subjectContains(String text) // Subject contains substring
EmailFilter.subjectMatches(Pattern regex) // Subject matches regex
EmailFilter.from(String sender) // From address contains substring
EmailFilter.fromMatches(Pattern regex) // From address matches regex
EmailFilter.matching(Predicate<Email> pred) // Custom predicate
EmailFilter filter1 = EmailFilter.subjectContains("Order");
EmailFilter filter2 = EmailFilter.from("shop@");
// Combine with AND
EmailFilter combined = filter1.and(filter2);

For complex filters:

EmailFilter filter = EmailFilter.builder()
.subject("Welcome") // Subject contains
.from("noreply@") // From contains
.subjectMatches("Order #\\d+") // Subject matches regex
.fromMatches(Pattern.compile(".*@example\\.com"))
.where(email -> email.getAttachments().size() > 0) // Custom predicate
.build();
MethodDescription
subject(String)Subject contains substring
subjectMatches(String)Subject matches regex string
subjectMatches(Pattern)Subject matches regex pattern
from(String)From address contains substring
fromMatches(String)From address matches regex string
fromMatches(Pattern)From address matches regex pattern
where(Predicate<Email>)Custom predicate
// Simple - subject contains
EmailFilter.subjectContains("Password Reset")
// Simple - from address
EmailFilter.from("[email protected]")
// Regex pattern
EmailFilter.subjectMatches(Pattern.compile("Invoice #\\d+"))
// Combined filters
EmailFilter.subjectContains("Order")
.and(EmailFilter.from("shop@"))
.and(EmailFilter.matching(e -> e.getAttachments().size() > 0))
// Custom predicate
EmailFilter.matching(email -> {
return email.getLinks().stream()
.anyMatch(link -> link.contains("/verify"));
})

Configuration for wait operations.

public final class WaitOptions
WaitOptions options = WaitOptions.builder()
.filter(EmailFilter.subjectContains("Reset"))
.timeout(Duration.ofSeconds(30))
.pollInterval(Duration.ofSeconds(1))
.build();
PropertyTypeDefaultDescription
filterEmailFilterany()Filter criteria
timeoutDurationfrom configMaximum wait time
pollIntervalDurationfrom configPoll frequency (polling strategy)

Lightweight representation of an email containing only metadata (no body content).

public class EmailMetadata
PropertyTypeDescription
idStringUnique email identifier
fromStringSender’s email address
subjectStringEmail subject line
receivedAtStringWhen the email was received
isReadbooleanWhether the email has been marked as read
public String getId()
public String getFrom()
public String getSubject()
public String getReceivedAt()
public boolean isRead()
List<EmailMetadata> emails = inbox.listEmailsMetadataOnly();
for (EmailMetadata meta : emails) {
System.out.printf("[%s] %s - %s%n",
meta.isRead() ? "READ" : "NEW",
meta.getFrom(),
meta.getSubject());
}

Handle for managing email subscriptions.

@FunctionalInterface
public interface Subscription {
void unsubscribe();
}
MethodDescription
unsubscribe()Stops the subscription

Example:

Subscription sub = inbox.onNewEmail(email -> {
processEmail(email);
});
// When done listening
sub.unsubscribe();
Inbox inbox = client.createInbox();
System.out.println("Send emails to: " + inbox.getEmailAddress());
// Wait for email
Email email = inbox.waitForEmail();
// Process
System.out.println("From: " + email.getFrom());
System.out.println("Subject: " + email.getSubject());
System.out.println("Body: " + email.getText());
// Cleanup
inbox.delete();
// Wait for password reset email
Email resetEmail = inbox.waitForEmail(
EmailFilter.subjectContains("Password Reset")
.and(EmailFilter.from("noreply@")),
Duration.ofSeconds(30)
);
// Extract reset link
String resetLink = resetEmail.getLinks().stream()
.filter(l -> l.contains("/reset"))
.findFirst()
.orElseThrow(() -> new AssertionError("No reset link found"));
System.out.println("Reset link: " + resetLink);
List<Email> received = new CopyOnWriteArrayList<>();
Subscription sub = inbox.onNewEmail(email -> {
System.out.println("Received: " + email.getSubject());
received.add(email);
if (email.getSubject().contains("Urgent")) {
notifyAdmin(email);
}
email.markAsRead();
});
// Trigger emails to be sent...
// Wait for expected emails
Thread.sleep(5000);
// Stop listening
sub.unsubscribe();
System.out.println("Received " + received.size() + " emails");
// Wait for 3 confirmation emails
List<Email> confirmations = inbox.waitForEmailCount(3, Duration.ofSeconds(60));
// Verify all received
assertEquals(3, confirmations.size());
// Process each
for (Email email : confirmations) {
assertTrue(email.getSubject().contains("Confirmation"));
processConfirmation(email);
}
// Check for optional notification
Email notification = inbox.awaitEmail(
EmailFilter.subjectContains("Notification"),
Duration.ofSeconds(5)
);
if (notification != null) {
System.out.println("Got notification: " + notification.getSubject());
} else {
System.out.println("No notification received (expected in some cases)");
}
// Export inbox for later use
ExportedInbox exported = inbox.export();
saveToFile(exported);
// Later, import in another session
ExportedInbox loaded = loadFromFile();
Inbox restoredInbox = client.importInbox(loaded);
// Continue using the inbox
Email email = restoredInbox.waitForEmail();

The Inbox class is thread-safe:

  • Multiple threads can call methods simultaneously
  • Email lists are safely copied
  • Subscriptions are thread-safe
  • Wait operations can be called from different threads