ElasticEmail 4.4.0
dotnet add package ElasticEmail --version 4.4.0
NuGet\Install-Package ElasticEmail -Version 4.4.0
<PackageReference Include="ElasticEmail" Version="4.4.0" />
<PackageVersion Include="ElasticEmail" Version="4.4.0" />
<PackageReference Include="ElasticEmail" />
paket add ElasticEmail --version 4.4.0
#r "nuget: ElasticEmail, 4.4.0"
#:package ElasticEmail@4.4.0
#addin nuget:?package=ElasticEmail&version=4.4.0
#tool nuget:?package=ElasticEmail&version=4.4.0
Elastic Email C# SDK
The official .NET client for the Elastic Email REST API v4. Send transactional and marketing email, manage contacts, lists, templates, domains, webhooks and suppressions, and read delivery statistics.
Targets .NET Standard 2.0, so it runs on .NET 6/7/8+, .NET Framework 4.6.1+ and Mono.
Installation
dotnet add package ElasticEmail
Quick start
Elastic Email only sends from verified domains. Before your first send, verify your sending domain and use an address on that domain as the sender.
using ElasticEmail.Api;
using ElasticEmail.Client;
using ElasticEmail.Model;
var config = new Configuration();
config.BasePath = "https://api.elasticemail.com/v4";
config.ApiKey.Add("X-ElasticEmail-ApiKey", Environment.GetEnvironmentVariable("ELASTICEMAIL_API_KEY"));
var emails = new EmailsApi(config);
var message = new EmailTransactionalMessageData(
recipients: new TransactionalRecipient(to: new List<string> { "john.doe@example.com" }),
content: new EmailContent(
from: "My App <no-reply@yourdomain.com>",
subject: "Welcome aboard!",
body: new List<BodyPart>
{
new BodyPart(BodyContentType.HTML, "<h1>Hello!</h1><p>Thanks for signing up.</p>"),
new BodyPart(BodyContentType.PlainText, "Hello! Thanks for signing up.")
}
)
);
try
{
EmailSend result = await emails.EmailsTransactionalPostAsync(message);
Console.WriteLine($"Sent. TransactionID: {result.TransactionID}, MessageID: {result.MessageID}");
}
catch (ApiException e)
{
Console.WriteLine($"Elastic Email API error {e.ErrorCode}: {e.Message}");
}
Keep your API key out of source code: load it from an environment variable, user secrets or a secrets manager. Create one in your API settings.
Retry a send safely (Idempotency-Key)
Pass an Idempotency-Key to EmailsPost, EmailsTransactionalPost or EmailsMergefilePost (or their …Async variants) so a retry after a timeout or a dropped connection can't send the same email twice. If the key was already processed, you get the stored response (same TransactionID and MessageID) and nothing is sent again.
// One key per logical send; reuse it only to retry that same send.
var idempotencyKey = Guid.NewGuid().ToString();
EmailSend result = null;
for (var attempt = 1; result == null; attempt++)
{
var wait = TimeSpan.FromSeconds(2);
try
{
// Returns null when there was no response (network error or timeout).
result = await emails.EmailsTransactionalPostAsync(message, idempotencyKey);
}
catch (ApiException e) when (attempt < 3 && (e.ErrorCode == 409 || e.ErrorCode >= 500))
{
if (e.Headers != null && e.Headers.TryGetValue("Retry-After", out var retryAfter))
wait = TimeSpan.FromSeconds(int.Parse(retryAfter[0]));
}
if (result == null && attempt == 3)
throw new TimeoutException("No response from Elastic Email after 3 attempts.");
if (result == null)
await Task.Delay(wait); // then retry with the same key and the same message
}
Reuse a key only to retry the same send, with the same body, within 24 hours: a different request with the same key returns 422. A 409 means the first request is still running, and a 503 means the key couldn't be checked, so wait for Retry-After and retry with the same key. Without the key, sends work as before.
Signed webhooks
Webhooks can be signed with HMAC-SHA256 and delivered as POST + JSON. Both are chosen when the webhook is created:
var webhookApi = new WebhookApi(config);
var created = await webhookApi.WebhookPostAsync(new WebhookCreatePayload(
name: "my-webhook",
uRL: "https://your-app.example.com/webhook",
notificationForSent: true,
enableSigning: true,
deliveryMethod: WebhookDeliveryMethod.PostJson));
// Returned only now - store it in your secret manager.
Console.WriteLine(created.SigningSecret);
Each request then carries X-ElasticEmail-Timestamp, X-ElasticEmail-Signature: v1=<hex> and X-ElasticEmail-Webhook-Id. To verify it, read the raw body before parsing it, reject timestamps more than 5 minutes off, compute hex(HMAC-SHA256(secret, "{timestamp}\n{METHOD}\n{raw path and query}\n{raw body}")) and compare it with every v1= entry in constant time. Return 401 on a mismatch; the event is retried. Rotate the secret with WebhookByPublicidSecretRotatePostAsync.
Links
- REST API documentation
- Help center
- Full SDK reference (every API method and model)
- Examples for ASP.NET Core and console apps
- Release notes
- Report an issue
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- JsonSubTypes (>= 2.0.1)
- Newtonsoft.Json (>= 13.0.3)
- Polly (>= 8.1.0)
- RestSharp (>= 112.0.0)
- System.ComponentModel.Annotations (>= 5.0.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 |
|---|---|---|
| 4.4.0 | 507 | 10/13/2026 |
| 4.3.0 | 79 | 10/13/2026 |
| 4.2.0 | 3,601 | 8/27/2026 |
| 4.0.30 | 126 | 8/26/2026 |
| 4.0.28 | 2,471 | 5/12/2026 |
| 4.0.27 | 2,756 | 3/12/2026 |
| 4.0.26 | 46,304 | 12/5/2024 |
| 4.0.24 | 15,831 | 7/5/2024 |
| 4.0.23 | 63,180 | 9/26/2023 |
| 4.0.22 | 19,239 | 12/13/2022 |
| 4.0.21 | 5,390 | 5/31/2022 |
| 4.0.19 | 8,561 | 3/15/2022 |
| 4.0.18 | 727 | 2/9/2022 |
| 4.0.17 | 11,677 | 2/9/2022 |
| 4.0.16 | 695 | 1/31/2022 |
| 4.0.15 | 559 | 11/10/2021 |
| 4.0.14 | 1,001 | 8/26/2021 |
| 4.0.13 | 566 | 8/26/2021 |
| 4.0.12 | 690 | 5/27/2021 |
| 4.0.11 | 572 | 5/25/2021 |
Release 4.4.0 - optional Idempotency-Key header for safe retries of email sends