All Projects → Jericho → Stronggrid

Jericho / Stronggrid

Licence: mit
Strongly typed library for the entire SendGrid v3 API, including webhooks

Projects that are alternatives of or similar to Stronggrid

Magento2 Gmail Smtp App
Configure Magento 2 to send email using Google App, Gmail, Amazon Simple Email Service (SES), Microsoft Office365 and many other SMTP (Simple Mail Transfer Protocol) servers
Stars: ✭ 281 (+124.8%)
Mutual labels:  email, sendgrid
Sendgrid Ruby
The Official Twilio SendGrid Led, Community Driven Ruby API Library
Stars: ✭ 520 (+316%)
Mutual labels:  email, sendgrid
Email Templates
📫 Create, preview, and send custom email templates for Node.js. Highly configurable and supports automatic inline CSS, stylesheets, embedded images and fonts, and much more!
Stars: ✭ 3,291 (+2532.8%)
Mutual labels:  email, sendgrid
Mailer
A light-weight, modular, message representation and mail delivery framework for Python.
Stars: ✭ 225 (+80%)
Mutual labels:  email, sendgrid
Dialogflow Sendgrid
📮 Dialogflow + Sendgrid = AI Mailbox
Stars: ✭ 33 (-73.6%)
Mutual labels:  email, sendgrid
nest-sendgrid
No description or website provided.
Stars: ✭ 24 (-80.8%)
Mutual labels:  email, sendgrid
Sendgrid Java
The Official Twilio SendGrid Led, Community Driven Java API Library
Stars: ✭ 380 (+204%)
Mutual labels:  email, sendgrid
Omnimail
Send email across all platforms using one interface
Stars: ✭ 325 (+160%)
Mutual labels:  email, sendgrid
Sendgrid Csharp
The Official Twilio SendGrid Led, Community Driven C#, .NetStandard, .NetCore API Library
Stars: ✭ 835 (+568%)
Mutual labels:  email, sendgrid
Notify
A dead simple Go library for sending notifications to various messaging services.
Stars: ✭ 727 (+481.6%)
Mutual labels:  email, sendgrid
Sendgrid Nodejs
The Official Twilio SendGrid Led, Community Driven Node.js API Library
Stars: ✭ 2,543 (+1934.4%)
Mutual labels:  email, sendgrid
Sendgrid Python
The Official Twilio SendGrid Led, Community Driven Python API Library
Stars: ✭ 1,125 (+800%)
Mutual labels:  email, sendgrid
Fluentemail
All in one email sender for .NET. Supports popular senders (SendGrid, MailGun, etc) and Razor templates.
Stars: ✭ 1,888 (+1410.4%)
Mutual labels:  email, sendgrid
content-reminder
⏰ A GitHub Action that reminds you to share your own content
Stars: ✭ 28 (-77.6%)
Mutual labels:  email, sendgrid
Sendgrid Go
The Official Twilio SendGrid Led, Community Driven Golang API Library
Stars: ✭ 710 (+468%)
Mutual labels:  email, sendgrid
Django Anymail
Django email backends and webhooks for Amazon SES, Mailgun, Mailjet, Postmark, SendGrid, Sendinblue, SparkPost and more
Stars: ✭ 1,109 (+787.2%)
Mutual labels:  email, sendgrid
Sendgrid Php
The Official Twilio SendGrid Led, Community Driven PHP API Library
Stars: ✭ 1,257 (+905.6%)
Mutual labels:  email, sendgrid
Fuzzymail
📨 Email template generator. Making emails fun again.
Stars: ✭ 114 (-8.8%)
Mutual labels:  email
Postmark Php
The official PHP library for Postmark.
Stars: ✭ 117 (-6.4%)
Mutual labels:  email
Preview Email
Automatically opens your browser to preview Node.js email messages sent with Nodemailer. Made for Lad!
Stars: ✭ 112 (-10.4%)
Mutual labels:  email

StrongGrid

Discussions at https://github.com/Jericho/StrongGrid/discussions FOSSA Status License Sourcelink

Build status Tests Coverage Status CodeFactor

Release Notes NuGet (stable) MyGet (prerelease)
GitHub release NuGet Version MyGet Pre Release

About

StrongGrid is a strongly typed library for SendGrid's v3 API.

It started out in February 2016 as a fork of SendGrid's own library. At the time, the SendGrid C# client for their API extensively used the dynamic type which was very inconvenient and made it very difficult for developers. Furthermore, their C# client only covered the mail end point but did not allow access to other end points in their email marketing API such as creating lists and segments, importing contacts, etc. I submited a pull request to SendGrid in March 2016 but it was not accepted and eventually closed in June 2016.

In October 2016 I decided to release this library as a nuget package since SendGrid's library was still using dynamic and lacking strong typing. As of February 14, 2017 dynamic was removed from SendGrid's official csharp library and support for .Net Standard was added.

StrongGrid includes a client that allows you to interact with all the "resources" in the SendGrid API (e.g.: send an email, manage lists, contacts and segments, search for contacts matching criteria, create API keys, etc.).

StrongGrid also includes a parser for webhook sent from SendGrid to your own WebAPI. This parser supports the two types of webhooks that SendGrid can post to your API: the Event Webhook and the Inbound Parse Webhook.

Since November 2017, StrongGrid also includes a "warmup engine" that allows you to warmup IP addresses using a custom schedule.

If you need information about how to setup the SendGrid webhooks, please consult the following resources:

Installation

The easiest way to include StrongGrid in your C# project is by adding the nuget package to your project:

PM> Install-Package StrongGrid

Once you have the StrongGrid library properly referenced in your project, add the following namespace:

using StrongGrid;

.NET framework suport

StrongGrid supports the 4.6.1 .NET framework as well as any framework supporting .NET Standard 2.0 (which includes .NET 4.7.2, .NET 4.8, .NET Core 2.x, .NET Core 3.x,ASP.NET Core 2.x and ASP.NET Core 3.x).

Usage

Client

You declare your client variable like so:

var apiKey = "... your api key...";
var client = new Client(apiKey);

If you need to use a proxy, you can pass it to the Client:

var apiKey = "... your api key...";
var proxy = new WebProxy("http://myproxy:1234");
var client = new Client(apiKey, proxy);

One of the most common scenarios is to send transactional emails.

Here are a few examples:

// Send an email to a single recipient
var messageId = await client.Mail.SendToSingleRecipientAsync(to, from, subject, html, text).ConfigureAwait(false);

// Send an email to multiple recipients
var messageId = await client.Mail.SendToMultipleRecipientsAsync(new[] { to1, to2, to3 }, from, subject, html, text).ConfigureAwait(false);

// Include attachments when sending an email
var attachments = new[]
{
	Attachment.FromLocalFile(@"C:\MyDocuments\MySpreadsheet.xlsx"),
	Attachment.FromLocalFile(@"C:\temp\Headshot.jpg")
};
var messageId = await client.Mail.SendToSingleRecipientAsync(to, from, subject, html, text, attachments: attachments).ConfigureAwait(false);

You have access to numerous 'resources' (such as Contacts, Lists, Segments, Settings, SenderAuthentication, etc) off of the Client and each resource offers several methods to such as retrieve, create, update, delete, etc.

Here are a few example:

// Create a new contact (contacts are sometimes refered to as 'recipients')
var contactId = await client.Contacts.CreateAsync(email, firstName, lastName, customFields);

// Send an email
await client.Mail.SendToSingleRecipientAsync(to, from, subject, htmlContent, textContent);

// Retreive all the API keys in your account
var apiKeys = await client.ApiKeys.GetAllAsync();

// Add an email address to a suppression group
await client.Suppressions.AddAddressToUnsubscribeGroupAsync(groupId, "[email protected]");

// Get statistics between the two specific dates
var globalStats = await client.Statistics.GetGlobalStatisticsAsync(startDate, endDate);

// Create a new email template
var template = await client.Templates.CreateAsync("My template");

Dynamic templates

In August 2018, SendGrid released a new feature in their API that allows you to use the Handlebars syntax to specify merge fields in your content. Using this powerfull new feature in StrongGrid is very easy.

First, you must specify TemplateType.Dynamic when creating a new template like in this example:

var dynamicTemplate = await client.Templates.CreateAsync("My dynamic template", TemplateType.Dynamic).ConfigureAwait(false);

Second, you create a version of your content where you use the Handlebars syntax to define the merge fields and you can also specify an optional "test data" that will be used by the SendGrid UI to show you a sample. Rest assured that this test data will never be sent to any recipient. The following code sample demonstrates creating a dynamic template version containing simple substitution for CreditBalance, deep object replacements for Customer.first_name and Customer.last_name and an iterator that displays information about multiple orders.

var subject = "Dear {{Customer.first_name}}";
var htmlContent = @"
	<html>
		<body>
			Hello {{Customer.first_name}} {{Customer.last_name}}. 
			You have a credit balance of {{CreditBalance}}<br/>
			<ol>
			{{#each Orders}}
				<li>You ordered: {{this.item}} on: {{this.date}}</li>
			{{/each}}
			</ol>
		</body>
	</html>";
var textContent = "... this is the text content ...";
var testData = new
{
	Customer = new
	{
		first_name = "aaa",
		last_name = "aaa"
	},
	CreditBalance = 99.88,
	Orders = new[]
	{
		new { item = "item1", date = "1/1/2018" },
		new { item = "item2", date = "1/2/2018" },
		new { item = "item3", date = "1/3/2018" }
	}
};
await client.Templates.CreateVersionAsync(dynamicTemplate.Id, "Version 1", subject, htmlContent, textContent, true, EditorType.Code, testData).ConfigureAwait(false);

Finally, you can send an email to a recipient and specify the dynamic data that applies to them like so:

var dynamicData = new
{
	Customer = new
	{
		first_name = "Bob",
		last_name = "Smith"
	},
	CreditBalance = 56.78,
	Orders = new[]
	{
		new { item = "shoes", date = "2/1/2018" },
		new { item = "hat", date = "1/4/2018" }
	}
};
var to = new MailAddress("[email protected]", "Bob Smith");
var from = new MailAddress("[email protected]", "John Smith");
var messageId = await client.Mail.SendToSingleRecipientAsync(to, from, dynamicTemplate.Id, dynamicData).ConfigureAwait(false);

Parser

Here's a basic example of an API controller which parses the webhook from SendGrid into an array of Events:

namespace WebApplication1.Controllers
{
	[Route("api/SendGridWebhooks")]
	public class SendGridController : Controller
	{
		[HttpPost]
		[Route("Events")]
		public async Task<IActionResult> ReceiveEvents()
		{
			var parser = new WebhookParser();
			var events = await parser.ParseWebhookEventsAsync(Request.Body).ConfigureAwait(false);
			
			... do something with the events ...

			return Ok();
		}
	}
}

Here's a basic example of an API controller which parses the webhook from SendGrid into an InboundEmail:

namespace WebApplication1.Controllers
{
	[Route("api/SendGridWebhooks")]
	public class SendGridController : Controller
	{
		[HttpPost]
		[Route("InboundEmail")]
		public async Task<IActionResult> ReceiveInboundEmail()
		{
			var parser = new WebhookParser();
			var inboundEmail = await parser.ParseInboundEmailWebhookAsync(Request.Body).ConfigureAwait(false);

			... do something with the inbound email ...

			return Ok();
		}
	}
}

Parsing a signed webhook

SendGrid has a feature called Signed Event Webhook Requests which you can enable under Settings > Mail Settings > Event Settings when logged in your SendGrid account. When this feature is enabled, SendGrid includes additional information with each webhook that allow you to verify that this webhook indeed originated from SendGrid and therefore can be trusted. Specifically, the webhook will include a "signature" and a "timestamp" and you must use these two value along with a public key that SendGrid generated when you enabled the feature to validate the data being submited to you. Please note that SendGrid sometimes refers to this value as a "verification key". In case you are curious and want to know more about the inticacies of validating the data, I invite you to read SendGrid's documentation on this topic.

However, if you want to avoid learning how to perform the validation and you simply want this validation to be conveniently performed for you, StrongGrid can help! The WebhookParser class has a method called ParseSignedEventsWebhookAsyncwhich will automatically validate the data and throw a security exception if validation fails. If the validation fails, you should consider the webhook data to be invalid. Here's how it works:

namespace WebApplication1.Controllers
{
    [Route("api/SendGridWebhooks")]
    public class SendGridController : Controller
    {
        [HttpPost]
        [Route("InboundEmail")]
        public IActionResult ReceiveInboundEmail()
        {
            // Get your public key
            var apiKey = "... your api key...";
            var strongGridClient = new StrongGrid.Client(apiKey);
            var publicKey = await strongGridClient.WebhookSettings.GetSignedEventsPublicKeyAsync().ConfigureAwait(false);

            // Get the signature and the timestamp from the request headers
            var signature = Request.Headers[WebhookParser.SIGNATURE_HEADER_NAME]; // SIGNATURE_HEADER_NAME is a convenient constant provided so you don't have to remember the name of the header
            var timestamp = Request.Headers[WebhookParser.TIMESTAMP_HEADER_NAME]; // TIMESTAMP_HEADER_NAME is a convenient constant provided so you don't have to remember the name of the header

            // Parse the events. The signature will be automatically validated and a security exception thrown if unable to validate
            try
            {
                var parser = new WebhookParser();
                var events = await parser.ParseSignedEventsWebhookAsync(Request.Body, publicKey, signature, timestamp).ConfigureAwait(false);

                ... do something with the events ...
            }
            catch (SecurityException e)
            {
                ... unable to validate the data ...
            }

            return Ok();
        }
    }
}

Warmup Engine

SendGrid already provides a way to warm up ip addresses but you have no control over this process. StrongGrid solves this issue by providing you a warmup engine that you can tailor to your needs.

Typical usage

// Prepare the warmup engine
var poolName = "warmup_pool";
var dailyVolumePerIpAddress = new[] { 50, 100, 500, 1000 };
var resetDays = 1; // Should be 1 if you send on a daily basis, should be 2 if you send every other day, should be 7 if you send on a weekly basis, etc.
var warmupSettings = new WarmupSettings(poolName, dailyVolumePerIpAddress, resetDays);
var warmupEngine = new WarmupEngine(warmupSettings, client);

// This is a one-time call to create the IP pool that will be used to warmup the IP addresses
var ipAddresses = new[] { "168.245.123.132", "168.245.123.133" };
await warmupEngine.PrepareWithExistingIpAddressesAsync(ipAddresses, CancellationToken.None).ConfigureAwait(false);

// Send emails using any of the following methods
var result = warmupEngine.SendToSingleRecipientAsync(...);
var result = warmupEngine.SendToMultipleRecipientsAsync(...);
var result = warmupEngine.SendAsync(...);

The Send... methods return a WarmupResult object that will tell you whether the process is completed or not, and will also give you the messageId of the email sent using the IP pool (if applicable) and the messageId of the email sent using the default IP address (which is not being warmed up). The WarmupEngine will send emails using the IP pool until the daily volume limit is achieved and any remaining email will be sent using the default IP address. As you get close to your daily limit, it's possible that the Warmup engine may have to split a given "send" into two messages: one of which is sent using the ip pool and the other one sent using the default ip address. Let's use an example to illustrate: let's say that you have 15 emails left before you reach your daily warmup limit and you try to send an email to 20 recipients. In this scenario the first 15 emails will be sent using the warmup ip pool and the remaining 5 emails will be sent using the default ip address.

More advanced usage

Recommended daily volume: If you are unsure what daily limits to use, SendGrid has provided a recommended schedule and StrongGrid provides a convenient method to use the recommended schedule tailored to the number of emails you expect to send in a typical day. All you have to do is come up with a rough estimate of your daily volume and StrongGrid can configure the appropriate warmup settings. Here's an example:

var poolName = "warmup_pool";
var estimatedDailyVolume = 50000; // Should be your best guess: how many emails you will be sending in a typical day
var resetDays = 1; // Should be 1 if you send on a daily basis, should be 2 if you send every other day, should be 7 if you send on a weekly basis, etc.
var warmupSettings = WarmupSettings.FromSendGridRecomendedSettings(poolName, estimatedDailyVolume, resetDays);

Progress repository: By default StrongGrid's WarmupEngine will write progress information in a file on your computer's temp folder but you can override this settings. You can change the folder where this file is saved but you can also decide to use a completely different repository. Out of the box, StrongGrid provides FileSystemWarmupProgressRepository and MemoryWarmupProgressRepository. It also provides an interface called IWarmupProgressRepository which allows you to write your own implementation to save the progress data to a location more suitable to you such as a database, Azure, AWS, etc. Please note that MemoryWarmupProgressRepository in intended to be used for testing and we don't recommend using it in production. The main reason for this recommendation is that the data is stored in memory and it's lost when your computer is restarted. This means that your warmup process would start all over from day 1 each time you computer is rebooted.

// You select one of the following repositories available out of the box:
var warmupProgressRepository = new MemoryWarmupProgressRepository();
var warmupProgressRepository = new FileSystemWarmupProgressRepository();
var warmupProgressRepository = new FileSystemWarmupProgressRepository(@"C:\temp\myfolder\");
var warmupEngine = new WarmupEngine(warmupSettings, client, warmupProgressRepository);

Purchase new IP Addresses: You can purchase new IP addresses using SendGrid' UI, but StrongGrid's WarmupEngine makes it even easier. Rather than invoking PrepareWithExistingIpAddressesAsync (as demonstrated previously), you can invoke PrepareWithNewIpAddressesAsync and StrongGrid will take care of adding new ip addresses to your account and add them to a new IP pool ready for warmup. As a reminder, please note that the PrepareWithExistingIpAddressesAsync and PrepareWithNewIpAddressesAsync should only be invoked once. Invoking either method a second time would result in an exception due to the fact that the IP pool has already been created.

var howManyAddresses = 2; // How many ip addresses do you want to purchase?
var subusers = new[] { "your_subuser" }; // The subusers you authorize to send emails on the new ip addresses
await warmupEngine.PrepareWithNewIpAddressesAsync(howManyAddresses, subusers, CancellationToken.None).ConfigureAwait(false);

End of warmup process: When the process is completed, the IP pool is deleted and the warmed up IP address(es) are returned to the default pool. You can subsequently invoke the client.Mail.SendAsync(...) method to send your emails.

License

FOSSA Status

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].