Email Objects
Email objects in VaultSandbox represent decrypted emails with all their content, headers, and metadata.
Email Structure
Section titled “Email Structure”const email = await inbox.waitForEmail({ timeout: 30000 });
console.log(email.id); // "email_abc123"console.log(email.subject); // "Welcome to our service"console.log(email.text); // Plain text contentconsole.log(email.html); // HTML contentconsole.log(email.receivedAt); // Date objectconsole.log(email.isRead); // falseconsole.log(email.links); // ["https://example.com/verify"]console.log(email.attachments); // Array of attachmentsconsole.log(email.authResults); // SPF/DKIM/DMARC resultsCore Properties
Section titled “Core Properties”Type: string
Unique identifier for the email.
const emailId = email.id;// Later...const sameEmail = await inbox.getEmail(emailId);Type: string
Sender’s email address (from the From header).
// Use in assertionsType: string[]
Array of recipient email addresses.
// Multiple recipients
// Check if sent to specific addressexpect(email.to).toContain(inbox.emailAddress);subject
Section titled “subject”Type: string
Email subject line.
console.log(email.subject); // "Password Reset Request"
// Use in filteringconst email = await inbox.waitForEmail({ subject: /Password Reset/,});Type: string | null
Plain text content of the email.
console.log(email.text);// "Hello,\n\nClick here to reset your password:\nhttps://..."
// May be null if email is HTML-onlyif (email.text) { expect(email.text).toContain('reset your password');}Type: string | null
HTML content of the email.
console.log(email.html);// "<html><body><p>Hello,</p><a href='https://...'>Reset Password</a></body></html>"
// May be null if email is plain text onlyif (email.html) { expect(email.html).toContain('<a href');}receivedAt
Section titled “receivedAt”Type: Date
When the email was received by the gateway.
console.log(email.receivedAt); // Date: 2024-01-15T12:00:00.000Z
// Check if email arrived recentlyconst ageInSeconds = (new Date() - email.receivedAt) / 1000;expect(ageInSeconds).toBeLessThan(60); // Received within last minuteisRead
Section titled “isRead”Type: boolean
Whether the email has been marked as read.
console.log(email.isRead); // false
await email.markAsRead();
console.log(email.isRead); // trueType: string[]
All URLs extracted from the email (text and HTML).
console.log(email.links);// [// "https://example.com/verify?token=abc123",// "https://example.com/unsubscribe",// "https://example.com/privacy"// ]
// Find specific linkconst verifyLink = email.links.find((url) => url.includes('/verify'));expect(verifyLink).toBeDefined();
// Test linkconst response = await fetch(verifyLink);expect(response.ok).toBe(true);attachments
Section titled “attachments”Type: AttachmentData[]
Array of email attachments.
console.log(email.attachments.length); // 2
email.attachments.forEach((att) => { console.log(att.filename); // "invoice.pdf" console.log(att.contentType); // "application/pdf" console.log(att.size); // 15234 bytes console.log(att.content); // Uint8Array});See Working with Attachments for details.
authResults
Section titled “authResults”Type: AuthResults
Email authentication results (SPF, DKIM, DMARC, reverse DNS).
const auth = email.authResults;
console.log(auth.spf?.result); // "pass"console.log(auth.dkim?.length); // 1console.log(auth.dmarc?.result); // "pass"
// Validate all checksconst validation = auth.validate();if (!validation.passed) { console.error('Authentication failed:', validation.failures);}See Authentication Results for details.
headers
Section titled “headers”Type: Record<string, unknown>
All email headers as a key-value object.
console.log(email.headers);// {// "from": "[email protected]",// "to": "[email protected]",// "subject": "Welcome",// "message-id": "<[email protected]>",// "date": "Mon, 15 Jan 2024 12:00:00 +0000",// "content-type": "text/html; charset=utf-8",// ...// }
// Access specific headersconst messageId = email.headers['message-id'];const contentType = email.headers['content-type'];metadata
Section titled “metadata”Type: Record<string, unknown>
Additional metadata associated with the email.
console.log(email.metadata);// {// emailSizeBytes: 5432,// encryptedAt: "2024-01-15T12:00:00.000Z",// ...// }Email Methods
Section titled “Email Methods”markAsRead()
Section titled “markAsRead()”Mark the email as read.
await email.markAsRead();
console.log(email.isRead); // truedelete()
Section titled “delete()”Delete the email from the inbox.
await email.delete();
// Email is now deletedtry { await inbox.getEmail(email.id);} catch (error) { console.log('Email deleted'); // EmailNotFoundError}getRaw()
Section titled “getRaw()”Get the raw email source (decrypted MIME).
const raw = await email.getRaw();
console.log(raw.id); // Email IDconsole.log(raw.raw);// "From: [email protected]\r\nTo: [email protected]\r\n..."Common Patterns
Section titled “Common Patterns”Content Validation
Section titled “Content Validation”const email = await inbox.waitForEmail({ subject: /Welcome/, timeout: 10000,});
// Validate sender
// Validate contentexpect(email.text).toContain('Thank you for signing up');expect(email.html).toContain('<h1>Welcome</h1>');
// Validate linksconst verifyLink = email.links.find((url) => url.includes('/verify'));expect(verifyLink).toBeDefined();expect(verifyLink).toMatch(/^https:\/\//);Link Extraction and Testing
Section titled “Link Extraction and Testing”const email = await inbox.waitForEmail({ subject: /Reset/ });
// Extract reset linkconst resetLink = email.links.find((url) => url.includes('reset-password') || url.includes('token='));
expect(resetLink).toBeDefined();
// Extract token from linkconst url = new URL(resetLink);const token = url.searchParams.get('token');
expect(token).toBeTruthy();expect(token.length).toBeGreaterThan(20);
// Test the linkconst response = await fetch(resetLink);expect(response.status).toBe(200);Multi-Part Emails
Section titled “Multi-Part Emails”// Email with both text and HTMLif (email.text && email.html) { // Validate both versions have key content expect(email.text).toContain('Welcome'); expect(email.html).toContain('<h1>Welcome</h1>');}
// HTML-only emailif (email.html && !email.text) { console.log('HTML-only email'); expect(email.html).toContain('<!DOCTYPE html>');}
// Plain text onlyif (email.text && !email.html) { console.log('Plain text email');}Time-Based Assertions
Section titled “Time-Based Assertions”const startTime = new Date();
// Trigger emailawait sendWelcomeEmail(inbox.emailAddress);
// Wait and receiveconst email = await inbox.waitForEmail({ timeout: 10000 });
// Verify it arrived quicklyconst deliveryTime = (email.receivedAt - startTime) / 1000;expect(deliveryTime).toBeLessThan(5); // Within 5 secondsEmail Metadata Analysis
Section titled “Email Metadata Analysis”console.log('Email details:');console.log('- From:', email.from);console.log('- Subject:', email.subject);console.log('- Received:', email.receivedAt.toISOString());console.log('- Size:', email.text?.length || 0, 'chars');console.log('- Links:', email.links.length);console.log('- Attachments:', email.attachments.length);
// Check email authenticationconst auth = email.authResults.validate();console.log('- Auth passed:', auth.passed);if (!auth.passed) { console.log('- Auth failures:', auth.failures);}Testing Examples
Section titled “Testing Examples”Jest Example
Section titled “Jest Example”describe('Welcome Email', () => { let inbox, email;
beforeEach(async () => { inbox = await client.createInbox(); });
afterEach(async () => { await inbox.delete(); });
test('should send welcome email on signup', async () => { await registerUser(inbox.emailAddress);
email = await inbox.waitForEmail({ subject: /Welcome/, timeout: 10000, });
expect(email.subject).toContain('Welcome'); expect(email.text).toContain('Thank you for signing up');
const verifyLink = email.links.find((url) => url.includes('/verify')); expect(verifyLink).toBeDefined(); });
test('should include unsubscribe link', async () => { await registerUser(inbox.emailAddress);
email = await inbox.waitForEmail({ timeout: 10000 });
const unsubLink = email.links.find((url) => url.includes('/unsubscribe') || url.includes('list-unsubscribe'));
expect(unsubLink).toBeDefined(); });});Vitest Example
Section titled “Vitest Example”import { describe, it, expect, beforeEach, afterEach } from 'vitest';
describe('Password Reset Flow', () => { let inbox;
beforeEach(async () => { inbox = await client.createInbox(); });
afterEach(async () => { await inbox.delete(); });
it('sends reset email with valid token', async () => { await requestPasswordReset(inbox.emailAddress);
const email = await inbox.waitForEmail({ subject: /reset/i, timeout: 10000, });
const resetLink = email.links[0]; expect(resetLink).toMatch(/^https:\/\//); expect(resetLink).toContain('token=');
// Verify token format const url = new URL(resetLink); const token = url.searchParams.get('token'); expect(token).toHaveLength(64); });});Troubleshooting
Section titled “Troubleshooting”Email Content is Null
Section titled “Email Content is Null”if (!email.text && !email.html) { console.error('Email has no content'); console.log('Headers:', email.headers); console.log('Raw:', await email.getRaw());}Links Not Extracted
Section titled “Links Not Extracted”if (email.links.length === 0) { console.log('No links found'); console.log('Text:', email.text); console.log('HTML:', email.html);
// Manually extract const urlRegex = /https?:\/\/[^\s]+/g; const textLinks = email.text?.match(urlRegex) || []; console.log('Manual extraction:', textLinks);}Decryption Errors
Section titled “Decryption Errors”try { const email = await inbox.getEmail(emailId);} catch (error) { if (error instanceof DecryptionError) { console.error('Failed to decrypt email'); console.error('This may indicate:'); console.error('- Wrong private key'); console.error('- Corrupted data'); console.error('- Server issue'); }}Next Steps
Section titled “Next Steps”- Authentication Results - Email authentication details
- Working with Attachments - Handle email attachments
- Email Authentication - Test SPF/DKIM/DMARC
- API Reference: Email - Complete API documentation