PostKit 10.0.1
dotnet add package PostKit --version 10.0.1
NuGet\Install-Package PostKit -Version 10.0.1
<PackageReference Include="PostKit" Version="10.0.1" />
<PackageVersion Include="PostKit" Version="10.0.1" />
<PackageReference Include="PostKit" />
paket add PostKit --version 10.0.1
#r "nuget: PostKit, 10.0.1"
#:package PostKit@10.0.1
#addin nuget:?package=PostKit&version=10.0.1
#tool nuget:?package=PostKit&version=10.0.1
PostKit
A MimeKit infused implementation of the Postmark API.
Quickstart
Prerequisites
- .NET 8.0 or later
- A Postmark account with a Server API Token
- Verified sender email addresses in your Postmark account
Installation
Install PostKit via NuGet:
dotnet add package PostKit
Configuration
Add PostKit to your services and configure your Postmark API token:
// Program.cs (Minimal API / Web App)
using PostKit;
var builder = WebApplication.CreateBuilder(args);
// Add PostKit to services
builder.Services.AddPostKit();
var app = builder.Build();
Configure your Postmark Server API Token in appsettings.json:
{
"PostKit": {
"ServerApiToken": "your-postmark-server-token-here"
}
}
Or set it via environment variables:
PostKit__ServerApiToken=your-postmark-server-token-here
If you need multiple Postmark configurations (for example, separate servers or tenants), register keyed services with AddKeyedPostKit. Each keyed registration binds to PostKit:{configurationKey}; if you omit configurationKey, the
serviceKey.ToString() value is used.
builder.Services.AddKeyedPostKit("Marketing"); // binds PostKit:Marketing
public enum PostmarkServer
{
Development,
Production
}
builder.Services.AddKeyedPostKit(PostmarkServer.Development); // binds PostKit:Development
builder.Services.AddKeyedPostKit(PostmarkServer.Production, "Default"); // binds PostKit:Default
{
"PostKit": {
"Marketing": { "ServerApiToken": "token-1" },
"Development": { "ServerApiToken": "token-2" },
"Default": { "ServerApiToken": "token-3" }
}
}
Basic Usage
PostKit uses a fluent builder pattern with the following capabilities:
- Email Addresses: Support for simple strings, name/address pairs, or MimeKit
MailboxAddressobjects - Multiple Recipients: Chain
AlsoTo(),AlsoCc(), orAlsoBcc()to add additional recipients - Validation: Automatic validation of email addresses, character limits, and required fields
Simple Email
using PostKit;
// Inject IPostKitClient via dependency injection
public class EmailService
{
private readonly IPostKitClient _postKitClient;
public EmailService(IPostKitClient postKitClient)
{
_postKitClient = postKitClient;
}
public async Task SendWelcomeEmailAsync()
{
var email = Email.CreateBuilder()
.From("noreply@yourapp.com")
.To("user@example.com")
.WithSubject("Welcome to Our Service!")
.WithTextBody("Thank you for signing up!")
.Build();
await _postKitClient.SendEmailAsync(email);
}
}
Rich HTML Email
var email = Email.CreateBuilder()
.From("Sarah Johnson", "sarah@company.com")
.To("customer@example.com")
.WithSubject("Your Order Confirmation")
.WithHtmlBody(@"
<h1>Order Confirmed!</h1>
<p>Thank you for your purchase. Your order #12345 has been confirmed.</p>
<a href='https://yourapp.com/orders/12345'>View Order Details</a>
")
.WithTextBody("Order Confirmed! Thank you for your purchase. Your order #12345 has been confirmed. View details at: https://yourapp.com/orders/12345")
.Build();
await _postKitClient.SendEmailAsync(email);
Multiple Recipients
var email = Email.CreateBuilder()
.From("notifications@company.com")
.To(new[] { "user1@example.com", "user2@example.com" })
.Cc("manager@company.com")
.Bcc("admin@company.com")
.WithSubject("Team Update")
.WithTextBody("Important team announcement...")
.Build();
await _postKitClient.SendEmailAsync(email);
Batch Sending
var welcomeEmail = Email.CreateBuilder()
.From("noreply@yourapp.com")
.To("user1@example.com")
.WithSubject("Welcome!")
.WithTextBody("Thanks for signing up")
.Build();
var reminderEmail = Email.CreateBuilder()
.From("noreply@yourapp.com")
.To("user2@example.com")
.WithSubject("Complete Your Profile")
.WithTextBody("Finish setting up your account")
.Build();
var batchResult = await _postKitClient.SendEmailBatchAsync(new[] { welcomeEmail, reminderEmail });
if (!batchResult.IsSuccessful)
{
foreach (var result in batchResult.Results.Where(result => !result.IsSuccessful))
{
// Inspect result.Email and result.Message to handle the failure.
}
}
Advanced Features
var email = Email.CreateBuilder()
.From("newsletter@company.com")
.To("subscriber@example.com")
.ReplyTo("support@company.com")
.WithSubject("Monthly Newsletter")
.WithHtmlBody("<h1>Newsletter</h1><p>Check out our latest updates!</p>")
.WithTag("newsletter")
.WithMetadata("campaign", "monthly-2024")
.WithMetadata("segment", "premium-users")
.WithOpenTracking(true)
.WithLinkTracking(LinkTracking.HtmlAndText)
.UsingMessageStream(MessageStream.Broadcast)
.WithHeader("X-Campaign-ID", "CAMP-001")
.Build();
await _postKitClient.SendEmailAsync(email);
Attachments and Inline Images
var invoice = Attachment.Create(
name: "invoice.pdf",
contentType: "application/pdf",
content: await File.ReadAllBytesAsync("invoice.pdf"));
var logo = Attachment.Create(
name: "logo.png",
contentType: "image/png",
content: await File.ReadAllBytesAsync("logo.png"),
contentId: "logo@yourapp.com");
var email = Email.CreateBuilder()
.From("billing@company.com")
.To("customer@example.com")
.WithSubject("Your Monthly Invoice")
.WithHtmlBody($"<p>Please find your invoice attached.</p><img src=\"{logo.ContentId}\" alt=\"Company Logo\" />")
.WithAttachment(invoice)
.WithAttachment(logo)
.Build();
await _postKitClient.SendEmailAsync(email);
Size Limits
Postmark limits TextBody and HtmlBody to 5 MB each, and total message size (including attachments) to 10 MB. When batching, Postmark accepts up to 500 emails per batch and batch payloads are limited to 50 MB. PostKit uses a conservative
estimate to prevent grossly oversized requests. Actual size limits will be enforced by the Postmark API.
Error Handling
PostKit uses LightResults for error handling. SendEmailAsync returns a Result<SendEmailResponse> that contains either the response or error information:
var result = await _postKitClient.SendEmailAsync(email);
if (result.IsSuccess(out var response, out var error))
{
// Email sent successfully
Console.WriteLine($"Email sent with MessageId: {response.MessageId}");
}
else
{
// Handle the error
Console.WriteLine($"Failed to send email: {error.Message}");
}
Error Types
PostKit may return different types of errors depending on the failure scenario:
HttpError - Returned for HTTP-level failures (network issues, timeouts, non-422 status codes):
if (error is HttpError httpError)
{
Console.WriteLine($"HTTP error: {httpError.StatusCode} - {httpError.Message}");
}
PostmarkError - Returned for Postmark API validation errors (422 status code):
if (error is PostmarkError postmarkError)
{
Console.WriteLine($"Postmark error: {postmarkError.ErrorCode} - {postmarkError.Message}");
// Handle specific error codes
switch (postmarkError.ErrorCode)
{
case PostmarkErrorCode.SenderSignatureNotFound:
// The From address doesn't have a verified sender signature
break;
case PostmarkErrorCode.InvalidEmailRequest:
// The email request validation failed
break;
case PostmarkErrorCode.NotAllowedToSend:
// Account has run out of credits
break;
}
}
See PostmarkErrorCode enum for the complete list of possible Postmark error codes.
Message Streams
Postmark supports different message streams for different types of emails:
// For transactional emails (default)
.UsingMessageStream(MessageStream.Transactional)
// For broadcast/marketing emails
.UsingMessageStream(MessageStream.Broadcast)
// Or use a custom stream ID
.UsingMessageStream("custom-stream-id")
Complete Console Application Example
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PostKit;
var builder = Host.CreateApplicationBuilder(args);
// Add PostKit
builder.Services.AddPostKit();
var host = builder.Build();
// Get the PostKit client
var postKitClient = host.Services.GetRequiredService<IPostKitClient>();
// Create and send an email
var email = Email.CreateBuilder()
.From("test@yourapp.com")
.To("recipient@example.com")
.WithSubject("Test Email from PostKit")
.WithTextBody("Hello from PostKit! This email was sent using the PostKit library.")
.WithHtmlBody("<h1>Hello from PostKit!</h1><p>This email was sent using the <strong>PostKit</strong> library.</p>")
.Build();
await postKitClient.SendEmailAsync(email);
Console.WriteLine("Email sent successfully!");
Development
The following tables track development progress and map the different Postmark API endpoints to their respective methods in PostKit.
Email API
| Endpoint | Implementation | |
|---|---|---|
| ✅ | Send a single email | IPostKitClient.SendEmailAsync |
| ✅ | Send batch emails | IPostKitClient.SendEmailBatchAsync |
Bulk Email
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Send bulk emails BETA | |
| ✏️ | Get the status/details of a bulk API request BETA |
Bounce API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Get delivery stats | |
| ✏️ | Get bounces | |
| ✏️ | Get a single bounce | |
| ✏️ | Get bounce dump | |
| ✏️ | Activate a bounce | |
| ✏️ | Bounce types | |
| ✏️ | Rebound |
Templates API
| Endpoint | Implementation | |
|---|---|---|
| ✅ | Send email with template | IPostKitClient.SendEmailAsync |
| ✅ | Send batch with templates | IPostKitClient.SendEmailBatchAsync |
| ✏️ | Push templates to another server | |
| ✏️ | Get a template | |
| ✏️ | Create a template | |
| ✏️ | Edit a template | |
| ✏️ | List templates | |
| ✏️ | Delete a template | |
| ✏️ | Validate a template |
Server API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Get the server | |
| ✏️ | Edit the server |
Servers API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Get a server | |
| ✏️ | Create a server | |
| ✏️ | Edit a server | |
| ✏️ | List servers | |
| ✏️ | Delete a server |
Message Streams API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | List message streams | |
| ✏️ | Get a message stream | |
| ✏️ | Edit a message stream | |
| ✏️ | Create a message stream | |
| ✏️ | Archive a message stream | |
| ✏️ | Unarchive a message stream |
Messages API
Domains API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | List domains | |
| ✏️ | Get domain details | |
| ✏️ | Create domain | |
| ✏️ | Edit domain | |
| ✏️ | Delete domain | |
| ✏️ | Verify DKIM | |
| ✏️ | Verify Return-Path | |
| ✏️ | Verify an SPF record | |
| ✏️ | Rotate DKIM keys |
Sender signatures API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | List sender signatures | |
| ✏️ | Get sender signature | |
| ✏️ | Create a signature | |
| ✏️ | Edit a signature | |
| ✏️ | Delete a signature | |
| ✏️ | Resend a confirmation | |
| ✏️ | Verify an SPF record | |
| ✏️ | Request a new DKIM |
Stats API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Get outbound overview | |
| ✏️ | Get sent counts | |
| ✏️ | Get bounce counts | |
| ✏️ | Get spam complaints | |
| ✏️ | Get tracked email counts | |
| ✏️ | Get email open counts | |
| ✏️ | Get email platform usage | |
| ✏️ | Get email client usage | |
| ✏️ | Get click counts | |
| ✏️ | Get browser usage | |
| ✏️ | Get browser platform usage | |
| ✏️ | Get click location |
Triggers: Inbound rules
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | List inbound rule triggers | |
| ✏️ | Create an inbound rule trigger | |
| ✏️ | Delete a single trigger |
Webhooks API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | List webhooks | |
| ✏️ | Get a webhook | |
| ✏️ | Create a webhook | |
| ✏️ | Edit a webhook | |
| ✏️ | Delete a webhook |
Suppressions API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Suppression dump | |
| ✏️ | Create a Suppression | |
| ✏️ | Delete a Suppression |
Data Removal API
| Endpoint | Implementation | |
|---|---|---|
| ✏️ | Create a Data Removal request | |
| ✏️ | Check a Data Removal request status |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- JetBrains.Annotations (>= 2025.2.4)
- LightResults (>= 10.0.1)
- Microsoft.Extensions.Http (>= 10.0.1)
- Microsoft.Extensions.Telemetry.Abstractions (>= 10.1.0)
- MimeKit (>= 4.14.0)
-
net8.0
- JetBrains.Annotations (>= 2025.2.4)
- LightResults (>= 10.0.1)
- Microsoft.Extensions.Http (>= 10.0.1)
- Microsoft.Extensions.Telemetry.Abstractions (>= 10.1.0)
- MimeKit (>= 4.14.0)
-
net9.0
- JetBrains.Annotations (>= 2025.2.4)
- LightResults (>= 10.0.1)
- Microsoft.Extensions.Http (>= 10.0.1)
- Microsoft.Extensions.Telemetry.Abstractions (>= 10.1.0)
- MimeKit (>= 4.14.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.1 | 218 | 12/22/2025 |
| 10.0.0 | 270 | 12/16/2025 |
| 10.0.0-preview.1 | 543 | 11/15/2025 |
| 9.0.0-preview.7 | 363 | 10/13/2025 |
| 9.0.0-preview.6 | 134 | 10/13/2025 |
| 9.0.0-preview.5 | 629 | 10/8/2025 |
| 9.0.0-preview.4 | 154 | 9/24/2025 |
| 9.0.0-preview.3 | 141 | 9/24/2025 |
| 9.0.0-preview.2 | 896 | 12/22/2024 |
| 9.0.0-preview.1 | 91 | 12/21/2024 |
