Client Configuration
This page covers all configuration options for the VaultSandbox Go client.
Basic Configuration
Section titled “Basic Configuration”Creating a Client
Section titled “Creating a Client”import "github.com/vaultsandbox/client-go"
client, err := vaultsandbox.New("your-api-key", vaultsandbox.WithBaseURL("https://mail.example.com"),)if err != nil { log.Fatal(err)}defer client.Close()Configuration Options
Section titled “Configuration Options”Required Parameters
Section titled “Required Parameters”apiKey
Section titled “apiKey”Type: string
Description: API key for authentication. Passed as the first argument to New().
Example:
client, err := vaultsandbox.New("vs_1234567890abcdef...")Best practices:
- Store in environment variables
- Never commit to version control
- Rotate periodically
Client Options
Section titled “Client Options”Options are passed as variadic arguments to New().
WithBaseURL
Section titled “WithBaseURL”Signature: WithBaseURL(url string) Option
Default: https://api.vaultsandbox.com
Description: Base URL of your VaultSandbox Gateway
Examples:
vaultsandbox.WithBaseURL("https://mail.example.com")vaultsandbox.WithBaseURL("http://localhost:3000") // Local developmentRequirements:
- Must include protocol (
https://orhttp://) - Should not include trailing slash
- Must be accessible from your application
WithDeliveryStrategy
Section titled “WithDeliveryStrategy”Signature: WithDeliveryStrategy(strategy DeliveryStrategy) Option
Default: StrategyAuto
Description: Email delivery strategy
Options:
StrategyAuto- Automatically choose best strategy (tries SSE first, falls back to polling)StrategySSE- Server-Sent Events for real-time deliveryStrategyPolling- Poll for new emails at intervals
Examples:
vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyAuto) // Recommendedvaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategySSE) // Force SSEvaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyPolling) // Force pollingWhen to use each:
StrategyAuto: Most use cases (recommended)StrategySSE: When you need real-time, low-latency deliveryStrategyPolling: When SSE is blocked by firewall/proxy
WithTimeout
Section titled “WithTimeout”Signature: WithTimeout(timeout time.Duration) Option
Default: 60 * time.Second
Description: Default timeout for wait operations (WaitForEmail, WaitForEmailCount) and API key validation during client creation. This timeout is also passed to the internal HTTP client for individual requests.
Note: This controls the maximum time for wait operations, not per-HTTP-request timeouts. For fine-grained HTTP timeout control, use WithHTTPClient with a custom http.Client.
Examples:
vaultsandbox.WithTimeout(30 * time.Second)vaultsandbox.WithTimeout(2 * time.Minute)WithRetries
Section titled “WithRetries”Signature: WithRetries(count int) Option
Default: 3
Description: Maximum retry attempts for failed HTTP requests
Examples:
vaultsandbox.WithRetries(3) // Defaultvaultsandbox.WithRetries(5) // More resilientvaultsandbox.WithRetries(0) // No retriesWithRetryOn
Section titled “WithRetryOn”Signature: WithRetryOn(statusCodes []int) Option
Default: []int{408, 429, 500, 502, 503, 504}
Description: HTTP status codes that trigger a retry
Example:
vaultsandbox.WithRetryOn([]int{408, 429, 500, 502, 503, 504}) // Defaultvaultsandbox.WithRetryOn([]int{500, 502, 503}) // Only server errorsvaultsandbox.WithRetryOn([]int{}) // Never retryWithOnSyncError
Section titled “WithOnSyncError”Signature: WithOnSyncError(fn func(error)) Option
Default: nil (errors are silently ignored)
Description: Callback invoked when background sync fails to fetch emails after an SSE reconnection. Use this to log or handle errors that would otherwise be silently dropped.
Example:
client, err := vaultsandbox.New(apiKey, vaultsandbox.WithOnSyncError(func(err error) { log.Printf("background sync error: %v", err) }),)WithHTTPClient
Section titled “WithHTTPClient”Signature: WithHTTPClient(client *http.Client) Option
Default: http.DefaultClient with timeout
Description: Custom HTTP client for advanced networking needs
Example:
httpClient := &http.Client{ Timeout: 30 * time.Second, Transport: &http.Transport{ MaxIdleConns: 10, IdleConnTimeout: 30 * time.Second, DisableCompression: true, },}
client, err := vaultsandbox.New(apiKey, vaultsandbox.WithHTTPClient(httpClient),)WithPollingConfig
Section titled “WithPollingConfig”Signature: WithPollingConfig(cfg PollingConfig) Option
Description: Sets all polling-related options at once. This is the recommended way to customize polling behavior when you need to change multiple settings. Zero values are ignored, so you only need to specify the fields you want to change.
PollingConfig struct:
type PollingConfig struct { InitialInterval time.Duration // Default: 2 * time.Second MaxBackoff time.Duration // Default: 30 * time.Second BackoffMultiplier float64 // Default: 1.5 JitterFactor float64 // Default: 0.3 (30%) SSEConnectionTimeout time.Duration // Default: 5 * time.Second}Example:
client, err := vaultsandbox.New(apiKey, vaultsandbox.WithPollingConfig(vaultsandbox.PollingConfig{ InitialInterval: 1 * time.Second, // Faster initial polling MaxBackoff: 10 * time.Second, // Lower max backoff }),)When to use: Use WithPollingConfig when you need to customize polling settings. Zero values are ignored, so you only need to specify the fields you want to change.
Inbox Options
Section titled “Inbox Options”Options passed to CreateInbox().
WithTTL
Section titled “WithTTL”Signature: WithTTL(ttl time.Duration) InboxOption
Default: 1 * time.Hour
Description: Time-to-live for the inbox
Constraints:
- Minimum: 1 minute (
MinTTL) - Maximum: 7 days (
MaxTTL) or server-configured limit
Examples:
inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(30 * time.Minute),)
inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(24 * time.Hour),)WithEmailAddress
Section titled “WithEmailAddress”Signature: WithEmailAddress(email string) InboxOption
Default: Auto-generated
Description: Request a specific email address
Example:
inbox, err := client.CreateInbox(ctx,)Wait Options
Section titled “Wait Options”Options passed to WaitForEmail() and WaitForEmailCount().
WithWaitTimeout
Section titled “WithWaitTimeout”Signature: WithWaitTimeout(timeout time.Duration) WaitOption
Default: 60 * time.Second
Description: Maximum time to wait for email
Example:
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(30 * time.Second),)WithSubject
Section titled “WithSubject”Signature: WithSubject(subject string) WaitOption
Description: Filter emails by exact subject match
Example:
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithSubject("Password Reset"),)WithSubjectRegex
Section titled “WithSubjectRegex”Signature: WithSubjectRegex(pattern *regexp.Regexp) WaitOption
Description: Filter emails by subject regex
Example:
pattern := regexp.MustCompile(`(?i)password.*reset`)email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithSubjectRegex(pattern),)WithFrom
Section titled “WithFrom”Signature: WithFrom(from string) WaitOption
Description: Filter emails by exact sender match
Example:
email, err := inbox.WaitForEmail(ctx,)WithFromRegex
Section titled “WithFromRegex”Signature: WithFromRegex(pattern *regexp.Regexp) WaitOption
Description: Filter emails by sender regex
Example:
pattern := regexp.MustCompile(`@example\.com$`)email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithFromRegex(pattern),)WithPredicate
Section titled “WithPredicate”Signature: WithPredicate(fn func(*Email) bool) WaitOption
Description: Filter emails by custom predicate function
Example:
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithPredicate(func(e *vaultsandbox.Email) bool { return len(e.Attachments) > 0 }),)Configuration Examples
Section titled “Configuration Examples”Production Configuration
Section titled “Production Configuration”client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyAuto), vaultsandbox.WithRetries(5), vaultsandbox.WithTimeout(60 * time.Second),)CI/CD Configuration
Section titled “CI/CD Configuration”client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyAuto), vaultsandbox.WithRetries(3), vaultsandbox.WithTimeout(30 * time.Second),)Development Configuration
Section titled “Development Configuration”client, err := vaultsandbox.New("dev-api-key", vaultsandbox.WithBaseURL("http://localhost:3000"), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyPolling), vaultsandbox.WithRetries(1),)High-Reliability Configuration
Section titled “High-Reliability Configuration”client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), vaultsandbox.WithRetries(10), vaultsandbox.WithRetryOn([]int{408, 429, 500, 502, 503, 504}), vaultsandbox.WithTimeout(2 * time.Minute),)Custom Polling Configuration
Section titled “Custom Polling Configuration”client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyPolling), vaultsandbox.WithPollingConfig(vaultsandbox.PollingConfig{ InitialInterval: 1 * time.Second, // Faster initial polling MaxBackoff: 15 * time.Second, // Lower max backoff BackoffMultiplier: 1.2, // Slower backoff growth JitterFactor: 0.2, // Less jitter }),)Tuned Auto Mode Configuration
Section titled “Tuned Auto Mode Configuration”client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), vaultsandbox.WithDeliveryStrategy(vaultsandbox.StrategyAuto), vaultsandbox.WithPollingConfig(vaultsandbox.PollingConfig{ SSEConnectionTimeout: 10 * time.Second, // More time for SSE InitialInterval: 2 * time.Second, // Fallback polling config MaxBackoff: 30 * time.Second, }),)Environment Variables
Section titled “Environment Variables”Store configuration in environment variables:
.env File
Section titled “.env File”VAULTSANDBOX_URL=https://mail.example.comVAULTSANDBOX_API_KEY=vs_1234567890abcdef...import ( "os"
"github.com/joho/godotenv" "github.com/vaultsandbox/client-go")
func main() { // Load .env file godotenv.Load()
client, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")), ) if err != nil { log.Fatal(err) } defer client.Close()}Client Methods
Section titled “Client Methods”CreateInbox()
Section titled “CreateInbox()”Create a new temporary email inbox:
inbox, err := client.CreateInbox(ctx, vaultsandbox.WithTTL(30 * time.Minute),)Signature: CreateInbox(ctx context.Context, opts ...InboxOption) (*Inbox, error)
Returns: A new *Inbox that can receive emails.
ImportInbox()
Section titled “ImportInbox()”Import a previously exported inbox:
inbox, err := client.ImportInbox(ctx, exportedData)Signature: ImportInbox(ctx context.Context, data *ExportedInbox) (*Inbox, error)
Returns: The restored *Inbox.
Errors: Returns ErrInboxAlreadyExists if the inbox is already managed by this client.
DeleteInbox()
Section titled “DeleteInbox()”Delete an inbox by email address:
Signature: DeleteInbox(ctx context.Context, emailAddress string) error
DeleteAllInboxes()
Section titled “DeleteAllInboxes()”Delete all inboxes managed by this client:
count, err := client.DeleteAllInboxes(ctx)fmt.Printf("Deleted %d inboxes\n", count)Signature: DeleteAllInboxes(ctx context.Context) (int, error)
Returns: The number of inboxes deleted.
GetInbox()
Section titled “GetInbox()”Get an inbox by email address:
if exists { // Use inbox}Signature: GetInbox(emailAddress string) (*Inbox, bool)
Returns: The inbox and true if found, otherwise nil and false.
Inboxes()
Section titled “Inboxes()”Get all inboxes managed by this client:
inboxes := client.Inboxes()for _, inbox := range inboxes { fmt.Println(inbox.EmailAddress())}Signature: Inboxes() []*Inbox
ServerInfo()
Section titled “ServerInfo()”Get server configuration:
info := client.ServerInfo()fmt.Printf("Max TTL: %v\n", info.MaxTTL)fmt.Printf("Allowed domains: %v\n", info.AllowedDomains)Signature: ServerInfo() *ServerInfo
Returns: *ServerInfo containing:
AllowedDomains []string- Email domains the server acceptsMaxTTL time.Duration- Maximum inbox TTL allowedDefaultTTL time.Duration- Default inbox TTL
CheckKey()
Section titled “CheckKey()”Validate the API key:
err := client.CheckKey(ctx)if err != nil { log.Fatal("Invalid API key")}Signature: CheckKey(ctx context.Context) error
Note: The API key is automatically validated when creating a client with New().
ExportInboxToFile()
Section titled “ExportInboxToFile()”Export an inbox to a JSON file:
err := client.ExportInboxToFile(inbox, "/path/to/inbox.json")Signature: ExportInboxToFile(inbox *Inbox, filePath string) error
Warning: The exported file contains private key material. Handle securely.
ImportInboxFromFile()
Section titled “ImportInboxFromFile()”Import an inbox from a JSON file:
inbox, err := client.ImportInboxFromFile(ctx, "/path/to/inbox.json")Signature: ImportInboxFromFile(ctx context.Context, filePath string) (*Inbox, error)
WatchInboxes()
Section titled “WatchInboxes()”Watch multiple inboxes for new emails via a channel:
ctx, cancel := context.WithCancel(context.Background())defer cancel()
for event := range client.WatchInboxes(ctx, inbox1, inbox2) { fmt.Printf("New email in %s: %s\n", event.Inbox.EmailAddress(), event.Email.Subject)}Signature: WatchInboxes(ctx context.Context, inboxes ...*Inbox) <-chan *InboxEvent
Returns: A receive-only channel of *InboxEvent that closes when context is cancelled.
Close()
Section titled “Close()”Close the client and clean up resources:
err := client.Close()What it does:
- Terminates all active SSE connections
- Stops all polling operations
- Cleans up resources
When to use:
- After test suite completes
- Before process exit
- When client is no longer needed
Example:
client, err := vaultsandbox.New(apiKey, vaultsandbox.WithBaseURL(url))if err != nil { log.Fatal(err)}defer client.Close()
// Use clientinbox, err := client.CreateInbox(ctx)// ...Inbox Methods
Section titled “Inbox Methods”EmailAddress()
Section titled “EmailAddress()”Get the inbox email address:
email := inbox.EmailAddress()Signature: EmailAddress() string
ExpiresAt()
Section titled “ExpiresAt()”Get when the inbox expires:
expiry := inbox.ExpiresAt()fmt.Printf("Expires at: %v\n", expiry)Signature: ExpiresAt() time.Time
InboxHash()
Section titled “InboxHash()”Get the SHA-256 hash of the public key:
hash := inbox.InboxHash()Signature: InboxHash() string
IsExpired()
Section titled “IsExpired()”Check if the inbox has expired:
if inbox.IsExpired() { // Create a new inbox}Signature: IsExpired() bool
GetSyncStatus()
Section titled “GetSyncStatus()”Get the synchronization status of the inbox:
status, err := inbox.GetSyncStatus(ctx)fmt.Printf("Email count: %d\n", status.EmailCount)fmt.Printf("Emails hash: %s\n", status.EmailsHash)Signature: GetSyncStatus(ctx context.Context) (*SyncStatus, error)
Returns: *SyncStatus containing:
EmailCount int- Number of emails in the inboxEmailsHash string- Hash of the email list for change detection
GetEmails()
Section titled “GetEmails()”Fetch all emails in the inbox:
emails, err := inbox.GetEmails(ctx)for _, email := range emails { fmt.Printf("Subject: %s\n", email.Subject)}Signature: GetEmails(ctx context.Context) ([]*Email, error)
GetEmail()
Section titled “GetEmail()”Fetch a specific email by ID:
email, err := inbox.GetEmail(ctx, "email-id-123")Signature: GetEmail(ctx context.Context, emailID string) (*Email, error)
WaitForEmail()
Section titled “WaitForEmail()”Wait for an email matching the given criteria:
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithSubject("Welcome"), vaultsandbox.WithWaitTimeout(30 * time.Second),)Signature: WaitForEmail(ctx context.Context, opts ...WaitOption) (*Email, error)
WaitForEmailCount()
Section titled “WaitForEmailCount()”Wait until the inbox has at least N emails matching criteria:
emails, err := inbox.WaitForEmailCount(ctx, 3,)Signature: WaitForEmailCount(ctx context.Context, count int, opts ...WaitOption) ([]*Email, error)
Delete()
Section titled “Delete()”Delete the inbox:
err := inbox.Delete(ctx)Signature: Delete(ctx context.Context) error
Export()
Section titled “Export()”Export inbox data including private key:
data := inbox.Export()// data can be serialized to JSON and storedSignature: Export() *ExportedInbox
Warning: The returned data contains private key material. Handle securely.
Watch()
Section titled “Watch()”Watch for new email notifications via a channel:
ctx, cancel := context.WithCancel(context.Background())defer cancel()
for email := range inbox.Watch(ctx) { fmt.Printf("New email: %s\n", email.Subject)}Signature: Watch(ctx context.Context) <-chan *Email
Returns: A receive-only channel of *Email that closes when context is cancelled.
Email Operations
Section titled “Email Operations”Email is a pure data struct with no methods. Use Inbox methods to perform operations on emails.
GetRawEmail()
Section titled “GetRawEmail()”Fetch the raw email content (RFC 5322 format):
raw, err := inbox.GetRawEmail(ctx, email.ID)fmt.Println(raw)Signature: GetRawEmail(ctx context.Context, emailID string) (string, error)
MarkEmailAsRead()
Section titled “MarkEmailAsRead()”Mark an email as read:
err := inbox.MarkEmailAsRead(ctx, email.ID)Signature: MarkEmailAsRead(ctx context.Context, emailID string) error
DeleteEmail()
Section titled “DeleteEmail()”Delete an email:
err := inbox.DeleteEmail(ctx, email.ID)Signature: DeleteEmail(ctx context.Context, emailID string) error
Represents a decrypted email:
type Email struct { ID string From string To []string Subject string Text string HTML string ReceivedAt time.Time Headers map[string]string Attachments []Attachment Links []string AuthResults *authresults.AuthResults IsRead bool}Attachment
Section titled “Attachment”Represents an email attachment:
type Attachment struct { Filename string ContentType string Size int ContentID string ContentDisposition string Content []byte Checksum string}ServerInfo
Section titled “ServerInfo”Contains server configuration:
type ServerInfo struct { AllowedDomains []string MaxTTL time.Duration DefaultTTL time.Duration}SyncStatus
Section titled “SyncStatus”Represents the synchronization status of an inbox:
type SyncStatus struct { EmailCount int EmailsHash string}ExportedInbox
Section titled “ExportedInbox”Contains all data needed to restore an inbox:
type ExportedInbox struct { EmailAddress string ExpiresAt time.Time InboxHash string ServerSigPk string PublicKeyB64 string SecretKeyB64 string ExportedAt time.Time}Warning: Contains private key material. Handle securely.
InboxEvent
Section titled “InboxEvent”Event struct returned when watching multiple inboxes:
type InboxEvent struct { Inbox *Inbox // The inbox that received the email Email *Email // The received email}Strategy Selection Guide
Section titled “Strategy Selection Guide”Auto (Recommended)
Section titled “Auto (Recommended)”Use when: You want optimal performance with automatic fallback
Behavior:
- Tries SSE first
- Falls back to polling if SSE fails
- Automatically reconnects on errors
Pros:
- Best of both worlds
- No manual configuration needed
- Resilient to network issues
Cons:
- Slightly more complex internally
SSE (Server-Sent Events)
Section titled “SSE (Server-Sent Events)”Use when: You need real-time, low-latency delivery
Behavior:
- Persistent connection to server
- Push-based email notification
- Instant delivery
Pros:
- Real-time delivery (no polling delay)
- Efficient (no repeated HTTP requests)
- Deterministic tests
Cons:
- Requires persistent connection
- May be blocked by some proxies/firewalls
- More complex error handling
Polling
Section titled “Polling”Use when: SSE is blocked or unreliable
Behavior:
- Periodic HTTP requests for new emails
- Pull-based email retrieval
- Configurable interval
Pros:
- Works in all network environments
- No persistent connection required
- Simple and predictable
Cons:
- Delay based on polling interval
- More HTTP requests
- Less efficient than SSE
Best Practices
Section titled “Best Practices”Security
Section titled “Security”Do:
// Use environment variablesclient, err := vaultsandbox.New(os.Getenv("VAULTSANDBOX_API_KEY"), vaultsandbox.WithBaseURL(os.Getenv("VAULTSANDBOX_URL")),)Don’t:
// Hard-code credentialsclient, err := vaultsandbox.New("vs_1234567890...", // Never do this vaultsandbox.WithBaseURL("https://mail.example.com"),)Resource Management
Section titled “Resource Management”Do:
client, err := vaultsandbox.New(apiKey, vaultsandbox.WithBaseURL(url))if err != nil { log.Fatal(err)}defer client.Close() // Always clean up
runTests()Don’t:
client, err := vaultsandbox.New(apiKey, vaultsandbox.WithBaseURL(url))runTests()// Forgot to close, resources leakError Handling
Section titled “Error Handling”Error Types:
APIError- HTTP errors from the API withStatusCode,Message,RequestID, andResourceTypefieldsNetworkError- Network-level failures withErr(underlying error),URL, andAttemptfieldsSignatureVerificationError- Signature verification failures withMessageandIsKeyMismatchfields
Sentinel Errors (use with errors.Is()):
ErrMissingAPIKey- No API key provided toNew()ErrClientClosed- Client has been closedErrUnauthorized- Invalid or expired API keyErrInboxNotFound- Inbox does not exist or has expiredErrEmailNotFound- Email does not existErrInboxAlreadyExists- Inbox already exists (when importing duplicate)ErrInvalidImportData- Invalid inbox import dataErrDecryptionFailed- Email decryption failedErrSignatureInvalid- Signature verification failedErrRateLimited- API rate limit exceeded
Timeouts: Use context.DeadlineExceeded for timeout handling
Do:
inbox, err := client.CreateInbox(ctx)if err != nil { var apiErr *vaultsandbox.APIError var netErr *vaultsandbox.NetworkError
switch { case errors.As(err, &apiErr): log.Printf("API error %d: %s (request: %s)", apiErr.StatusCode, apiErr.Message, apiErr.RequestID) case errors.As(err, &netErr): log.Printf("Network error on %s (attempt %d): %v", netErr.URL, netErr.Attempt, netErr.Err) case errors.Is(err, vaultsandbox.ErrUnauthorized): log.Printf("Invalid API key") case errors.Is(err, vaultsandbox.ErrRateLimited): log.Printf("Rate limited, retry later") default: log.Printf("Unexpected error: %v", err) } return}Context Usage
Section titled “Context Usage”Do:
// Use context for cancellation and timeoutsctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()
email, err := inbox.WaitForEmail(ctx)Don’t:
// Don't use context.Background() for long operations without timeoutemail, err := inbox.WaitForEmail(context.Background()) // May hang foreverNext Steps
Section titled “Next Steps”- Core Concepts: Inboxes - Learn about inboxes
- Managing Inboxes - Common inbox operations
- Testing Patterns - Integrate with your tests
- API Reference: Client - Full API documentation