Southport.Messaging.Email.SendGrid
10.0.5
dotnet add package Southport.Messaging.Email.SendGrid --version 10.0.5
NuGet\Install-Package Southport.Messaging.Email.SendGrid -Version 10.0.5
<PackageReference Include="Southport.Messaging.Email.SendGrid" Version="10.0.5" />
<PackageVersion Include="Southport.Messaging.Email.SendGrid" Version="10.0.5" />
<PackageReference Include="Southport.Messaging.Email.SendGrid" />
paket add Southport.Messaging.Email.SendGrid --version 10.0.5
#r "nuget: Southport.Messaging.Email.SendGrid, 10.0.5"
#:package Southport.Messaging.Email.SendGrid@10.0.5
#addin nuget:?package=Southport.Messaging.Email.SendGrid&version=10.0.5
#tool nuget:?package=Southport.Messaging.Email.SendGrid&version=10.0.5
Southport.Messaging.Email.SendGrid
SendGrid implementation of Southport.Messaging.Email.Core. It provides a fluent message builder that sends one SendGrid API request per recipient, with per-recipient substitutions, custom arguments, attachments, dynamic templates, categories, batch IDs, scheduled delivery, and tracking settings.
Targets net9.0 and net10.0. Licensed under MIT.
Installation
Available on NuGet.
dotnet add package Southport.Messaging.Email.SendGrid
Configuration
Add a SendGrid section to appsettings.json:
{
"SendGrid": {
"ApiKey": "SG.xxxxxxxx",
"UseTestMode": false,
"TestEmailAddresses": ""
}
}
| Option | Description |
|---|---|
ApiKey |
SendGrid API key with mail send permission. Required. |
UseTestMode |
When true, every message is sent with SendGrid sandbox mode enabled. SendGrid validates the request but does not deliver it. Can be overridden per message with SetTestMode. |
TestEmailAddresses |
Comma separated list. When set, every message is delivered to these addresses instead of the real recipients. CC and BCC addresses are dropped and a custom argument IsTest=true is added. |
Register the services:
builder.Services.AddSendGridServices(builder.Configuration.GetSection("SendGrid"));
Or pass the options directly:
builder.Services.AddSendGridServices(new SendGridOptions
{
ApiKey = "SG.xxxxxxxx",
UseTestMode = true
});
Both overloads register ISendGridMessageFactory and IDynamicTemplateService as typed HTTP clients.
Sending a message
Inject ISendGridMessageFactory and build a message from it. Each message is disposable and
should be used once.
public class WelcomeMailer(ISendGridMessageFactory factory)
{
public async Task SendAsync(string toAddress, CancellationToken cancellationToken)
{
await using var message = factory.Create();
var results = await message
.SetFromAddress("no-reply@example.com", "Example")
.AddToAddress(toAddress)
.SetSubject("Welcome")
.SetHtml("<p>Thanks for signing up.</p>")
.SetText("Thanks for signing up.")
.Send(cancellationToken);
foreach (var result in results)
{
if (result.IsSuccessful == false)
{
// result.Message contains the SendGrid response body.
}
}
}
}
Send returns one IEmailResult per recipient. A SouthportMessagingException is thrown
before any request is made when the from address is missing, there are no valid recipients,
or the message has no text, HTML, or template.
Recipients
AddToAddress, AddCcAddress, and AddBccAddress accept a plain address or a typed
EmailRecipient / EmailAddress. Addresses that fail validation are kept on the message but
are not sent to. Each recipient gets its own API request. CC and BCC addresses are attached to
every recipient's request, except where the address matches the recipient or appears in both
lists.
Substitutions and custom arguments
Message-level substitutions apply to every recipient. Recipient-level substitutions override them.
await using var message = factory.Create();
var results = await message
.SetFromAddress("no-reply@example.com")
.AddToAddress(new EmailRecipient("alice@example.com",
substitutions: new Dictionary<string, object> { ["FirstName"] = "Alice" }))
.AddSubstitution("Company", "Example")
.SetSubject("Hello")
.SetText("Hi {{FirstName}}, welcome to {{Company}}.")
.Send(substitute: true);
With substitute: true, text and HTML bodies are rendered with Handlebars before sending.
With a template ID set, substitutions are sent as dynamic template data instead and SendGrid
renders them.
AddCustomArgument attaches key/value pairs to the message for use in SendGrid event webhooks.
Recipient-level custom arguments override message-level ones.
Dynamic templates
await message
.SetFromAddress("no-reply@example.com")
.AddToAddress("alice@example.com")
.SetTemplate("d-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.AddSubstitution("FirstName", "Alice")
.Send();
IDynamicTemplateService.GetTemplateVersion(templateId, versionId, cancellationToken) fetches a
template version from the SendGrid API.
Attachments
Attachments can be added at the message level with AddAttachments, or per recipient through
EmailRecipient.Attachments. Three attachment types are supported:
// Stream
message.AddAttachments(new EmailAttachmentStream(stream, "report.pdf", "application/pdf"));
// Byte array
message.AddAttachments(new EmailAttachmentBytes(bytes, "report.pdf", "application/pdf"));
// Plain string, encoded to base64 by the library
message.AddAttachments(new EmailAttachmentString("Some text.", "notes.txt"));
// String that is already base64 encoded, sent as is
message.AddAttachments(new EmailAttachmentString(base64Content, "report.pdf", "application/pdf", isBase64Encoded: true));
Each attachment is base64 encoded once and the encoded content is reused for every recipient.
When IsBase64Encoded is true on an EmailAttachmentString, the content is passed to SendGrid
without re-encoding.
Other options
| Method | Effect |
|---|---|
SetReplyTo |
Sets the reply-to address. |
AddCategory / AddCategories |
Adds SendGrid categories. |
AddHeader |
Adds a custom header. |
SetDeliveryTime |
Schedules delivery for a future time. |
SetBatchId |
Uses an existing batch ID. Send(substitute, batch: true) requests a new batch ID from SendGrid and applies it to every recipient's request. |
SetTestMode |
Enables SendGrid sandbox mode for this message. Defaults to UseTestMode from options. |
SetTracking / SetTrackingClicks / SetTrackingOpens |
Controls click and open tracking. Both default to enabled. |
Build and test
dotnet build
dotnet test
The tests send real messages through SendGrid. They read the API key from
Southport.Messaging.Email.SendGrid.Test/appsettings.json or from the APIKEY and
USETESTMODE environment variables.
Contributing
Issues and pull requests are welcome at github.com/southportsolutions/Southport.Messaging.Email.SendGrid.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Handlebars.Net (>= 2.4.3)
- Microsoft.Extensions.Http (>= 10.0.13)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.13)
- SendGrid (>= 9.29.3)
- Southport.Messaging.Email.Core (>= 10.0.5)
-
net9.0
- Handlebars.Net (>= 2.4.3)
- Microsoft.Extensions.Http (>= 9.0.21)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.21)
- SendGrid (>= 9.29.3)
- Southport.Messaging.Email.Core (>= 10.0.5)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Southport.Messaging.Email.SendGrid:
| Package | Downloads |
|---|---|
|
Southport.Azure.Functions.Extensions
Package Description |
|
|
Southport.Azure.Functions.Isolated.Extensions
Initial Release |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.5 | 141 | 10/13/2026 |
| 10.0.4 | 117 | 10/8/2026 |
| 10.0.0 | 1,382 | 1/1/2026 |
| 8.0.2 | 1,541 | 6/18/2024 |
| 8.0.1 | 355 | 6/12/2024 |
| 8.0.0 | 1,261 | 2/17/2024 |
| 2.3.2 | 2,952 | 2/16/2023 |
| 2.3.1 | 876 | 12/29/2022 |
| 2.3.0 | 462 | 12/29/2022 |
| 2.2.0 | 437 | 12/28/2022 |
| 2.1.0 | 531 | 11/30/2022 |
| 2.0.1 | 2,254 | 3/19/2022 |
| 2.0.0 | 643 | 3/19/2022 |
| 1.0.2 | 641 | 3/4/2022 |
| 1.0.1 | 6,968 | 8/6/2021 |
| 1.0.0 | 741 | 7/31/2021 |
| 1.0.0-beta1 | 407 | 7/29/2021 |
Attachment encoding.