Skip to content

Inboxes

Inboxes are the core concept in VaultSandbox. Each inbox is an isolated, encrypted email destination with its own unique address and encryption keys.

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
import { VaultSandboxClient } from '@vaultsandbox/client';
const client = new VaultSandboxClient({ url, apiKey });
const inbox = await client.createInbox();
console.log(inbox.emailAddress); // "[email protected]"
console.log(inbox.inboxHash); // "a1b2c3d4"
console.log(inbox.expiresAt); // Date object
const inbox = await client.createInbox({
ttl: 3600, // 1 hour (default: 24 hours)
emailAddress: '[email protected]', // Request specific address
});

Note: Requesting a specific email address may fail if it’s already in use. The server will return an error.

Type: string

The full email address for this inbox.

console.log(inbox.emailAddress);

Send emails to this address to have them appear in the inbox.

Type: string

A unique cryptographic hash identifier for the inbox. This is used internally for encryption and identification purposes.

console.log(inbox.inboxHash);
// "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.

Type: Date

When the inbox will automatically expire and be deleted.

00.000Z
console.log(inbox.expiresAt);
// Check if inbox is expiring soon
const hoursUntilExpiry = (inbox.expiresAt - new Date()) / 1000 / 60 / 60;
console.log(`Expires in ${hoursUntilExpiry} hours`);
┌─────────────────────────────────────────────────────────┐
│ 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 destroyed
const emails = await inbox.listEmails();
console.log(`${emails.length} emails in inbox`);
emails.forEach((email) => {
console.log(`${email.from}: ${email.subject}`);
});
const email = await inbox.getEmail('email-id-123');
console.log(email.subject);
console.log(email.text);
// Wait for any email
const email = await inbox.waitForEmail({ timeout: 30000 });
// Wait for specific email
const email = await inbox.waitForEmail({
timeout: 30000,
subject: /Password Reset/,
});
// Delete specific email
await inbox.deleteEmail('email-id-123');
// Or via email object
await email.delete();
// Delete inbox and all its emails
await inbox.delete();

Each inbox is completely isolated:

const inbox1 = await client.createInbox();
const inbox2 = await 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 time

Inboxes automatically expire after their TTL:

// Uses server's DEFAULT_INBOX_TTL (typically 24 hours)
const inbox = await client.createInbox();
// Expire after 1 hour
const inbox = await client.createInbox({ ttl: 3600 });
// Expire after 10 minutes (useful for quick tests)
const inbox = await client.createInbox({ ttl: 600 });
// Expire after 7 days
const inbox = await client.createInbox({ ttl: 604800 });
const minutesLeft = (inbox.expiresAt - new Date()) / 1000 / 60;
if (minutesLeft < 5) {
console.warn('Inbox expiring soon!');
}

Inboxes can be exported and imported for:

  • Test reproducibility
  • Sharing between environments
  • Backup and restore
const exportData = inbox.export();
// Save to file
fs.writeFileSync('inbox.json', JSON.stringify(exportData));
const exportData = JSON.parse(fs.readFileSync('inbox.json', 'utf8'));
const inbox = await client.importInbox(exportData);
// Inbox restored with all encryption keys

Security Warning: Exported data contains private keys. Treat as sensitive.

Short TTL for fast cleanup:

const inbox = await client.createInbox({ ttl: 3600 }); // 1 hour

Always clean up:

try {
const inbox = await client.createInbox();
// Run tests
} finally {
await inbox.delete();
}

Longer TTL for convenience:

const inbox = await client.createInbox({ ttl: 86400 }); // 24 hours

Export for reuse:

// Export after creating
const exportData = inbox.export();
fs.writeFileSync('test-inbox.json', JSON.stringify(exportData));
// Reuse in later sessions
const inbox = await client.importInbox(exportData);

Monitor expiration:

setInterval(() => {
const minutesLeft = (inbox.expiresAt - new Date()) / 1000 / 60;
if (minutesLeft < 10) {
console.warn(`Inbox ${inbox.emailAddress} expiring in ${minutesLeft} minutes`);
}
}, 60000); // Check every minute
let testInbox;
beforeAll(async () => {
testInbox = await client.createInbox({ ttl: 7200 }); // 2 hours
});
afterAll(async () => {
await testInbox.delete();
});
test('password reset', async () => {
await triggerPasswordReset(testInbox.emailAddress);
const email = await testInbox.waitForEmail({ timeout: 10000 });
// ...
});
const user1Inbox = await client.createInbox();
const user2Inbox = await client.createInbox();
const adminInbox = await client.createInbox();
// Each inbox receives emails independently
await sendWelcomeEmail(user1Inbox.emailAddress);
await sendWelcomeEmail(user2Inbox.emailAddress);
await sendAdminReport(adminInbox.emailAddress);
class InboxPool {
constructor(client, size = 5) {
this.client = client;
this.pool = [];
this.size = size;
}
async initialize() {
for (let i = 0; i < this.size; i++) {
const inbox = await this.client.createInbox();
this.pool.push(inbox);
}
}
get() {
return this.pool.shift();
}
async cleanup() {
await Promise.all(this.pool.map((inbox) => inbox.delete()));
}
}

Check:

  1. Email is sent to correct address
  2. Inbox hasn’t expired
  3. DNS/MX records configured correctly
  4. SMTP connection successful
// Verify inbox still exists
const emails = await inbox.listEmails(); // Will error if inbox expired

When requesting a specific email address:

try {
const inbox = await client.createInbox({
emailAddress: '[email protected]',
});
} catch (error) {
if (error instanceof InboxAlreadyExistsError) {
// Address already in use, generate random instead
const inbox = await client.createInbox();
}
}
try {
const emails = await inbox.listEmails();
} catch (error) {
if (error instanceof InboxNotFoundError) {
console.error('Inbox has expired');
// Create new inbox
const newInbox = await client.createInbox();
}
}