LettermintLettermint
  • Knowledge base
  • Community
  • Changelog
  • Support
  • Documentation
  • Sending API
  • Team API
  • MCP server
Get started
Send email
    Send with
      SDKs
        Node.jsPHPPythonGoJava.NETElixir
      Frameworks
    SMTP
    Email activitySchedulingTest emailsTLSIdempotencySuppressionsTagsInline imagesData retentionSending limits
    Tracking
Receive email
Manage
Resources
SDKs

.NET

Use the official Lettermint .NET SDK to send email from a C# application. The SDK also supports the Team API and webhook signature verification. See SDKs and integrations for other packages.

Requirements

Before you start, you need:

  • The .NET SDK for your application, targeting .NET 8 or newer
  • A Lettermint account with a verified sending domain
  • A Project API token from your project settings

1. Installation

Install the Lettermint NuGet package from your application directory:

TerminalCode
dotnet add package Lettermint

The package includes targets for .NET 8 and .NET 10.

2. Send your first email

Set LETTERMINT_PROJECT_TOKEN in your application's environment. Use a Project API token for email sends.

Add this code to a console application's Program.cs:

Code
using System; using Lettermint; var projectToken = Environment.GetEnvironmentVariable("LETTERMINT_PROJECT_TOKEN"); if (string.IsNullOrWhiteSpace(projectToken)) { throw new InvalidOperationException("Set LETTERMINT_PROJECT_TOKEN before sending email."); } using var email = LettermintClient.Email(projectToken); var response = await email .From("Example <hello@yourdomain.com>") .To("recipient@example.com") .Subject("Hello from Lettermint") .Html("<h1>Hello!</h1><p>This is a test email.</p>") .Text("Hello! This is a test email.") .SendAsync(); Console.WriteLine($"Email ID: {response.MessageId}"); Console.WriteLine($"Status: {response.Status}");

Replace the sender with an address on your verified domain. Replace the recipient with your test address, then run the application:

TerminalCode
dotnet run --project path/to/YourApp.csproj

Keep the email client for repeated requests. Dispose it when your application no longer needs it. Each email.From(...) or email.Compose() call creates a new email builder. Use a new builder for each email. Do not share a builder between concurrent sends.

3. Email options

The examples below use the email client from the previous section.

Recipients, reply-to, and headers

Code
using System.Collections.Generic; await email .From("Support <support@yourdomain.com>") .To("customer@example.com", "colleague@example.com") .Cc("manager@yourdomain.com") .Bcc("archive@yourdomain.com") .ReplyTo("help@yourdomain.com") .Subject("Support ticket 12345") .Headers(new Dictionary<string, string> { ["X-Ticket-ID"] = "12345" }) .Text("Your support ticket has an update.") .SendAsync();

Headers sets email headers. Use IdempotencyKey for the HTTP idempotency header.

Tags and metadata

Code
using System.Collections.Generic; using Lettermint.Models; await email .From("orders@yourdomain.com") .To("customer@example.com") .Subject("Order 12345 confirmed") .Text("Your order is confirmed.") .Tags(new SendMailRequestTagsItem { Name = "category", Value = "order-confirmation" }) .Metadata(new Dictionary<string, string> { ["order_id"] = "12345", ["customer_id"] = "cust_789" }) .SendAsync();

Use Tags for named tags or Tag("order-confirmation") for a single tag. Metadata values must be strings. Lettermint includes metadata in webhook payloads so you can connect delivery events to application records. See tags for tag options.

Route and delivery settings

Code
using Lettermint.Models; await email .From("notifications@yourdomain.com") .To("recipient@example.com") .Subject("Your account is ready") .Text("You can now sign in.") .Route("transactional") .Settings(new SendMailRequestSettings { Tls = TlsPolicy.Enforced }) .SendAsync();

Route selects a route by its slug. TlsPolicy.Enforced requires TLS for email delivery. See TLS for delivery behavior.

Idempotency

Set a key to prevent duplicate emails when your application repeats a send:

Code
await email .From("orders@yourdomain.com") .To("customer@example.com") .Subject("Order 12345 confirmed") .Text("Your order is confirmed.") .IdempotencyKey("order-confirmation-12345") .SendAsync();

Use the same key when you retry the same email. The SDK does not retry requests automatically. See idempotency for the API rules and retention window.

File attachments

Read the file and encode its content as Base64:

Code
using System; using System.IO; var content = Convert.ToBase64String(await File.ReadAllBytesAsync("/path/to/invoice.pdf")); await email .From("invoices@yourdomain.com") .To("customer@example.com") .Subject("Your invoice") .Text("Your invoice is attached.") .Attach("invoice.pdf", content, contentType: "application/pdf") .SendAsync();

For an inline image, pass contentId to Attach and use the matching cid: reference in the HTML body. See inline images.

Scheduled emails

Use a future timestamp with an explicit time zone:

Code
using System; var scheduled = await email .From("reminders@yourdomain.com") .To("recipient@example.com") .Subject("Appointment reminder") .Text("Your appointment starts in one hour.") .ScheduledAt(DateTimeOffset.UtcNow.AddHours(1).ToString("O")) .SendAsync(); Console.WriteLine(scheduled.MessageId); Console.WriteLine(scheduled.ScheduledAt);

The client also provides RescheduleAsync and CancelAsync. See email scheduling for scheduling limits and cancellation behavior.

4. Responses and errors

SendAsync() returns a typed response with MessageId and Status. API acceptance does not confirm delivery. Use webhooks to receive delivery and bounce events.

Catch API failures before other SDK failures:

Code
using System; using Lettermint; try { var response = await email .From("hello@yourdomain.com") .To("recipient@example.com") .Subject("Hello") .Text("This is a test email.") .SendAsync(); Console.WriteLine(response.MessageId); } catch (LettermintApiException exception) { Console.Error.WriteLine($"Lettermint rejected the request: HTTP {(int)exception.StatusCode}."); } catch (LettermintException exception) { Console.Error.WriteLine($"The request failed: {exception.Message}"); }

LettermintApiException also exposes ResponseBody, with the token removed. Other SDK failures, including network, timeout, and response parsing failures, use LettermintException. If you cancel a request with a CancellationToken, it throws OperationCanceledException.

To change the default request timeout, pass ClientOptions when you create the client:

Code
using System; using Lettermint; using var emailWithTimeout = LettermintClient.Email(projectToken, new ClientOptions { Timeout = TimeSpan.FromSeconds(15) });

Team API

Use a separate Team API token to manage team resources. Set it in LETTERMINT_TEAM_TOKEN:

Code
using System; using Lettermint; var teamToken = Environment.GetEnvironmentVariable("LETTERMINT_TEAM_TOKEN"); if (string.IsNullOrWhiteSpace(teamToken)) { throw new InvalidOperationException("Set LETTERMINT_TEAM_TOKEN before using the Team API."); } using var api = LettermintClient.Api(teamToken); var page = await api.Domains.ListAsync(); foreach (var domain in page.Data ?? []) { Console.WriteLine(domain.Domain); }

Do not use a Team API token with the email client. See the Team API quickstart for token setup and permissions.

Track delivery, opens, and bounces

Enable tracking on your sending route to record opens and clicks. Subscribe to webhooks for delivery and bounce events.

The SDK provides Webhook.Verify(rawBody, signatureHeader, signingSecret) to verify webhook signatures. Pass the original request body without changes. Invalid signatures throw WebhookVerificationException. See webhook signature verification for the header and signing secret.

Next steps

Tags

Organize emails with tags.

Webhooks

Receive delivery and bounce events.

Test addresses

Test delivery and bounce handling.

Team API

Manage team resources.

GitHub repository

Read the source code or report an issue.

JavaElixir
On this page
  • Requirements
  • 1. Installation
  • 2. Send your first email
  • 3. Email options
    • Recipients, reply-to, and headers
    • Tags and metadata
    • Route and delivery settings
    • Idempotency
    • File attachments
    • Scheduled emails
  • 4. Responses and errors
  • Team API
  • Track delivery, opens, and bounces
  • Next steps
C#
C#
C#
C#
C#
C#
C#
C#
C#
C#