Inboxes
Inboxes are the core concept in VaultSandbox. Each inbox is an isolated, encrypted email destination with its own unique address and encryption keys.
What is an Inbox?
Section titled “What is an Inbox?”An inbox is a temporary, encrypted email destination that:
- Has a unique email address (e.g.,
[email protected]) - Uses client-side encryption (ML-KEM-768 keypair)
- Expires automatically after a configurable time-to-live (TTL)
- Is isolated from other inboxes
- Stores emails in memory on the gateway
Creating Inboxes
Section titled “Creating Inboxes”Basic Creation
Section titled “Basic Creation”import com.vaultsandbox.client.VaultSandboxClient;import com.vaultsandbox.client.ClientConfig;import com.vaultsandbox.client.Inbox;
ClientConfig config = ClientConfig.builder() .apiKey("your-api-key") .baseUrl("https://gateway.example.com") .build();
VaultSandboxClient client = VaultSandboxClient.create(config);
Inbox inbox = client.createInbox();
System.out.println(inbox.getHash()); // "Rr02MLnP7F0pRVC..."System.out.println(inbox.getExpiresAt()); // InstantWith Options
Section titled “With Options”import com.vaultsandbox.client.CreateInboxOptions;import java.time.Duration;
Inbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofHours(1)) .build());Note: Requesting a specific email address may fail if it’s already in use. The server will return an error.
Inbox Properties
Section titled “Inbox Properties”emailAddress
Section titled “emailAddress”Type: String
The full email address for this inbox.
System.out.println(inbox.getEmailAddress());// "[email protected]"Send emails to this address to have them appear in the inbox.
hash (inboxHash)
Section titled “hash (inboxHash)”Type: String
A unique cryptographic hash identifier for the inbox. Used internally for encryption and identification.
System.out.println(inbox.getHash());// "Rr02MLnP7F0pRVC6QdcpSIeyklqu3PDkYglvsfN7Oss"Note: This is not the same as the local part of the email address. The email address local part (e.g., a1b2c3d4 in [email protected]) is different from the inboxHash.
expiresAt
Section titled “expiresAt”Type: Instant
When the inbox will automatically expire and be deleted.
System.out.println(inbox.getExpiresAt());// 2024-01-16T12:00:00Z
// Check if inbox is expiring soonDuration untilExpiry = Duration.between(Instant.now(), inbox.getExpiresAt());System.out.printf("Expires in %.1f hours%n", untilExpiry.toHours());Inbox Lifecycle
Section titled “Inbox Lifecycle”┌─────────────────────────────────────────────────────────┐│ Inbox Lifecycle │└─────────────────────────────────────────────────────────┘
1. Creation client.createInbox() → Inbox object ↓ - Keypair generated client-side - Public key sent to server - Unique email address assigned - TTL timer starts
2. Active ↓ - Receive emails - List/read emails - Wait for emails - Monitor for new emails
3. Expiration (TTL reached) or Manual Deletion ↓ inbox.delete() or TTL expires - All emails deleted - Inbox address freed - Keypair destroyedWorking with Inboxes
Section titled “Working with Inboxes”Listing Emails
Section titled “Listing Emails”List<Email> emails = inbox.listEmails();
System.out.printf("%d emails in inbox%n", emails.size());for (Email email : emails) { System.out.printf("%s: %s%n", email.getFrom(), email.getSubject());}Getting a Specific Email
Section titled “Getting a Specific Email”Email email = inbox.getEmail("email-id-123");
System.out.println(email.getSubject());System.out.println(email.getText());Waiting for Emails
Section titled “Waiting for Emails”// Wait for any email (uses default timeout)Email email = inbox.waitForEmail();
// Wait with custom timeoutEmail email = inbox.waitForEmail(EmailFilter.any(), Duration.ofSeconds(30));
// Wait for specific emailEmail email = inbox.waitForEmail( EmailFilter.subjectContains("Password Reset"), Duration.ofSeconds(30));
// Wait with filter builderEmail email = inbox.waitForEmail( EmailFilter.builder() .subject("Welcome") .build(), Duration.ofSeconds(30));Wait Methods vs Await Methods
Section titled “Wait Methods vs Await Methods”The waitForEmail methods throw TimeoutException if no email arrives:
try { Email email = inbox.waitForEmail(Duration.ofSeconds(10));} catch (TimeoutException e) { System.err.println("No email received within timeout");}The awaitEmail methods return null on timeout:
Email email = inbox.awaitEmail(Duration.ofSeconds(10));if (email == null) { System.err.println("No email received within timeout");}Waiting for Multiple Emails
Section titled “Waiting for Multiple Emails”// Wait for exactly 3 emailsList<Email> emails = inbox.waitForEmailCount(3, Duration.ofSeconds(30));
System.out.printf("Received %d emails%n", emails.size());Subscribing to New Emails
Section titled “Subscribing to New Emails”Subscription subscription = inbox.onNewEmail(email -> { System.out.println("New email: " + email.getSubject());});
// Later, unsubscribesubscription.unsubscribe();Deleting Emails
Section titled “Deleting Emails”// Delete specific email by IDinbox.deleteEmail("email-id-123");
// Or via email objectemail.delete();Deleting Inbox
Section titled “Deleting Inbox”// Delete inbox and all its emailsinbox.delete();Inbox Isolation
Section titled “Inbox Isolation”Each inbox is completely isolated:
Inbox inbox1 = client.createInbox();Inbox inbox2 = client.createInbox();
// inbox1 cannot access inbox2's emails// inbox2 cannot access inbox1's emails
// Each has its own:// - Email address// - Encryption keys// - Email storage// - Expiration timeTime-to-Live (TTL)
Section titled “Time-to-Live (TTL)”Inboxes automatically expire after their TTL.
Default TTL
Section titled “Default TTL”// Uses server's default TTL (typically 24 hours)Inbox inbox = client.createInbox();Custom TTL
Section titled “Custom TTL”// Expire after 1 hourInbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofHours(1)) .build());
// Expire after 10 minutes (useful for quick tests)Inbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofMinutes(10)) .build());
// Expire after 7 daysInbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofDays(7)) .build());Checking Expiration
Section titled “Checking Expiration”Duration timeLeft = Duration.between(Instant.now(), inbox.getExpiresAt());long minutesLeft = timeLeft.toMinutes();
if (minutesLeft < 5) { System.err.println("Inbox expiring soon!");}Import and Export
Section titled “Import and Export”Inboxes can be exported and imported for:
- Test reproducibility
- Sharing between environments
- Backup and restore
Export
Section titled “Export”// Export via inboxExportedInbox exported = inbox.export();
// Or via clientExportedInbox exported = client.exportInbox(inbox);
// Export to fileclient.exportInboxToFile(inbox, Path.of("inbox.json"));Import
Section titled “Import”// Import from ExportedInbox objectInbox inbox = client.importInbox(exported);
// Import from fileInbox inbox = client.importInboxFromFile(Path.of("inbox.json"));
// Inbox restored with all encryption keysSystem.out.println(inbox.getEmailAddress());Security Warning: Exported data contains private keys. Treat as sensitive and handle securely.
Best Practices
Section titled “Best Practices”CI/CD Pipelines
Section titled “CI/CD Pipelines”Short TTL for fast cleanup:
Inbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofHours(1)) .build());Always clean up:
Inbox inbox = null;try { inbox = client.createInbox(); // Run tests} finally { if (inbox != null) { inbox.delete(); }}Manual Testing
Section titled “Manual Testing”Longer TTL for convenience:
Inbox inbox = client.createInbox( CreateInboxOptions.builder() .ttl(Duration.ofHours(24)) .build());Export for reuse:
// Export after creatingclient.exportInboxToFile(inbox, Path.of("test-inbox.json"));
// Reuse in later sessionsInbox inbox = client.importInboxFromFile(Path.of("test-inbox.json"));Common Patterns
Section titled “Common Patterns”Dedicated Test Inbox (JUnit 5)
Section titled “Dedicated Test Inbox (JUnit 5)”class EmailTest { private static VaultSandboxClient client; private Inbox inbox;
@BeforeAll static void initClient() { ClientConfig config = ClientConfig.builder() .apiKey(System.getenv("VAULTSANDBOX_API_KEY")) .baseUrl(System.getenv("VAULTSANDBOX_URL")) .build(); client = VaultSandboxClient.create(config); }
@BeforeEach void setUp() { inbox = client.createInbox(); }
@AfterEach void tearDown() { if (inbox != null) { inbox.delete(); } }
@Test void shouldReceivePasswordResetEmail() { triggerPasswordReset(inbox.getEmailAddress());
Email email = inbox.waitForEmail( EmailFilter.subjectContains("Password Reset"), Duration.ofSeconds(10) );
assertThat(email.getSubject()).contains("Password Reset"); }}Multiple Inboxes
Section titled “Multiple Inboxes”Inbox user1Inbox = client.createInbox();Inbox user2Inbox = client.createInbox();Inbox adminInbox = client.createInbox();
// Each inbox receives emails independentlysendWelcomeEmail(user1Inbox.getEmailAddress());sendWelcomeEmail(user2Inbox.getEmailAddress());sendAdminReport(adminInbox.getEmailAddress());Creating Multiple Inboxes
Section titled “Creating Multiple Inboxes”List<Inbox> inboxes = IntStream.range(0, 5) .mapToObj(i -> client.createInbox()) .collect(Collectors.toList());
// Clean up allinboxes.forEach(Inbox::delete);Inbox Pool
Section titled “Inbox Pool”class InboxPool implements Closeable { private final VaultSandboxClient client; private final Queue<Inbox> pool = new ConcurrentLinkedQueue<>(); private final int size;
public InboxPool(VaultSandboxClient client, int size) { this.client = client; this.size = size; }
public void initialize() { for (int i = 0; i < size; i++) { pool.add(client.createInbox()); } }
public Inbox acquire() { Inbox inbox = pool.poll(); if (inbox == null) { return client.createInbox(); } return inbox; }
public void release(Inbox inbox) { pool.add(inbox); }
@Override public void close() { pool.forEach(Inbox::delete); }}Troubleshooting
Section titled “Troubleshooting”Inbox Not Receiving Emails
Section titled “Inbox Not Receiving Emails”Check:
- Email is sent to correct address
- Inbox hasn’t expired
- DNS/MX records configured correctly
- SMTP connection successful
// Verify inbox still existstry { List<Email> emails = inbox.listEmails(); // Will error if inbox expired System.out.println("Inbox is active");} catch (InboxNotFoundException e) { System.err.println("Inbox has expired");}Inbox Already Exists Error
Section titled “Inbox Already Exists Error”When requesting a specific email address:
try { Inbox inbox = client.createInbox( CreateInboxOptions.builder() .build() );} catch (InboxAlreadyExistsException e) { // Address already in use, generate random instead Inbox inbox = client.createInbox();}Inbox Expired
Section titled “Inbox Expired”try { List<Email> emails = inbox.listEmails();} catch (InboxNotFoundException e) { System.err.println("Inbox has expired"); // Create new inbox Inbox newInbox = client.createInbox();}Invalid Import Data
Section titled “Invalid Import Data”try { Inbox inbox = client.importInboxFromFile(Path.of("old-inbox.json"));} catch (InvalidImportDataException e) { System.err.println("Import failed: " + e.getMessage()); // Common causes: // - Inbox has expired // - Invalid key format // - Missing required fields}Next Steps
Section titled “Next Steps”- Email Objects - Learn about email structure
- Managing Inboxes - Common inbox operations
- Import/Export - Advanced inbox persistence
- API Reference: Inbox - Complete API documentation