Managing Inboxes
This guide covers common inbox operations including creation, email management, and cleanup patterns for testing.
Creating Inboxes
Section titled “Creating Inboxes”Basic Creation
Section titled “Basic Creation”ClientConfig config = ClientConfig.builder() .apiKey(apiKey) .baseUrl(baseUrl) .build();VaultSandboxClient client = VaultSandboxClient.create(config);Inbox inbox = client.createInbox();
System.out.println("Send emails to: " + inbox.getEmailAddress());System.out.println("Expires at: " + inbox.getExpiresAt());With Custom TTL
Section titled “With Custom TTL”Inbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofHours(2)) .build());With Specific Domain or Address
Section titled “With Specific Domain or Address”// Request specific domainInbox inbox = client.createInbox( CreateInboxOptions.builder() .emailAddress("yourdomain.com") .build());
// Request specific full addressInbox inbox = client.createInbox( CreateInboxOptions.builder() .build());Multiple Options
Section titled “Multiple Options”Inbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofMinutes(30)) .build());Inbox Properties
Section titled “Inbox Properties”| Property | Type | Description |
|---|---|---|
emailAddress | String | The inbox email address |
expiresAt | Instant | When the inbox expires |
Inbox inbox = client.createInbox();
Instant expires = inbox.getExpiresAt(); // 2024-01-15T12:00:00ZListing Emails
Section titled “Listing Emails”Get All Emails
Section titled “Get All Emails”List<Email> emails = inbox.listEmails();
for (Email email : emails) { System.out.println("From: " + email.getFrom()); System.out.println("Subject: " + email.getSubject()); System.out.println("Received: " + email.getReceivedAt());}With Stream API
Section titled “With Stream API”inbox.listEmails().stream() .filter(e -> e.getSubject().contains("Important")) .forEach(this::processEmail);Filtering Emails
Section titled “Filtering Emails”Using EmailFilter with Streams
Section titled “Using EmailFilter with Streams”// Filter by subjectList<Email> filtered = inbox.listEmails().stream() .filter(e -> e.getSubject().contains("Welcome")) .collect(Collectors.toList());
// Filter by senderList<Email> fromSupport = inbox.listEmails().stream() .filter(e -> e.getFrom().contains("support@")) .collect(Collectors.toList());Using EmailFilter Predicates
Section titled “Using EmailFilter Predicates”// Create reusable filtersEmailFilter welcomeFilter = EmailFilter.subjectContains("Welcome");EmailFilter supportFilter = EmailFilter.from("support@");
// Combine filtersEmailFilter combined = welcomeFilter.and(supportFilter);
// Apply to listList<Email> matching = inbox.listEmails().stream() .filter(combined::matches) .collect(Collectors.toList());Custom Predicates
Section titled “Custom Predicates”// Filter by attachment countList<Email> withAttachments = inbox.listEmails().stream() .filter(e -> !e.getAttachments().isEmpty()) .collect(Collectors.toList());
// Filter by multiple criteriaList<Email> recent = inbox.listEmails().stream() .filter(e -> e.getReceivedAt().isAfter(Instant.now().minus(Duration.ofMinutes(5)))) .filter(e -> !e.isRead()) .collect(Collectors.toList());Sorting Emails
Section titled “Sorting Emails”By Received Date
Section titled “By Received Date”// Newest firstList<Email> sorted = inbox.listEmails().stream() .sorted(Comparator.comparing(Email::getReceivedAt).reversed()) .collect(Collectors.toList());
// Oldest firstList<Email> oldest = inbox.listEmails().stream() .sorted(Comparator.comparing(Email::getReceivedAt)) .collect(Collectors.toList());By Subject
Section titled “By Subject”List<Email> bySubject = inbox.listEmails().stream() .sorted(Comparator.comparing(Email::getSubject, Comparator.nullsLast(String::compareToIgnoreCase))) .collect(Collectors.toList());Getting Specific Emails
Section titled “Getting Specific Emails”Email email = inbox.getEmail(emailId);First Email
Section titled “First Email”Email first = inbox.listEmails().stream() .findFirst() .orElseThrow(() -> new AssertionError("No emails found"));Latest Email
Section titled “Latest Email”Email latest = inbox.listEmails().stream() .max(Comparator.comparing(Email::getReceivedAt)) .orElseThrow(() -> new AssertionError("No emails found"));First Matching Filter
Section titled “First Matching Filter”Email welcome = inbox.listEmails().stream() .filter(e -> e.getSubject().contains("Welcome")) .findFirst() .orElseThrow(() -> new AssertionError("Welcome email not found"));Managing Email State
Section titled “Managing Email State”Mark as Read
Section titled “Mark as Read”// Via inboxinbox.markEmailAsRead(emailId);
// Via email objectemail.markAsRead();Check Read Status
Section titled “Check Read Status”List<Email> unread = inbox.listEmails().stream() .filter(e -> !e.isRead()) .collect(Collectors.toList());
System.out.println("Unread emails: " + unread.size());Deleting Emails
Section titled “Deleting Emails”Single Email
Section titled “Single Email”// By IDinbox.deleteEmail(emailId);
// Via email objectemail.delete();Multiple Emails
Section titled “Multiple Emails”// Delete all read emailsinbox.listEmails().stream() .filter(Email::isRead) .forEach(Email::delete);By Criteria
Section titled “By Criteria”// Delete old emailsInstant cutoff = Instant.now().minus(Duration.ofHours(1));
inbox.listEmails().stream() .filter(e -> e.getReceivedAt().isBefore(cutoff)) .forEach(Email::delete);All Emails in Inbox
Section titled “All Emails in Inbox”inbox.listEmails().forEach(Email::delete);Deleting Inboxes
Section titled “Deleting Inboxes”Single Inbox
Section titled “Single Inbox”// Via clientclient.deleteInbox(inbox.getEmailAddress());
// Via inbox objectinbox.delete();All Inboxes
Section titled “All Inboxes”int deletedCount = client.deleteAllInboxes();System.out.println("Deleted " + deletedCount + " inbox(es)");Bulk Operations
Section titled “Bulk Operations”Create Multiple Inboxes
Section titled “Create Multiple Inboxes”List<Inbox> inboxes = IntStream.range(0, 10) .mapToObj(i -> client.createInbox()) .collect(Collectors.toList());
// Use inboxes...
// Clean upinboxes.forEach(Inbox::delete);Parallel Processing
Section titled “Parallel Processing”List<Inbox> inboxes = IntStream.range(0, 5) .mapToObj(i -> client.createInbox()) .collect(Collectors.toList());
// Process emails in parallelinboxes.parallelStream() .flatMap(inbox -> inbox.listEmails().stream()) .filter(e -> e.getSubject().contains("Alert")) .forEach(this::processAlert);Testing Patterns
Section titled “Testing Patterns”JUnit 5 Setup/Teardown
Section titled “JUnit 5 Setup/Teardown”class EmailTest { private VaultSandboxClient client; private Inbox inbox;
@BeforeEach void setUp() { ClientConfig config = ClientConfig.builder() .apiKey(System.getenv("VAULTSANDBOX_API_KEY")) .baseUrl(System.getenv("VAULTSANDBOX_URL")) .build(); client = VaultSandboxClient.create(config); inbox = client.createInbox(); }
@AfterEach void tearDown() { if (inbox != null) { try { inbox.delete(); } catch (Exception ignored) {} } if (client != null) { client.close(); } }
@Test void shouldReceiveWelcomeEmail() { // Trigger email signUpUser(inbox.getEmailAddress());
// Wait and verify Email email = inbox.waitForEmail( EmailFilter.subjectContains("Welcome"), Duration.ofSeconds(30) );
}}Try-With-Resources Pattern
Section titled “Try-With-Resources Pattern”@Testvoid shouldProcessEmails() { ClientConfig config = ClientConfig.builder() .apiKey(apiKey) .baseUrl(baseUrl) .build(); try (VaultSandboxClient client = VaultSandboxClient.create(config)) { Inbox inbox = client.createInbox();
try { // Trigger and receive emails sendTestEmail(inbox.getEmailAddress()); Email email = inbox.waitForEmail(Duration.ofSeconds(30)); assertThat(email).isNotNull(); } finally { inbox.delete(); } }}Shared Inbox Pattern
Section titled “Shared Inbox Pattern”For tests that share a single inbox:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)class SharedInboxTest { private VaultSandboxClient client; private Inbox inbox;
@BeforeAll void setUpClass() { ClientConfig config = ClientConfig.builder() .apiKey(System.getenv("VAULTSANDBOX_API_KEY")) .baseUrl(System.getenv("VAULTSANDBOX_URL")) .build(); client = VaultSandboxClient.create(config); inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofHours(1)) .build() ); }
@AfterAll void tearDownClass() { if (client != null) { client.deleteAllInboxes(); client.close(); } }
@BeforeEach void clearEmails() { // Clear emails between tests inbox.listEmails().forEach(Email::delete); }
@Test void testOne() { // Uses shared inbox }
@Test void testTwo() { // Uses same shared inbox }}Inbox Pool Pattern
Section titled “Inbox Pool Pattern”For high-throughput testing:
class InboxPool { private final Queue<Inbox> available = new ConcurrentLinkedQueue<>(); private final VaultSandboxClient client;
public InboxPool(VaultSandboxClient client) { this.client = client; }
public Inbox acquire() { Inbox inbox = available.poll(); if (inbox != null) { return inbox; } return client.createInbox(); }
public void release(Inbox inbox) { // Clear emails and return to pool try { inbox.listEmails().forEach(Email::delete); available.offer(inbox); } catch (Exception e) { // Inbox may have expired, don't return to pool } }
public void shutdown() { Inbox inbox; while ((inbox = available.poll()) != null) { try { inbox.delete(); } catch (Exception ignored) {} } }}Usage:
class PooledInboxTest { private static InboxPool pool; private Inbox inbox;
@BeforeAll static void setUpPool() { ClientConfig config = ClientConfig.builder() .apiKey(apiKey) .baseUrl(baseUrl) .build(); VaultSandboxClient client = VaultSandboxClient.create(config); pool = new InboxPool(client); }
@AfterAll static void tearDownPool() { pool.shutdown(); }
@BeforeEach void acquireInbox() { inbox = pool.acquire(); }
@AfterEach void releaseInbox() { pool.release(inbox); }
@Test void testWithPooledInbox() { // Use inbox... }}Test Base Class
Section titled “Test Base Class”abstract class EmailTestBase { protected VaultSandboxClient client; protected Inbox inbox;
@BeforeEach void setUpInbox() { ClientConfig config = ClientConfig.builder() .apiKey(System.getenv("VAULTSANDBOX_API_KEY")) .baseUrl(System.getenv("VAULTSANDBOX_URL")) .build(); client = VaultSandboxClient.create(config); inbox = client.createInbox(); }
@AfterEach void tearDownInbox() { if (inbox != null) { try { inbox.delete(); } catch (Exception ignored) {} } if (client != null) { client.close(); } }
protected Email waitForEmail(String subjectContains) { return inbox.waitForEmail( EmailFilter.subjectContains(subjectContains), Duration.ofSeconds(30) ); }}
class WelcomeEmailTest extends EmailTestBase { @Test void shouldSendWelcomeEmail() { signUp(inbox.getEmailAddress()); Email email = waitForEmail("Welcome"); assertThat(email).isNotNull(); }}Error Handling
Section titled “Error Handling”Common Exceptions
Section titled “Common Exceptions”try { Inbox inbox = client.createInbox(); Email email = inbox.waitForEmail(Duration.ofSeconds(10));} catch (ApiException e) { System.err.println("API error: " + e.getStatusCode() + " - " + e.getMessage());} catch (NetworkException e) { System.err.println("Network error: " + e.getMessage());} catch (TimeoutException e) { System.err.println("Timeout waiting for email");} catch (VaultSandboxException e) { System.err.println("General error: " + e.getMessage());}Inbox Not Found
Section titled “Inbox Not Found”try {} catch (InboxNotFoundException e) { System.err.println("Inbox does not exist: " + e.getMessage());}Graceful Cleanup
Section titled “Graceful Cleanup”void cleanupSafely(Inbox inbox) { if (inbox == null) return;
try { inbox.delete(); } catch (InboxNotFoundException e) { // Already deleted, ignore } catch (Exception e) { System.err.println("Failed to delete inbox: " + e.getMessage()); }}Retrieving Inboxes
Section titled “Retrieving Inboxes”From Client Registry
Section titled “From Client Registry”// Create inboxInbox inbox = client.createInbox();String address = inbox.getEmailAddress();
// Later, retrieve from same client instanceInbox sameInbox = client.getInbox(address);Best Practices
Section titled “Best Practices”- Always clean up inboxes after tests - Use
@AfterEachor try-finally blocks - Use appropriate TTLs - Set shorter TTLs for automated tests, longer for manual testing
- Create fresh inboxes for isolation - Avoid sharing inboxes between unrelated tests
- Handle rate limits - Implement retries for bulk operations
- Close the client - Call
client.close()when done to release resources
// Good: Fresh inbox per test@BeforeEachvoid setUp() { inbox = client.createInbox();}
@AfterEachvoid tearDown() { inbox.delete();}
// Good: Short TTL for automated testsInbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofMinutes(15)) .build());
// Good: Use try-with-resources for clientClientConfig config = ClientConfig.builder() .apiKey(apiKey) .baseUrl(baseUrl) .build();try (VaultSandboxClient client = VaultSandboxClient.create(config)) { // Use client...}Next Steps
Section titled “Next Steps”- Waiting for Emails - Delivery strategies and filters
- Import & Export - Persist inbox credentials
- API Reference: Inbox - Complete Inbox API documentation