Amazon S3 Storage Provider

Highly scalable object storage with S3 and S3-compatible services support.

Universal S3 Support

AWS S3MinIOWasabiKMS EncryptionLifecycle Rules

Installation

dotnet add package Zetian
dotnet add package Zetian.Storage.AmazonS3

Quick Start

QuickStart.cs
using Zetian.Server;
using Zetian.Storage.AmazonS3.Extensions;

// Basic S3 setup
var server = new SmtpServerBuilder()
    .Port(25)
    .WithS3Storage(
        "AKIAIOSFODNN7EXAMPLE",
        "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "my-smtp-bucket")
    .Build();

await server.StartAsync();

S3-Compatible Services

Works with MinIO, Wasabi, DigitalOcean Spaces, and more:

S3Compatible.cs
// MinIO, Wasabi, or other S3-compatible services
var server = new SmtpServerBuilder()
    .Port(25)
    .WithS3CompatibleStorage(
        "http://localhost:9000", // MinIO endpoint
        "minioadmin",
        "minioadmin",
        "smtp-messages",
        config =>
        {
            config.ForcePathStyle = true; // Required for MinIO
            config.Region = "us-east-1";
        })
    .Build();

// Wasabi example
var server = new SmtpServerBuilder()
    .Port(25)
    .WithS3CompatibleStorage(
        "https://s3.wasabisys.com",
        "accessKey",
        "secretKey",
        "my-bucket",
        config =>
        {
            config.Region = "us-east-1";
        })
    .Build();

MinIO

Self-hosted S3 alternative

Wasabi

80% cheaper than S3

Backblaze B2

Cost-effective storage

Advanced Configuration

AdvancedConfig.cs
var server = new SmtpServerBuilder()
    .Port(25)
    .WithS3Storage(
        accessKeyId: Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID"),
        secretAccessKey: Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY"),
        bucketName: "smtp-messages",
        config =>
        {
            config.Region = "us-west-2";
            config.KeyPrefix = "emails/";
            
            // Server-side encryption
            config.EnableServerSideEncryption = true;
            config.KmsKeyId = "alias/my-kms-key";
            
            // Versioning
            config.EnableVersioning = true;
            
            // Storage class
            config.StorageClass = S3StorageClass.StandardInfrequentAccess;
            
            // Performance
            config.UseTransferAcceleration = true;
            config.CompressMessageBody = true;
        })
    .Build();

Lifecycle Management

Automatically transition objects between storage classes:

Lifecycle.json
// Lifecycle rules for automatic management
{
  "Rules": [{
    "Id": "ArchiveOldEmails",
    "Status": "Enabled",
    "Transitions": [
      {
        "Days": 30,
        "StorageClass": "STANDARD_IA"
      },
      {
        "Days": 90,
        "StorageClass": "GLACIER"
      },
      {
        "Days": 365,
        "StorageClass": "DEEP_ARCHIVE"
      }
    ],
    "Expiration": {
      "Days": 730
    }
  }]
}

// Apply lifecycle policy
var lifecycleConfig = new LifecycleConfiguration
{
    Rules = new List<LifecycleRule>
    {
        new LifecycleRule
        {
            Id = "EmailArchiving",
            Status = LifecycleRuleStatus.Enabled,
            Transitions = new List<Transition>
            {
                new Transition { Days = 30, StorageClass = S3StorageClass.StandardInfrequentAccess },
                new Transition { Days = 90, StorageClass = S3StorageClass.Glacier }
            }
        }
    }
};

Storage Classes

Standard: Frequently accessed data
Standard-IA: Infrequent access (30+ days)
Glacier Instant: Archive with millisecond retrieval
Glacier Flexible: 1-12 hour retrieval
Glacier Deep Archive: 12-48 hour retrieval

Encryption Options

Encryption.cs
// KMS encryption for sensitive data
var putRequest = new PutObjectRequest
{
    BucketName = "smtp-messages",
    Key = "email-123.eml",
    ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS,
    ServerSideEncryptionKeyManagementServiceKeyId = "arn:aws:kms:us-west-2:111122223333:key/abc123"
};

// Customer-provided encryption keys
var putRequest = new PutObjectRequest
{
    BucketName = "smtp-messages",
    Key = "email-123.eml",
    ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
    ServerSideEncryptionCustomerProvidedKey = "base64-encoded-256-bit-key",
    ServerSideEncryptionCustomerProvidedKeyMD5 = "base64-encoded-md5"
};

Configuration Options

OptionDefaultDescription
BucketNamerequiredS3 bucket name
Region"us-east-1"AWS region
KeyPrefix"smtp/"Object key prefix
StorageClassStandardDefault storage class
EnableServerSideEncryptiontrueEncryption method
EnableVersioningfalseEnable object versioning

Security Best Practices

Use IAM Roles

Avoid hardcoding credentials

Enable Encryption

Use KMS for sensitive data

Bucket Policies

Restrict access properly

Enable Versioning

Protect against overwrites

Cost Optimization

💡

Use appropriate storage classes

Standard-IA for infrequent access saves 45%

💡

Set lifecycle policies

Automatically transition to cheaper tiers

💡

Consider S3-compatible alternatives

Wasabi or Backblaze B2 for lower costs

💡

Enable compression

Reduce storage and transfer costs