StrongGrid C# Client Library

repository·develop·Indexed 41 days ago

https://github.com/jericho/stronggrid

A strongly typed C# client library for the SendGrid v3 API, providing full type safety for all resources, including email sending, contact management, and API key creation. It features a built-in IP warmup engine, a webhook parser for Event and Inbound Parse webhooks, and support for Dynamic Templates with Handlebars. Compatible with .NET Framework 4.8 and .NET Standard 2.1.

Tokens
4.3K
Snippets
9
Records
12
Agent score
2%

What's inside StrongGrid

  1. Overview of StrongGrid capabilities

    develop

    StrongGrid is a strongly typed library for interacting with the SendGrid v3 API. Unlike the official SendGrid C# client which historically relied on dynamic types, StrongGrid provides full type safety for all SendGrid resources.

    Key features include:

    • Full API Resource Access: Interact with all SendGrid endpoints, including sending emails, managing lists, contacts, segments, searching for contacts, and creating API keys.
    • Webhook Parsing: Includes a parser for SendGrid webhooks sent to your WebAPI, supporting both the Event Webhook and the Inbound Parse Webhook.
    • IP Warmup Engine: A built-in engine to warmup IP addresses using a custom schedule.
    • Strong Typing: Replaces dynamic usage with concrete types for better developer experience and compile-time safety.
  2. Use Dynamic Templates with Handlebars

    develop

    StrongGrid supports SendGrid's Dynamic Templates which use Handlebars syntax for merge fields.

    Workflow:

    1. Create the template: Use Templates.CreateAsync with TemplateType.Dynamic.
    2. Create a version: Use Templates.CreateVersionAsync. You can provide testData (an anonymous object) which is used by the SendGrid UI for previewing but is never sent to recipients.
    3. Send the email: Use Mail.SendToSingleRecipientAsync, passing the templateId and a dynamicData object containing the actual values for the merge fields.
    // 1. Create dynamic template
    var dynamicTemplate = await strongGridClient.Templates.CreateAsync("My dynamic template", TemplateType.Dynamic).ConfigureAwait(false);
    
    // 2. Create version with Handlebars and test data
    var subject = "Dear {{Customer.first_name}}";
    var htmlContent = "<html><body>Hello {{Customer.first_name}} {{Customer.last_name}}.</body></html>";
    var testData = new { Customer = new { first_name = "aaa", last_name = "aaa" } };
    await strongGridClient.Templates.CreateVersionAsync(dynamicTemplate.Id, "Version 1", subject, htmlContent, "text", true, EditorType.Code, testData).ConfigureAwait(false);
    
    // 3. Send using dynamic data
    var dynamicData = new { Customer = new { first_name = "Bob", last_name = "Smith" } };
    var to = new MailAddress("bob@example.com", "Bob Smith");
    var from = new MailAddress("test@example.com", "John Smith");
    var messageId = await strongGridClient.Mail.SendToSingleRecipientAsync(to, from, dynamicTemplate.Id, dynamicData).ConfigureAwait(false);
  3. Initialize the StrongGrid Client

    develop

    To use StrongGrid, you must instantiate a StrongGrid.Client using your SendGrid API key. If your environment requires a proxy, you can pass a WebProxy instance to the constructor.

    Important Lifetime Management: By default, StrongGrid.Client creates its own HttpClient. To avoid socket exhaustion under heavy load, you should:

    1. Reuse the client: Instantiate StrongGrid.Client once and reuse it throughout your application's lifetime.
    2. Provide your own HttpClient: If you need to create multiple clients, pass your own managed HttpClient to the constructor to ensure proper lifetime management.
    // Basic initialization
    var apiKey = "... your api key...";
    var strongGridClient = new StrongGrid.Client(apiKey);
    
    // Initialization with a proxy
    var proxy = new WebProxy("http://myproxy:1234");
    var strongGridClient = new StrongGrid.Client(apiKey, proxy);
  4. Install StrongGrid via NuGet

    develop

    To include StrongGrid in your C# project, add the NuGet package using the Package Manager Console:

    PM> Install-Package StrongGrid

    After installation, include the following namespace in your code to access the library's features:

    using StrongGrid;
  5. Use the Warmup Engine for IP addresses

    develop

    The WarmupEngine helps manage the process of warming up new IP addresses by gradually increasing daily email volume.

    Configuration

    • WarmupSettings: Defines the pool name, daily volume increments (e.g., new[] { 50, 100, 500 }), and resetDays (how often the volume resets).
    • WarmupEngine: The main engine that executes the warmup. It requires WarmupSettings and a StrongGrid.Client.
    • Progress Repository: The engine needs to track progress.
      • FileSystemWarmupProgressRepository: Saves progress to a local folder (recommended for production).
      • MemoryWarmupProgressRepository: Saves progress in memory (use for testing only; progress is lost on restart).
      • IWarmupProgressRepository: Interface for custom implementations (e.g., Database, Azure, AWS).

    Workflow

    1. Initialize: Create WarmupSettings and WarmupEngine.
    2. Prepare IPs:
      • Use PrepareWithExistingIpAddressesAsync(ipAddresses) if you already have IPs.
      • Use PrepareWithNewIpAddressesAsync(count, subusers) to purchase and add new IPs automatically.
    3. Send: Use warmupEngine.SendToSingleRecipientAsync(...) or similar. The engine automatically handles splitting volume between the warmup pool and the default IP address when limits are reached.
    4. Completion: Once the process finishes, the IP pool is deleted and IPs return to the default pool.
    // 1. Setup
    var warmupSettings = WarmupSettings.FromSendGridRecomendedSettings("warmup_pool", 50000, 1);
    var warmupEngine = new WarmupEngine(warmupSettings, client, new FileSystemWarmupProgressRepository(@"C:\temp"));
    
    // 2. Prepare (Run once)
    await warmupEngine.PrepareWithExistingIpAddressesAsync(new[] { "168.245.123.132" }, CancellationToken.None);
    
    // 3. Send via engine
    var result = warmupEngine.SendToSingleRecipientAsync(to, from, subject, html, text);
  6. Register StrongGrid with Dependency Injection

    develop

    If you are using Microsoft.Extensions.DependencyInjection, StrongGrid provides an extension method AddStrongGrid to register and manage the lifetime of StrongGrid.IClient and its underlying HttpClient automatically. This is the recommended approach for .NET web apps, worker services, and console apps using a Generic Host to prevent socket exhaustion.

    For other IoC containers (Autofac, SimpleInjector, etc.), you must register the services manually following similar singleton/scoped patterns.

    // For .NET 8+ Web Applications
    var builder = WebApplication.CreateBuilder(args);
    var sendGridApiKey = builder.Configuration["SendGridApiKey"];
    builder.Services.AddStrongGrid(sendGridApiKey);
    var app = builder.Build();
    
    // Usage in a service via constructor injection
    public class MyEmailService
    {
        private readonly StrongGrid.IClient _strongGridClient;
        public MyEmailService(StrongGrid.IClient strongGridClient)
        {
            _strongGridClient = strongGridClient;
        }
        public async Task SendEmailAsync()
        {
            await _strongGridClient.Mail.SendToSingleRecipientAsync(/* details */);
        }
    }
  7. Send transactional emails

    develop

    StrongGrid provides several methods via the Mail resource to send emails to single or multiple recipients, with support for attachments.

    Common methods include:

    • SendToSingleRecipientAsync: Sends to one recipient.
    • SendToMultipleRecipientsAsync: Sends to an array of recipients.
    • SendToSingleRecipientAsync (with attachments): Allows including files using Attachment.FromLocalFile.
    // Single recipient
    var messageId = await strongGridClient.Mail.SendToSingleRecipientAsync(to, from, subject, html, text).ConfigureAwait(false);
    
    // Multiple recipients
    var messageId = await strongGridClient.Mail.SendToMultipleRecipientsAsync(new[] { to1, to2, to3 }, from, subject, html, text).ConfigureAwait(false);
    
    // With attachments
    var attachments = new[] 
    {
        Attachment.FromLocalFile(@"C:\MyDocuments\MySpreadsheet.xlsx"),
        Attachment.FromLocalFile(@"C:\temp\Headshot.jpg")
    };
    var messageId = await strongGridClient.Mail.SendToSingleRecipientAsync(to, from, subject, html, text, attachments: attachments).ConfigureAwait(false);
  8. Manage SendGrid Resources

    develop

    The StrongGrid.Client provides access to various SendGrid resources. Each resource offers methods for CRUD operations or data retrieval. Key resources include:

    • Contacts: Manage contacts via UpsertAsync (supports single or bulk imports).
    • ApiKeys: Retrieve account API keys via GetAllAsync.
    • Suppressions: Manage suppression groups via AddAddressToUnsubscribeGroupAsync.
    • Statistics: Retrieve account statistics via GetGlobalStatisticsAsync.
    • Templates: Manage email templates via CreateAsync.
    // Upsert a single contact
    var importJobId = await client.Contacts.UpsertAsync(email, firstName, lastName, addressLine1, addressLine2, city, stateOrProvince, country, postalCode, alternateEmails, customFields, null, cancellationToken).ConfigureAwait(false);
    
    // Bulk upsert contacts
    var contacts = new[] { new Models.Contact("dummy1@hotmail.com", "John", "Doe") };
    var importJobId = await client.Contacts.UpsertAsync(contacts, null, cancellationToken).ConfigureAwait(false);
    
    // Get API keys
    var apiKeys = await strongGridClient.ApiKeys.GetAllAsync();
    
    // Get statistics
    var globalStats = await strongGridClient.Statistics.GetGlobalStatisticsAsync(startDate, endDate);
  9. Parse SendGrid Webhooks

    develop

    StrongGrid provides a WebhookParser to handle incoming SendGrid webhooks in ASP.NET Core controllers.

    Standard Webhooks

    Use ParseEventsWebhookAsync for event webhooks and ParseInboundEmailWebhookAsync for inbound email webhooks. Both accept the Request.Body.

    Signed Event Webhooks

    If you have enabled Signed Event Webhook Requests in SendGrid, you must validate the signature and timestamp. The WebhookParser.ParseSignedEventsWebhookAsync method automates this validation. It requires:

    • The publicKey (retrieved via strongGridClient.WebhookSettings.GetSignedEventsPublicKeyAsync()).
    • The signature (from the SIGNATURE_HEADER_NAME header).
    • The timestamp (from the TIMESTAMP_HEADER_NAME header).

    If validation fails, a SecurityException is thrown.

    // Parsing signed events in a controller
    [HttpPost("SignedEvents")]
    public async Task<IActionResult> ReceiveSignedEvents()
    {
        var apiKey = "... api key...";
        var strongGridClient = new StrongGrid.Client(apiKey);
        var publicKey = await strongGridClient.WebhookSettings.GetSignedEventsPublicKeyAsync().ConfigureAwait(false);
    
        var signature = Request.Headers[WebhookParser.SIGNATURE_HEADER_NAME];
        var timestamp = Request.Headers[WebhookParser.TIMESTAMP_HEADER_NAME];
    
        try
        {
            var parser = new WebhookParser();
            var events = await parser.ParseSignedEventsWebhookAsync(Request.Body, publicKey, signature, timestamp).ConfigureAwait(false);
            return Ok();
        }
        catch (SecurityException e)
        {
            // Validation failed
            return BadRequest();
        }
    }
  10. Initialize the StrongGrid Client

    develop

    The Client class is the primary entry point for interacting with the SendGrid API. You can initialize it using your API key and optionally provide custom configuration via StrongGridClientOptions, a logger, or custom HTTP infrastructure.

    Available constructors:

    1. Standard: Client(string apiKey, StrongGridClientOptions options = null, ILogger logger = null)
    2. With Proxy: Client(string apiKey, IWebProxy proxy, StrongGridClientOptions options = null, ILogger logger = null)
    3. With Custom Handler: Client(string apiKey, HttpMessageHandler handler, StrongGridClientOptions options = null, ILogger logger = null)
    4. With Custom HttpClient: Client(string apiKey, HttpClient httpClient, StrongGridClientOptions options = null, ILogger logger = null)
    using StrongGrid;
    
    // Basic initialization
    var client = new Client("YOUR_SENDGRID_API_KEY");
    
    // Initialization with custom HttpClient
    var httpClient = new HttpClient();
    var clientWithCustomHttp = new Client("YOUR_SENDGRID_API_KEY", httpClient);
  11. Access SendGrid resources via the Client

    develop

    The Client class provides access to various SendGrid resources through properties. Each property exposes an interface for managing specific parts of your SendGrid account.

    Available resource properties:

    PropertyInterfaceDescription
    ContactsIContactsManage contacts (recipients)
    CustomFieldsICustomFieldsManage custom fields
    EngagementQualityIEngagementQualityManage engagement quality
    ListsIListsManage lists
    SegmentsISegmentsManage segments
    SenderIdentitiesISenderIdentitiesManage sender identities
    SingleSendsISingleSendsManage single sends (campaigns)