Skip to content

Commit

Permalink
Merge branch 'feature/inbound_parse_webhook' into develop
Browse files Browse the repository at this point in the history
# Conflicts:
#	Source/StrongGrid/project.json
  • Loading branch information
Jericho committed Dec 6, 2016
2 parents b63a8c3 + 1a65ccb commit e862834
Show file tree
Hide file tree
Showing 9 changed files with 373 additions and 46 deletions.
52 changes: 36 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ StrongGrid also includes a parser for webhook sent from SendGrid to your own Web
If you information about how to setup the SendGrid webhooks, please consult the following resources:
- [Webhooks Overview](https://sendgrid.com/docs/API_Reference/Webhooks/debug.html)
- [Guide to debug webhooks](https://sendgrid.com/docs/API_Reference/Webhooks/index.html)
- [Setting up the inbound parse webhook](https://sendgrid.com/docs/Classroom/Basics/Inbound_Parse_Webhook/setting_up_the_inbound_parse_webhook.html)


## Nuget
Expand Down Expand Up @@ -97,28 +98,47 @@ var template = await client.Templates.CreateAsync("My template");

#### Parser


Here's a basic example of an API controller which parses the webhook from SendGrid into an array of Events:
```csharp
[OverrideExceptionFilters]
[OverrideAuthentication]
[OverrideAuthorization]
[AllowAnonymous]
[RoutePrefix("API/Webhooks")]
public class SendGridWebhooksController : ApiController
namespace WebApplication1.Controllers
{
[Route("SendGrid")]
[HttpPost]
public async Task<IHttpActionResult> SendGrid()
[Route("api/SendGridWebhooks")]
public class SendGridController : Controller
{
var parser = new StrongGrid.WebHookParser();
var events = await parser.ParseWebhookEventsAsync(Request.Content));

foreach (var event in events)
[HttpPost]
[Route("Events")]
public async Task<IActionResult> ReceiveEvents()
{
... do something with the event ...
var parser = new WebhookParser();
var events = await parser.ParseWebhookEventsAsync(Request.Body).ConfigureAwait(false);

... do something with the events ...

return Ok();
}
}
}
```


return Ok();
Here's a basic example of an API controller which parses the webhook from SendGrid into an InboundEmail:
```csharp
namespace WebApplication1.Controllers
{
[Route("api/SendGridWebhooks")]
public class SendGridController : Controller
{
[HttpPost]
[Route("InboundEmail")]
public IActionResult ReceiveInboundEmail()
{
var parser = new WebhookParser();
var inboundEmail = parser.ParseInboundEmailWebhook(Request.Body);

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

return Ok();
}
}
}
```
123 changes: 123 additions & 0 deletions Source/StrongGrid/Model/Webhooks/InboundEmail.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrongGrid.Model.Webhooks
{
/// <summary>
/// The parsed information about an email sent by SendGrid via a webhook
/// </summary>
public class InboundEmail
{
/// <summary>
/// Gets or sets the headers of the email.
/// </summary>
/// <value>
/// The headers.
/// </value>
public KeyValuePair<string, string>[] Headers { get; set; }

/// <summary>
/// Gets or sets a string containing the verification results of any DKIM and domain keys signatures in the message.
/// </summary>
/// <value>
/// The dkim.
/// </value>
public string Dkim { get; set; }

/// <summary>
/// Gets or sets the email recipient field, as taken from the message headers.
/// </summary>
/// <value>
/// To.
/// </value>
public MailAddress To { get; set; }

/// <summary>
/// Gets or sets the HTML body of email.If not set, email did not have an HTML body.
/// </summary>
/// <value>
/// The HTML.
/// </value>
public string Html { get; set; }

/// <summary>
/// Gets or sets from the email sender, as taken from the message headers
/// </summary>
/// <value>
/// From.
/// </value>
public MailAddress From { get; set; }

/// <summary>
/// Gets or sets the sender's ip address.
/// </summary>
/// <value>
/// The sender ip.
/// </value>
public string SenderIp { get; set; }

/// <summary>
/// Gets or sets the Spam Assassin's spam report.
/// </summary>
/// <value>
/// The spam report.
/// </value>
public string SpamReport { get; set; }

/// <summary>
/// Gets or sets the SMTP envelope.
/// This will have two variables:
/// - to, which is a single-element array containing the address that we received the email to,
/// - from, which is the return path for the message.
/// </summary>
/// <value>
/// The envelope.
/// </value>
public InboundEmailEnvelope Envelope { get; set; }

/// <summary>
/// Gets or sets the email subject.
/// </summary>
/// <value>
/// The subject.
/// </value>
public string Subject { get; set; }

/// <summary>
/// Gets or sets the Spam Assassin’s rating for whether or not this is spam.
/// </summary>
/// <value>
/// The spam score.
/// </value>
public string SpamScore { get; set; }

/// <summary>
/// Gets or sets the attachment.
/// </summary>
/// <value>
/// The attachment.
/// </value>
public InboundEmailAttachment[] Attachments { get; set; }

/// <summary>
/// Gets or sets the character sets of the fields extracted from the message.
/// </summary>
/// <value>
/// The charsets.
/// </value>
public KeyValuePair<string, Encoding>[] Charsets { get; set; }

/// <summary>
/// Gets or sets the results of the Sender Policy Framework verification of the message sender
/// and receiving IP address.
/// </summary>
/// <value>
/// The SPF.
/// </value>
public string Spf { get; set; }
}
}
60 changes: 60 additions & 0 deletions Source/StrongGrid/Model/Webhooks/InboundEmailAttachment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Newtonsoft.Json;
using System.IO;

namespace StrongGrid.Model.Webhooks
{
public class InboundEmailAttachment
{

/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public string Id { get; set; }

/// <summary>
/// Gets or sets the content-type. Defaults to text/plain if unspecified.
/// </summary>
/// <value>
/// The content-type.
/// </value>
public string ContentType { get; set; }

/// <summary>
/// Gets the data.
/// </summary>
/// <value>
/// The data.
/// </value>
public Stream Data { get; set; }

/// <summary>
/// Gets or sets the file name.
/// </summary>
/// <value>
/// The name of the file.
/// </value>
[JsonProperty("filename", NullValueHandling = NullValueHandling.Ignore)]
public string FileName { get; set; }

/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }

/// <summary>
/// Gets or sets the content identifier.
/// </summary>
/// <value>
/// The content identifier.
/// </value>
[JsonProperty("content-id", NullValueHandling = NullValueHandling.Ignore)]
public string ContentId { get; set; }
}
}
31 changes: 31 additions & 0 deletions Source/StrongGrid/Model/Webhooks/InboundEmailEnvelope.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Newtonsoft.Json;
using StrongGrid.Utilities;
using System;

namespace StrongGrid.Model.Webhooks
{
/// <summary>
/// The SMTP envelope
/// </summary>
public class InboundEmailEnvelope
{
/// <summary>
/// Gets or sets to, which is a single-element array containing the address that we received the email to,
/// </summary>
/// <value>
/// To.
/// </value>
[JsonProperty("to", NullValueHandling = NullValueHandling.Ignore)]
public string[] To { get; set; }

/// <summary>
/// Gets or sets from, which is the return path for the message.

/// </summary>
/// <value>
/// From.
/// </value>
[JsonProperty("from", NullValueHandling = NullValueHandling.Ignore)]
public string From { get; set; }
}
}
16 changes: 15 additions & 1 deletion Source/StrongGrid/Utilities/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Newtonsoft.Json.Linq;
using HttpMultipartParser;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Net.Http;
Expand Down Expand Up @@ -189,5 +190,18 @@ public static Encoding GetEncoding(this HttpContent content, Encoding defaultEnc

return encoding;
}

/// <summary>
/// Returns the value of a parameter or the default value if it doesn't exist.
/// </summary>
/// <param name="parser">The parser.</param>
/// <param name="name">The name of the parameter.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>The value of the parameter</returns>
public static string GetParameterValue(this MultipartFormDataParser parser, string name, string defaultValue)
{
if (parser.HasParameter(name)) return parser.GetParameterValue(name);
else return defaultValue;
}
}
}
2 changes: 1 addition & 1 deletion Source/StrongGrid/Utilities/WebHookEventConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class WebHookEventConverter : JsonConverter
/// </returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Event) || objectType == typeof(Event[]);
return objectType == typeof(Event);
}

/// <summary>
Expand Down
Loading

0 comments on commit e862834

Please sign in to comment.