IVaultSandboxClient API
The IVaultSandboxClient is the main entry point for interacting with the VaultSandbox Gateway. It handles authentication, inbox creation, and provides utility methods for managing inboxes.
Creating a Client
Section titled “Creating a Client”Builder Pattern
Section titled “Builder Pattern”Use VaultSandboxClientBuilder to create a client instance with fluent configuration:
using VaultSandbox.Client;
// Basic configurationvar client = VaultSandboxClientBuilder.Create() .WithBaseUrl("https://smtp.vaultsandbox.com") .WithApiKey("your-api-key") .Build();
// With validation (recommended for production)var client = await VaultSandboxClientBuilder.Create() .WithBaseUrl("https://smtp.vaultsandbox.com") .WithApiKey("your-api-key") .BuildAndValidateAsync();Dependency Injection (ASP.NET Core)
Section titled “Dependency Injection (ASP.NET Core)”Register the client in your service collection:
// In Program.cs or Startup.csservices.AddVaultSandboxClient(options =>{ options.BaseUrl = "https://smtp.vaultsandbox.com"; options.ApiKey = Configuration["VaultSandbox:ApiKey"];});
// Or bind from configurationservices.AddVaultSandboxClient(Configuration.GetSection("VaultSandbox"));Configuration in appsettings.json:
{ "VaultSandbox": { "BaseUrl": "https://smtp.vaultsandbox.com", "ApiKey": "your-api-key", "WaitTimeoutMs": 30000, "PollIntervalMs": 2000 }}Inject the client in your services:
public class EmailTestService{ private readonly IVaultSandboxClient _client;
public EmailTestService(IVaultSandboxClient client) { _client = client; }}VaultSandboxClientBuilder
Section titled “VaultSandboxClientBuilder”The builder provides fluent configuration methods for creating a client.
Methods
Section titled “Methods”| Method | Description |
|---|---|
Create() | Static factory method to start building |
WithBaseUrl(string) | Set the gateway URL |
WithApiKey(string) | Set the API authentication key |
WithHttpTimeout(TimeSpan) | HTTP request timeout (default: 30s) |
WithWaitTimeout(TimeSpan) | Default wait timeout for email operations (default: 30s) |
WithPollInterval(TimeSpan) | Polling interval for email delivery (default: 2s) |
WithMaxRetries(int) | Maximum retry attempts for HTTP requests (default: 3) |
WithRetryDelay(TimeSpan) | Initial delay between retries (default: 1s) |
WithSseReconnectInterval(TimeSpan) | SSE reconnection delay (default: 5s) |
WithSseMaxReconnectAttempts(int) | Maximum SSE reconnection attempts (default: 10) |
WithDeliveryStrategy(DeliveryStrategy) | Set the delivery strategy directly |
UseSseDelivery() | Use Server-Sent Events for email delivery |
UsePollingDelivery() | Use polling for email delivery |
UseAutoDelivery() | Auto-select delivery strategy (default) |
WithDefaultInboxTtl(TimeSpan) | Default time-to-live for new inboxes |
WithLogging(ILoggerFactory) | Add logging support |
WithHttpClient(HttpClient, bool) | Use a custom HttpClient instance (optional: dispose client on cleanup) |
Build() | Build the client instance |
BuildAndValidateAsync(CancellationToken) | Build and validate the API key |
Example
Section titled “Example”var client = VaultSandboxClientBuilder.Create() .WithBaseUrl("https://smtp.vaultsandbox.com") .WithApiKey(Environment.GetEnvironmentVariable("VAULTSANDBOX_API_KEY")) .WithWaitTimeout(TimeSpan.FromSeconds(60)) .WithPollInterval(TimeSpan.FromSeconds(1)) .WithMaxRetries(5) .WithRetryDelay(TimeSpan.FromSeconds(2)) .UseSseDelivery() .WithLogging(loggerFactory) .Build();Custom HttpClient
Section titled “Custom HttpClient”// Use custom HttpClient, let the builder manage disposalvar client = VaultSandboxClientBuilder.Create() .WithBaseUrl("https://smtp.vaultsandbox.com") .WithApiKey("your-api-key") .WithHttpClient(myHttpClient, disposeClient: true) .Build();
// Use custom HttpClient, manage disposal yourselfvar client = VaultSandboxClientBuilder.Create() .WithBaseUrl("https://smtp.vaultsandbox.com") .WithApiKey("your-api-key") .WithHttpClient(sharedHttpClient, disposeClient: false) .Build();VaultSandboxClientOptions
Section titled “VaultSandboxClientOptions”Configuration options class for the client.
public sealed class VaultSandboxClientOptions{ public required string BaseUrl { get; set; } public required string ApiKey { get; set; } public int HttpTimeoutMs { get; set; } = 30_000; public int WaitTimeoutMs { get; set; } = 30_000; public int PollIntervalMs { get; set; } = 2_000; public int MaxRetries { get; set; } = 3; public int RetryDelayMs { get; set; } = 1_000; public int SseReconnectIntervalMs { get; set; } = 5_000; public int SseMaxReconnectAttempts { get; set; } = 10; public DeliveryStrategy DefaultDeliveryStrategy { get; set; } = DeliveryStrategy.Auto; public int DefaultInboxTtlSeconds { get; set; } = 3600;
public void Validate();}Methods
Section titled “Methods”CreateInboxAsync
Section titled “CreateInboxAsync”Creates a new email inbox with automatic key generation and encryption setup.
Task<IInbox> CreateInboxAsync( CreateInboxOptions? options = null, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”options(optional): Configuration for the inboxcancellationToken: Cancellation token for the operation
public sealed class CreateInboxOptions{ public string? EmailAddress { get; set; } public TimeSpan? Ttl { get; set; }}| Property | Type | Description |
|---|---|---|
Ttl | TimeSpan? | Time-to-live for the inbox (min: 60s, max: 7 days) |
EmailAddress | string? | Request a specific email address (max 254 chars) |
Returns
Section titled “Returns”Task<IInbox> - The created inbox instance
Example
Section titled “Example”// Create inbox with default settingsvar inbox = await client.CreateInboxAsync();Console.WriteLine($"Send email to: {inbox.EmailAddress}");
// Create inbox with custom TTL (1 hour)var inbox = await client.CreateInboxAsync(new CreateInboxOptions{ Ttl = TimeSpan.FromHours(1)});
// Request specific email addressvar inbox = await client.CreateInboxAsync(new CreateInboxOptions{});Errors
Section titled “Errors”ApiException- API-level error (invalid request, permission denied)NetworkException- Network connection failureInboxAlreadyExistsException- Requested email address is already in use
DeleteInboxAsync
Section titled “DeleteInboxAsync”Deletes a specific inbox by email address.
Task DeleteInboxAsync(string emailAddress, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”emailAddress: The email address of the inbox to deletecancellationToken: Cancellation token for the operation
Example
Section titled “Example”Console.WriteLine("Inbox deleted");DeleteAllInboxesAsync
Section titled “DeleteAllInboxesAsync”Deletes all inboxes associated with the current API key. Useful for cleanup in test environments.
Task<int> DeleteAllInboxesAsync(CancellationToken cancellationToken = default)Returns
Section titled “Returns”Task<int> - Number of inboxes deleted
Example
Section titled “Example”var deleted = await client.DeleteAllInboxesAsync();Console.WriteLine($"Deleted {deleted} inboxes");Best Practice
Section titled “Best Practice”Use this in test cleanup to avoid orphaned inboxes:
[TearDown]public async Task Cleanup(){ var deleted = await _client.DeleteAllInboxesAsync(); if (deleted > 0) { Console.WriteLine($"Cleaned up {deleted} orphaned inboxes"); }}GetServerInfoAsync
Section titled “GetServerInfoAsync”Retrieves information about the VaultSandbox Gateway server.
Task<ServerInfo> GetServerInfoAsync(CancellationToken cancellationToken = default)Returns
Section titled “Returns”Task<ServerInfo> - Server information record
public sealed record ServerInfo{ public required string ServerSigPk { get; init; } public required string Context { get; init; } public required int MaxTtl { get; init; } public required int DefaultTtl { get; init; } public required bool SseConsole { get; init; } public required IReadOnlyList<string> AllowedDomains { get; init; }}| Property | Type | Description |
|---|---|---|
ServerSigPk | string | Base64URL-encoded server signing public key for ML-DSA-65 |
Context | string | Context string for the encryption scheme |
MaxTtl | int | Maximum time-to-live for inboxes in seconds |
DefaultTtl | int | Default time-to-live for inboxes in seconds |
SseConsole | bool | Whether the server SSE console is enabled |
AllowedDomains | IReadOnlyList<string> | List of domains allowed for inbox creation |
Example
Section titled “Example”var info = await client.GetServerInfoAsync();Console.WriteLine($"Server: {info.Context}");Console.WriteLine($"Max TTL: {info.MaxTtl}s, Default TTL: {info.DefaultTtl}s");Console.WriteLine($"Allowed domains: {string.Join(", ", info.AllowedDomains)}");ValidateApiKeyAsync
Section titled “ValidateApiKeyAsync”Validates the API key with the server.
Task<bool> ValidateApiKeyAsync(CancellationToken cancellationToken = default)Returns
Section titled “Returns”Task<bool> - true if the API key is valid
Example
Section titled “Example”var isValid = await client.ValidateApiKeyAsync();if (!isValid){ throw new InvalidOperationException("Invalid API key");}Useful for verifying configuration before running tests:
[OneTimeSetUp]public async Task Setup(){ _client = VaultSandboxClientBuilder.Create() .WithBaseUrl(Environment.GetEnvironmentVariable("VAULTSANDBOX_URL")) .WithApiKey(Environment.GetEnvironmentVariable("VAULTSANDBOX_API_KEY")) .Build();
var isValid = await _client.ValidateApiKeyAsync(); if (!isValid) { throw new InvalidOperationException("VaultSandbox API key is invalid"); }}MonitorInboxes
Section titled “MonitorInboxes”Monitors multiple inboxes simultaneously for new emails.
InboxMonitor MonitorInboxes(params IInbox[] inboxes)Parameters
Section titled “Parameters”inboxes: Array of inbox instances to monitor
Returns
Section titled “Returns”InboxMonitor - Monitor for multi-inbox watching
Example
Section titled “Example”var inbox1 = await client.CreateInboxAsync();var inbox2 = await client.CreateInboxAsync();
var monitor = client.MonitorInboxes(inbox1, inbox2);
await foreach (var evt in monitor.WatchAsync(cancellationToken)){ Console.WriteLine($"New email in {evt.InboxAddress}: {evt.Email.Subject}");}See InboxMonitor for more details.
ImportInboxAsync
Section titled “ImportInboxAsync”Imports a previously exported inbox, restoring all data and encryption keys.
Task<IInbox> ImportInboxAsync( InboxExport export, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”export: Previously exported inbox datacancellationToken: Cancellation token for the operation
Returns
Section titled “Returns”Task<IInbox> - The imported inbox instance
Example
Section titled “Example”var exportedData = JsonSerializer.Deserialize<InboxExport>(savedJson);var inbox = await client.ImportInboxAsync(exportedData);
Console.WriteLine($"Imported inbox: {inbox.EmailAddress}");
// Use inbox normallyvar emails = await inbox.GetEmailsAsync();Errors
Section titled “Errors”InboxAlreadyExistsException- Inbox is already imported in this clientInvalidImportDataException- Import data is invalid or corruptedApiException- Server rejected the import (inbox may not exist)
ImportInboxFromFileAsync
Section titled “ImportInboxFromFileAsync”Imports an inbox from a JSON file.
Task<IInbox> ImportInboxFromFileAsync( string filePath, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”filePath: Path to the exported inbox JSON filecancellationToken: Cancellation token for the operation
Returns
Section titled “Returns”Task<IInbox> - The imported inbox instance
Example
Section titled “Example”// Import from filevar inbox = await client.ImportInboxFromFileAsync("./backup/inbox.json");
Console.WriteLine($"Imported inbox: {inbox.EmailAddress}");
// Monitor for new emailsawait foreach (var email in inbox.WatchAsync(cancellationToken)){ Console.WriteLine($"New email: {email.Subject}");}Use Cases
Section titled “Use Cases”- Test reproducibility across runs
- Sharing inboxes between environments
- Manual testing workflows
- Debugging production issues
ExportInboxToFileAsync
Section titled “ExportInboxToFileAsync”Exports an inbox to a JSON file on disk.
Task ExportInboxToFileAsync( IInbox inbox, string filePath, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”inbox: Inbox instance to exportfilePath: Path where the JSON file will be writtencancellationToken: Cancellation token for the operation
Example
Section titled “Example”var inbox = await client.CreateInboxAsync();
// Export to fileawait client.ExportInboxToFileAsync(inbox, "./backup/inbox.json");
Console.WriteLine("Inbox exported to ./backup/inbox.json");Security Warning
Section titled “Security Warning”Exported data contains private encryption keys. Store securely and never commit to version control.
InboxMonitor
Section titled “InboxMonitor”The InboxMonitor class allows you to monitor multiple inboxes simultaneously using IAsyncEnumerable.
Creating a Monitor
Section titled “Creating a Monitor”var inbox1 = await client.CreateInboxAsync();var inbox2 = await client.CreateInboxAsync();
var monitor = client.MonitorInboxes(inbox1, inbox2);WatchAsync
Section titled “WatchAsync”Streams email arrival events from all monitored inboxes.
IAsyncEnumerable<InboxEmailEvent> WatchAsync(CancellationToken cancellationToken = default)Returns
Section titled “Returns”IAsyncEnumerable<InboxEmailEvent> - Stream of email events
public sealed record InboxEmailEvent(IInbox Inbox, Email Email){ public IInbox Inbox { get; } = Inbox; public Email Email { get; } = Email; public string InboxAddress => Inbox.EmailAddress;}Example
Section titled “Example”var monitor = client.MonitorInboxes(inbox1, inbox2);
await foreach (var evt in monitor.WatchAsync(cancellationToken)){ Console.WriteLine($"Email received in {evt.InboxAddress}"); Console.WriteLine($"Subject: {evt.Email.Subject}");}DisposeAsync
Section titled “DisposeAsync”Stops monitoring and cleans up resources.
await monitor.DisposeAsync();Complete Example
Section titled “Complete Example”using VaultSandbox.Client;
async Task MonitorMultipleInboxes(CancellationToken cancellationToken){ var client = VaultSandboxClientBuilder.Create() .WithBaseUrl("https://smtp.vaultsandbox.com") .WithApiKey(Environment.GetEnvironmentVariable("VAULTSANDBOX_API_KEY")) .Build();
// Create multiple inboxes var inbox1 = await client.CreateInboxAsync(); var inbox2 = await client.CreateInboxAsync();
Console.WriteLine($"Inbox 1: {inbox1.EmailAddress}"); Console.WriteLine($"Inbox 2: {inbox2.EmailAddress}");
// Monitor both inboxes await using var monitor = client.MonitorInboxes(inbox1, inbox2);
await foreach (var evt in monitor.WatchAsync(cancellationToken)) { Console.WriteLine($"\nNew email in {evt.InboxAddress}:"); Console.WriteLine($" Subject: {evt.Email.Subject}"); Console.WriteLine($" From: {evt.Email.From}"); }
// Clean up await client.DeleteInboxAsync(inbox1.EmailAddress); await client.DeleteInboxAsync(inbox2.EmailAddress);}Complete Example
Section titled “Complete Example”Here’s a complete example showing typical client usage:
using VaultSandbox.Client;
async Task Main(CancellationToken cancellationToken){ // Create client var client = VaultSandboxClientBuilder.Create() .WithBaseUrl(Environment.GetEnvironmentVariable("VAULTSANDBOX_URL")) .WithApiKey(Environment.GetEnvironmentVariable("VAULTSANDBOX_API_KEY")) .UseAutoDelivery() .WithMaxRetries(5) .Build();
try { // Verify API key var isValid = await client.ValidateApiKeyAsync(cancellationToken); if (!isValid) { throw new InvalidOperationException("Invalid API key"); }
// Get server info var info = await client.GetServerInfoAsync(cancellationToken); Console.WriteLine($"Connected to VaultSandbox (default TTL: {info.DefaultTtl}s)");
// Create inbox var inbox = await client.CreateInboxAsync(cancellationToken: cancellationToken); Console.WriteLine($"Created inbox: {inbox.EmailAddress}");
// Export for later use await client.ExportInboxToFileAsync(inbox, "./inbox-backup.json", cancellationToken);
// Wait for email var email = await inbox.WaitForEmailAsync(new WaitForEmailOptions { Timeout = TimeSpan.FromSeconds(30), Subject = "Test" }, cancellationToken);
Console.WriteLine($"Received: {email.Subject}");
// Clean up await client.DeleteInboxAsync(inbox.EmailAddress, cancellationToken);
// Delete any other orphaned inboxes var deleted = await client.DeleteAllInboxesAsync(cancellationToken); Console.WriteLine($"Cleaned up {deleted} total inboxes"); } finally { // Dispose the client if (client is IAsyncDisposable asyncDisposable) { await asyncDisposable.DisposeAsync(); } }}Next Steps
Section titled “Next Steps”- IInbox API Reference - Learn about inbox methods
- Email API Reference - Work with email records
- Error Handling - Handle exceptions gracefully
- Import/Export Guide - Advanced import/export usage