Providers

Eight provider packages implement IEmailProvider. Each accepts an options object with the credentials and transport settings it needs. Register any of them with UseProvider (or a factory) in AddMailForge.

services.AddMailForge(builder => builder
    .UseDefaultFrom("noreply@example.com")
    .UseProvider(new ResendEmailProvider(new ResendOptions { ApiKey = "re_..." })));

Capability Matrix

Provider Package Attachments Inline images Headers Tags
SMTP MailForge.Smtp ✓ ✓ ✓ ✓
Amazon SES MailForge.AmazonSES ✓ ✓ ✓ ✓
Postmark MailForge.Postmark ✓ ✓ ✓ ✓
Mailgun MailForge.Mailgun ✓ ✓ ✓ ✓
Brevo MailForge.Brevo ✓ ✓ ✓ ✓
Resend MailForge.Resend ✓ ✗ ✓ ✓
ZeptoMail MailForge.ZeptoMail ✓ ✓ ✗ ✗
Azure Communication Services MailForge.AzureCS ✓ ✓¹ ✓ ✗

¹ Azure CS has no cid: attachment mechanism; inline images are rewritten as data: URIs in the HTML body.

SMTP (MailForge.Smtp)

var provider = new SmtpEmailProvider(new SmtpOptions
{
    Host = "smtp.example.com",
    Port = 587,
    SecureSocketOptions = SecureSocketOptions.StartTls,
    Username = "user",
    Password = "secret",
    LocalDomain = "local",
    TimeoutMilliseconds = 30000
});

Built on MailKit. Validation is deferred to the SMTP server, so invalid recipients surface as delivery failures rather than validation errors.

Amazon SES (MailForge.AmazonSES)

var provider = new AmazonSesEmailProvider(new AmazonSesOptions
{
    Region = "us-east-1",
    AccessKey = "...",      // optional; the SDK default credential chain is used when absent
    SecretKey = "...",
    ConfigurationSetName = null,
    MaxErrorRetry = 3
});

Messages are sent through the raw-message API. Credentials fall back to the standard AWS credential chain (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY, profiles, IAM roles).

Postmark (MailForge.Postmark)

var provider = new PostmarkEmailProvider(new PostmarkOptions
{
    ServerToken = "server-token",
    MessageStream = "outbound"   // default
});

BaseUri and Timeout are configurable. Attachments use Postmark's inline attachment format, so inline images work out of the box.

Mailgun (MailForge.Mailgun)

var provider = new MailgunEmailProvider(new MailgunOptions
{
    ApiKey = "key-...",
    Domain = "mg.example.com"   // required
});

The domain must be verified with Mailgun. BaseUri and Timeout are configurable.

Brevo (MailForge.Brevo)

var provider = new BrevoEmailProvider(new BrevoOptions { ApiKey = "xkeysib-..." });

BaseUri and Timeout are configurable.

Resend (MailForge.Resend)

var provider = new ResendEmailProvider(new ResendOptions { ApiKey = "re_..." });

Resend does not support inline images; mark the capabilities accordingly (see the matrix). BaseUri and Timeout are configurable.

Zoho ZeptoMail (MailForge.ZeptoMail)

var provider = new ZeptoMailEmailProvider(new ZeptoMailOptions { SendApiKey = "..." });

Headers and tags are not supported by the ZeptoMail API; any Headers/Tags on a message are dropped. BaseUri and Timeout are configurable.

Azure Communication Services (MailForge.AzureCS)

var provider = new AzureCSEmailProvider(new AzureCSOptions
{
    Endpoint = "https://my-resource.communication.azure.com",
    AccessKey = "base64-access-key",   // as it appears in the connection string
    SenderAddress = "noreply@verified-domain.com"
});
  • Requests are signed with HMAC-SHA256; AccessKey is Base64-decoded before signing.
  • The sender must match a domain verified for the resource — Azure does not allow arbitrary From addresses.
  • Tags are not supported (dropped).

Using a Provider with Dependency Injection

Providers are plain objects; register them yourself and supply a factory:

services.AddSingleton(new ResendEmailProvider(new ResendOptions { ApiKey = Config.Resend }));

services.AddMailForge(builder => builder
    .UseDefaultFrom("noreply@example.com")
    .UseProvider(sp => sp.GetRequiredService<ResendEmailProvider>()));

See Failover to route across multiple providers.