Managing Inboxes
This guide covers common inbox management operations with practical examples.
Client Configuration
Section titled “Client Configuration”Basic Client Creation
Section titled “Basic Client Creation”package main
import ( "context" "fmt" "log" "os"
vaultsandbox "github.com/vaultsandbox/client-go")
func main() { client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY")) if err != nil { log.Fatal(err) } defer client.Close()
ctx := context.Background() inbox, err := client.CreateInbox(ctx) if err != nil { log.Fatal(err) }
fmt.Printf("Email address: %s\n", inbox.EmailAddress())}Client Options
Section titled “Client Options”import ( "net/http" "time")
// Custom base URL (for testing or self-hosted)client, err := vaultsandbox.New(apiKey, vaultsandbox.WithBaseURL("https://custom.api.com"))
// Custom HTTP clienthttpClient := &http.Client{Timeout: 30 * time.Second}client, err := vaultsandbox.New(apiKey, vaultsandbox.WithHTTPClient(httpClient))
// Custom timeout for operationsclient, err := vaultsandbox.New(apiKey, vaultsandbox.WithTimeout(2*time.Minute))
// Configure retriesclient, err := vaultsandbox.New(apiKey, vaultsandbox.WithRetries(3), vaultsandbox.WithRetryOn([]int{408, 429, 500, 502, 503, 504}),)
// Delivery strategy for real-time emailsclient, err := vaultsandbox.New(apiKey, vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategySSE), // Server-Sent Events // or vaultsandbox.StrategyPolling for polling // or vaultsandbox.StrategyAuto (default) to try SSE, fall back to polling)Validate API Key
Section titled “Validate API Key”// Check if the API key is validif err := client.CheckKey(ctx); err != nil { log.Fatal("Invalid API key:", err)}Get Server Configuration
Section titled “Get Server Configuration”info := client.ServerInfo()fmt.Println("Allowed domains:", info.AllowedDomains)fmt.Println("Max TTL:", info.MaxTTL)fmt.Println("Default TTL:", info.DefaultTTL)Creating Inboxes
Section titled “Creating Inboxes”Basic Creation
Section titled “Basic Creation”inbox, err := client.CreateInbox(ctx)if err != nil { log.Fatal(err)}fmt.Printf("Email address: %s\n", inbox.EmailAddress())With Custom TTL
Section titled “With Custom TTL”import "time"
// Expire after 1 hour (good for CI/CD)inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(time.Hour))
// Expire after 10 minutes (quick tests)inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(10*time.Minute))
// Expire after 7 days (long-running tests)inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(7*24*time.Hour))Requesting Specific Address
Section titled “Requesting Specific Address”import "errors"
inbox, err := client.CreateInbox(ctx,)if errors.Is(err, vaultsandbox.ErrInboxAlreadyExists) { fmt.Println("Address already in use, using random address") inbox, err = client.CreateInbox(ctx)}if err != nil { log.Fatal(err)}fmt.Println("Got address:", inbox.EmailAddress())Listing Emails
Section titled “Listing Emails”List All Emails
Section titled “List All Emails”emails, err := inbox.GetEmails(ctx)if err != nil { log.Fatal(err)}
fmt.Printf("Inbox contains %d emails\n", len(emails))for _, email := range emails { fmt.Printf("- %s: %s\n", email.From, email.Subject)}Filtering Emails
Section titled “Filtering Emails”emails, err := inbox.GetEmails(ctx)if err != nil { log.Fatal(err)}
// Filter by sendervar fromSupport []*vaultsandbox.Emailfor _, e := range emails { fromSupport = append(fromSupport, e) }}
// Filter by subjectvar passwordResets []*vaultsandbox.Emailfor _, e := range emails { if strings.Contains(strings.ToLower(e.Subject), "reset") { passwordResets = append(passwordResets, e) }}
// Filter by dateoneHourAgo := time.Now().Add(-time.Hour)var recentEmails []*vaultsandbox.Emailfor _, e := range emails { if e.ReceivedAt.After(oneHourAgo) { recentEmails = append(recentEmails, e) }}Sorting Emails
Section titled “Sorting Emails”import "sort"
emails, err := inbox.GetEmails(ctx)if err != nil { log.Fatal(err)}
// Sort by date (newest first)sort.Slice(emails, func(i, j int) bool { return emails[i].ReceivedAt.After(emails[j].ReceivedAt)})
// Sort by sendersort.Slice(emails, func(i, j int) bool { return emails[i].From < emails[j].From})Getting Specific Emails
Section titled “Getting Specific Emails”emailID := "email_abc123"email, err := inbox.GetEmail(ctx, emailID)if err != nil { log.Fatal(err)}
fmt.Println(email.Subject)With Error Handling
Section titled “With Error Handling”import "errors"
email, err := inbox.GetEmail(ctx, emailID)if errors.Is(err, vaultsandbox.ErrEmailNotFound) { fmt.Println("Email not found")} else if err != nil { log.Fatal(err)} else { fmt.Println("Found:", email.Subject)}Deleting Emails
Section titled “Deleting Emails”Delete Single Email
Section titled “Delete Single Email”// By ID via inboxemail, err := inbox.GetEmail(ctx, "email_abc123")if err != nil { log.Fatal(err)}if err := inbox.DeleteEmail(ctx, email.ID); err != nil { log.Fatal(err)}Delete Multiple Emails
Section titled “Delete Multiple Emails”emails, err := inbox.GetEmails(ctx)if err != nil { log.Fatal(err)}
// Delete all emails sequentiallyfor _, email := range emails { if err := inbox.DeleteEmail(ctx, email.ID); err != nil { log.Printf("Failed to delete email %s: %v", email.ID, err) }}
// Or delete concurrently with errgroupimport "golang.org/x/sync/errgroup"
g, ctx := errgroup.WithContext(ctx)for _, email := range emails { email := email // capture loop variable g.Go(func() error { return inbox.DeleteEmail(ctx, email.ID) })}if err := g.Wait(); err != nil { log.Fatal(err)}Delete by Criteria
Section titled “Delete by Criteria”emails, err := inbox.GetEmails(ctx)if err != nil { log.Fatal(err)}
// Delete old emails (older than 24 hours)cutoff := time.Now().Add(-24 * time.Hour)for _, email := range emails { if email.ReceivedAt.Before(cutoff) { if err := inbox.DeleteEmail(ctx, email.ID); err != nil { log.Printf("Failed to delete email %s: %v", email.ID, err) } }}Deleting Inboxes
Section titled “Deleting Inboxes”Delete Single Inbox
Section titled “Delete Single Inbox”if err := inbox.Delete(ctx); err != nil { log.Fatal(err)}// Inbox and all emails are now deletedDelete All Inboxes
Section titled “Delete All Inboxes”// Delete all inboxes for this API keycount, err := client.DeleteAllInboxes(ctx)if err != nil { log.Fatal(err)}fmt.Printf("Deleted %d inboxes\n", count)Safe Deletion with Cleanup
Section titled “Safe Deletion with Cleanup”func withInbox(ctx context.Context, client *vaultsandbox.Client, fn func(*vaultsandbox.Inbox) error) error { inbox, err := client.CreateInbox(ctx) if err != nil { return err } defer inbox.Delete(ctx)
return fn(inbox)}
// Usageerr := withInbox(ctx, client, func(inbox *vaultsandbox.Inbox) error { sendTestEmail(inbox.EmailAddress()) email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second)) if err != nil { return err } if !strings.Contains(email.Subject, "Test") { return fmt.Errorf("unexpected subject: %s", email.Subject) } return nil})Checking Inbox Status
Section titled “Checking Inbox Status”Check if Inbox Exists
Section titled “Check if Inbox Exists”import "errors"
_, err := inbox.GetEmails(ctx)if errors.Is(err, vaultsandbox.ErrInboxNotFound) { fmt.Println("Inbox expired or deleted")} else if err != nil { log.Fatal(err)} else { fmt.Println("Inbox exists")}Check Expiration
Section titled “Check Expiration”expiresIn := time.Until(inbox.ExpiresAt())
if expiresIn < 5*time.Minute { fmt.Println("Inbox expiring soon!") fmt.Printf("Time left: %d minutes\n", int(expiresIn.Minutes()))}
// Or use the convenience methodif inbox.IsExpired() { fmt.Println("Inbox has expired")}Get Sync Status
Section titled “Get Sync Status”syncStatus, err := inbox.GetSyncStatus(ctx)if err != nil { log.Fatal(err)}
fmt.Println("Email count:", syncStatus.EmailCount)fmt.Println("Emails hash:", syncStatus.EmailsHash)Get Inbox Hash
Section titled “Get Inbox Hash”// InboxHash returns a unique identifier derived from the inbox's public keyhash := inbox.InboxHash()fmt.Println("Inbox hash:", hash)Waiting for Emails
Section titled “Waiting for Emails”Basic Wait
Section titled “Basic Wait”// Wait for any email with default timeout (60 seconds)email, err := inbox.WaitForEmail(ctx)if err != nil { log.Fatal(err)}fmt.Println("Received:", email.Subject)Wait with Timeout
Section titled “Wait with Timeout”email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(30*time.Second))if err != nil { log.Fatal(err)}Wait with Filters
Section titled “Wait with Filters”import "regexp"
// Wait for email from specific sender
// Wait for email with specific subjectemail, err := inbox.WaitForEmail(ctx, vaultsandbox.WithSubject("Password Reset"))
// Wait for email matching subject regexpattern := regexp.MustCompile(`(?i)verification|confirm`)email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithSubjectRegex(pattern))
// Wait for email matching sender regexsenderPattern := regexp.MustCompile(`@example\.(com|org)$`)email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithFromRegex(senderPattern))
// Wait with custom predicateemail, err := inbox.WaitForEmail(ctx, vaultsandbox.WithPredicate(func(e *vaultsandbox.Email) bool { return len(e.Attachments) > 0 // Wait for email with attachments}))
// Combine multiple filtersemail, err := inbox.WaitForEmail(ctx, vaultsandbox.WithSubjectRegex(regexp.MustCompile(`(?i)ticket`)), vaultsandbox.WithWaitTimeout(2*time.Minute),)Wait for Multiple Emails
Section titled “Wait for Multiple Emails”// Wait until inbox has at least 3 emailsemails, err := inbox.WaitForEmailCount(ctx, 3, vaultsandbox.WithWaitTimeout(2*time.Minute))if err != nil { log.Fatal(err)}fmt.Printf("Received %d emails\n", len(emails))
// With filters - wait for 2 emails from specific senderemails, err := inbox.WaitForEmailCount(ctx, 2, vaultsandbox.WithWaitTimeout(time.Minute),)Working with Email Content
Section titled “Working with Email Content”Get Raw Email
Section titled “Get Raw Email”// Fetch the original raw email content (RFC 5322 format)rawContent, err := inbox.GetRawEmail(ctx, email.ID)if err != nil { log.Fatal(err)}fmt.Println("Raw email:", rawContent)Mark Email as Read
Section titled “Mark Email as Read”if err := inbox.MarkEmailAsRead(ctx, email.ID); err != nil { log.Fatal(err)}fmt.Println("Email marked as read")Access Email Fields
Section titled “Access Email Fields”email, err := inbox.GetEmail(ctx, emailID)if err != nil { log.Fatal(err)}
fmt.Println("ID:", email.ID)fmt.Println("From:", email.From)fmt.Println("To:", email.To)fmt.Println("Subject:", email.Subject)fmt.Println("Text body:", email.Text)fmt.Println("HTML body:", email.HTML)fmt.Println("Received:", email.ReceivedAt)fmt.Println("Is read:", email.IsRead)fmt.Println("Links found:", email.Links)
// Access headersfor key, value := range email.Headers { fmt.Printf("Header %s: %s\n", key, value)}
// Access attachmentsfor _, att := range email.Attachments { fmt.Printf("Attachment: %s (%s, %d bytes)\n", att.Filename, att.ContentType, att.Size) // att.Content contains the raw bytes}
// Access authentication results (SPF, DKIM, DMARC)if email.AuthResults != nil { fmt.Println("SPF:", email.AuthResults.SPF) fmt.Println("DKIM:", email.AuthResults.DKIM) fmt.Println("DMARC:", email.AuthResults.DMARC)}Real-time Email Monitoring
Section titled “Real-time Email Monitoring”Subscribe to Single Inbox
Section titled “Subscribe to Single Inbox”// Watch for new emails on a single inboxctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)defer cancel()
ch := inbox.Watch(ctx)for email := range ch { fmt.Printf("New email: %s from %s\n", email.Subject, email.From)}Monitor Multiple Inboxes
Section titled “Monitor Multiple Inboxes”// Watch multiple inboxes for new emailsctx, cancel := context.WithCancel(context.Background())defer cancel()
ch := client.WatchInboxes(ctx, inbox1, inbox2, inbox3)for event := range ch { fmt.Printf("New email in %s: %s\n", event.Inbox.EmailAddress(), event.Email.Subject)}Export and Import Inboxes
Section titled “Export and Import Inboxes”Export Inbox
Section titled “Export Inbox”// Export inbox data (includes private key - handle securely!)exported := inbox.Export()fmt.Println("Exported at:", exported.ExportedAt)fmt.Println("Email address:", exported.EmailAddress)fmt.Println("Expires at:", exported.ExpiresAt)
// Export to fileif err := client.ExportInboxToFile(inbox, "/path/to/inbox.json"); err != nil { log.Fatal(err)}Import Inbox
Section titled “Import Inbox”// Import from ExportedInbox structimported, err := client.ImportInbox(ctx, exported)if err != nil { log.Fatal(err)}
// Import from fileimported, err := client.ImportInboxFromFile(ctx, "/path/to/inbox.json")if err != nil { log.Fatal(err)}
// Use imported inboxemails, err := imported.GetEmails(ctx)Client Inbox Management
Section titled “Client Inbox Management”Get Inbox by Address
Section titled “Get Inbox by Address”// Look up an inbox managed by this clientif exists { fmt.Println("Found inbox:", inbox.EmailAddress())}List All Client Inboxes
Section titled “List All Client Inboxes”// Get all inboxes currently managed by this clientinboxes := client.Inboxes()for _, inbox := range inboxes { fmt.Printf("- %s (expires: %s)\n", inbox.EmailAddress(), inbox.ExpiresAt())}Delete Inbox by Address
Section titled “Delete Inbox by Address”// Delete a specific inbox by email address log.Fatal(err)}Bulk Operations
Section titled “Bulk Operations”Create Multiple Inboxes
Section titled “Create Multiple Inboxes”import "golang.org/x/sync/errgroup"
const numInboxes = 3inboxes := make([]*vaultsandbox.Inbox, numInboxes)
g, ctx := errgroup.WithContext(ctx)for i := 0; i < numInboxes; i++ { i := i g.Go(func() error { inbox, err := client.CreateInbox(ctx) if err != nil { return err } inboxes[i] = inbox return nil })}if err := g.Wait(); err != nil { log.Fatal(err)}
fmt.Printf("Created %d inboxes\n", len(inboxes))for _, inbox := range inboxes { fmt.Printf("- %s\n", inbox.EmailAddress())}Clean Up Multiple Inboxes
Section titled “Clean Up Multiple Inboxes”// Delete individuallyfor _, inbox := range inboxes { if err := inbox.Delete(ctx); err != nil { log.Printf("Failed to delete inbox: %v", err) }}
// Or use convenience method to delete allcount, err := client.DeleteAllInboxes(ctx)if err != nil { log.Fatal(err)}fmt.Printf("Deleted %d inboxes\n", count)Testing Patterns
Section titled “Testing Patterns”Test Setup/Teardown
Section titled “Test Setup/Teardown”package myapp_test
import ( "context" "os" "testing" "time"
vaultsandbox "github.com/vaultsandbox/client-go")
var ( client *vaultsandbox.Client)
func TestMain(m *testing.M) { var err error client, err = vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY")) if err != nil { panic(err) } defer client.Close()
os.Exit(m.Run())}
func TestReceivesEmail(t *testing.T) { ctx := context.Background() inbox, err := client.CreateInbox(ctx) if err != nil { t.Fatal(err) } defer inbox.Delete(ctx)
sendEmail(inbox.EmailAddress())
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second)) if err != nil { t.Fatal(err) } if email == nil { t.Fatal("expected email") }}Shared Inbox Pattern
Section titled “Shared Inbox Pattern”package myapp_test
import ( "context" "os" "testing" "time"
vaultsandbox "github.com/vaultsandbox/client-go")
var ( client *vaultsandbox.Client inbox *vaultsandbox.Inbox)
func TestMain(m *testing.M) { ctx := context.Background()
var err error client, err = vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY")) if err != nil { panic(err) }
inbox, err = client.CreateInbox(ctx, vaultsandbox.WithTTL(2*time.Hour)) if err != nil { panic(err) }
code := m.Run()
inbox.Delete(ctx) client.Close()
os.Exit(code)}
func TestOne(t *testing.T) { // Use shared inbox}
func TestTwo(t *testing.T) { // Use shared inbox}Inbox Pool Pattern
Section titled “Inbox Pool Pattern”package myapp
import ( "context" "errors" "sync"
vaultsandbox "github.com/vaultsandbox/client-go")
type InboxPool struct { client *vaultsandbox.Client size int available chan *vaultsandbox.Inbox inUse map[*vaultsandbox.Inbox]struct{} mu sync.Mutex}
func NewInboxPool(client *vaultsandbox.Client, size int) *InboxPool { return &InboxPool{ client: client, size: size, available: make(chan *vaultsandbox.Inbox, size), inUse: make(map[*vaultsandbox.Inbox]struct{}), }}
func (p *InboxPool) Initialize(ctx context.Context) error { for i := 0; i < p.size; i++ { inbox, err := p.client.CreateInbox(ctx) if err != nil { return err } p.available <- inbox } return nil}
func (p *InboxPool) Acquire(ctx context.Context) (*vaultsandbox.Inbox, error) { select { case inbox := <-p.available: p.mu.Lock() p.inUse[inbox] = struct{}{} p.mu.Unlock() return inbox, nil case <-ctx.Done(): return nil, ctx.Err() }}
func (p *InboxPool) Release(inbox *vaultsandbox.Inbox) { p.mu.Lock() delete(p.inUse, inbox) p.mu.Unlock() p.available <- inbox}
func (p *InboxPool) Cleanup(ctx context.Context) error { close(p.available)
var errs []error for inbox := range p.available { if err := inbox.Delete(ctx); err != nil { errs = append(errs, err) } }
p.mu.Lock() for inbox := range p.inUse { if err := inbox.Delete(ctx); err != nil { errs = append(errs, err) } } p.mu.Unlock()
if len(errs) > 0 { return errors.Join(errs...) } return nil}
// Usagefunc Example() { ctx := context.Background() pool := NewInboxPool(client, 5) if err := pool.Initialize(ctx); err != nil { panic(err) } defer pool.Cleanup(ctx)
inbox, err := pool.Acquire(ctx) if err != nil { panic(err) } // Use inbox pool.Release(inbox)}Error Handling
Section titled “Error Handling”Sentinel Errors
Section titled “Sentinel Errors”The SDK provides sentinel errors for common error conditions:
import "errors"
// Check for specific error types using errors.Is()if errors.Is(err, vaultsandbox.ErrMissingAPIKey) { // API key was not provided}if errors.Is(err, vaultsandbox.ErrClientClosed) { // Operation attempted on a closed client}if errors.Is(err, vaultsandbox.ErrUnauthorized) { // Invalid or expired API key}if errors.Is(err, vaultsandbox.ErrInboxNotFound) { // Inbox does not exist (expired or deleted)}if errors.Is(err, vaultsandbox.ErrEmailNotFound) { // Email does not exist}if errors.Is(err, vaultsandbox.ErrInboxAlreadyExists) { // Tried to create/import inbox that already exists}if errors.Is(err, vaultsandbox.ErrInvalidImportData) { // Import data is malformed or invalid}if errors.Is(err, vaultsandbox.ErrDecryptionFailed) { // Failed to decrypt email content}if errors.Is(err, vaultsandbox.ErrSignatureInvalid) { // Email signature verification failed}if errors.Is(err, vaultsandbox.ErrRateLimited) { // API rate limit exceeded}Error Types
Section titled “Error Types”import "errors"
// APIError - HTTP errors from the APIvar apiErr *vaultsandbox.APIErrorif errors.As(err, &apiErr) { fmt.Printf("Status: %d\n", apiErr.StatusCode) fmt.Printf("Message: %s\n", apiErr.Message) fmt.Printf("Request ID: %s\n", apiErr.RequestID)}
// NetworkError - Network-level failuresvar netErr *vaultsandbox.NetworkErrorif errors.As(err, &netErr) { fmt.Printf("URL: %s\n", netErr.URL) fmt.Printf("Attempt: %d\n", netErr.Attempt) fmt.Printf("Cause: %v\n", netErr.Err)}
// SignatureVerificationError - Signature check failedvar sigErr *vaultsandbox.SignatureVerificationErrorif errors.As(err, &sigErr) { fmt.Printf("Message: %s\n", sigErr.Message) if sigErr.IsKeyMismatch { fmt.Println("Server key mismatch detected") }}
// Timeouts - use context.DeadlineExceededif errors.Is(err, context.DeadlineExceeded) { fmt.Println("Operation timed out")}Handling Expired Inboxes
Section titled “Handling Expired Inboxes”import "errors"
emails, err := inbox.GetEmails(ctx)if errors.Is(err, vaultsandbox.ErrInboxNotFound) { fmt.Println("Inbox expired, creating new one") inbox, err = client.CreateInbox(ctx) if err != nil { log.Fatal(err) }} else if err != nil { log.Fatal(err)}Handling Creation Errors
Section titled “Handling Creation Errors”import "errors"
inbox, err := client.CreateInbox(ctx)if err != nil { var apiErr *vaultsandbox.APIError var netErr *vaultsandbox.NetworkError
switch { case errors.As(err, &apiErr): fmt.Printf("API error: %d %s\n", apiErr.StatusCode, apiErr.Message) case errors.As(err, &netErr): fmt.Printf("Network error: %v\n", netErr.Err) default: log.Fatal(err) }}Comprehensive Error Handling
Section titled “Comprehensive Error Handling”func handleError(err error) { if err == nil { return }
switch { case errors.Is(err, vaultsandbox.ErrUnauthorized): log.Fatal("Invalid API key - please check your credentials")
case errors.Is(err, vaultsandbox.ErrRateLimited): log.Println("Rate limited - waiting before retry") time.Sleep(time.Minute)
case errors.Is(err, vaultsandbox.ErrInboxNotFound): log.Println("Inbox not found - it may have expired")
case errors.Is(err, vaultsandbox.ErrDecryptionFailed): log.Println("Decryption failed - email may be corrupted")
default: var apiErr *vaultsandbox.APIError var netErr *vaultsandbox.NetworkError
switch { case errors.As(err, &apiErr): log.Printf("API error %d: %s", apiErr.StatusCode, apiErr.Message) case errors.As(err, &netErr): log.Printf("Network error: %v", netErr.Err) default: log.Printf("Unexpected error: %v", err) } }}Best Practices
Section titled “Best Practices”Always Clean Up
Section titled “Always Clean Up”// Good: Cleanup with deferinbox, err := client.CreateInbox(ctx)if err != nil { log.Fatal(err)}defer inbox.Delete(ctx)// Use inbox
// Bad: No cleanupinbox, err := client.CreateInbox(ctx)if err != nil { log.Fatal(err)}// Use inbox// Inbox never deletedUse Appropriate TTL
Section titled “Use Appropriate TTL”// Good: Short TTL for CI/CDinbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(time.Hour))
// Bad: Long TTL wastes resourcesinbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(7*24*time.Hour)) // 7 days for quick testHandle Cleanup Errors
Section titled “Handle Cleanup Errors”func safeDelete(ctx context.Context, inbox *vaultsandbox.Inbox) { if err := inbox.Delete(ctx); err != nil { // Inbox may have already expired if !errors.Is(err, vaultsandbox.ErrInboxNotFound) { log.Printf("Error deleting inbox: %v", err) } }}Next Steps
Section titled “Next Steps”- Waiting for Emails - Learn about email waiting strategies
- Real-time Monitoring - Subscribe to new emails
- API Reference: Inbox - Complete inbox API documentation
- Core Concepts: Inboxes - Deep dive into inbox concepts