StrongGrid 0.109.0
dotnet add package StrongGrid --version 0.109.0
NuGet\Install-Package StrongGrid -Version 0.109.0
<PackageReference Include="StrongGrid" Version="0.109.0" />
paket add StrongGrid --version 0.109.0
#r "nuget: StrongGrid, 0.109.0"
// Install StrongGrid as a Cake Addin #addin nuget:?package=StrongGrid&version=0.109.0 // Install StrongGrid as a Cake Tool #tool nuget:?package=StrongGrid&version=0.109.0
StrongGrid
发布说明 | NuGet(稳定版) | MyGet(预发布版) |
---|---|---|
关于
StrongGrid 是一个用于 SendGrid v3 API 的强类型库。
从 2016 年 2 月开始,它作为 SendGrid 自己的库的一个分支。当时,SendGrid 的 API 的 C# 客户端广泛使用了 dynamic
类型,这非常不便,并且让开发者感到非常困难。此外,他们的 C# 客户端只覆盖了 mail
终端点,但无法访问 email marketing
API 中的其他终端点,例如创建列表和分段,导入联系人等。我在 2016 年 3 月向 SendGrid 提交了一个 pull request,但未获接受,并在 2016 年 6 月最终关闭。
2016年10月,我决定将这个库发布为nuget包,因为SendGrid的库仍然使用dynamic
且缺乏强类型。截至2017年2月14日,dynamic
已从SendGrid的官方csharp库中移除,并增加了对.Net Standard的支持。
StrongGrid包括一个客户端,它允许您与SendGrid API中的所有“资源”交互(例如:发送电子邮件、管理列表、联系人分段、根据条件搜索联系人、创建API密钥等)。
StrongGrid还包括一个解析器,用于解析从SendGrid发送到您自己的WebAPI的webhook。此解析器支持SendGrid可以发布到您的API的两个类型的webhook:事件webhook和入站解析webhook。
自2017年11月起,StrongGrid还包括一个“预热引擎”,允许您使用自定义的计划来预热IP地址。
如果您需要有关如何设置SendGrid webhooks的信息,请参阅以下资源
安装
将StrongGrid纳入您的C#项目的最简单方法是向项目中添加nuget包
PM> Install-Package StrongGrid
一旦您在项目中正确引用了StrongGrid库,请添加以下命名空间
using StrongGrid;
.NET框架支持
StrongGrid支持4.8
、6.0
和7.0
.NET框架,以及任何支持.NET Standard 2.1
的框架(包括.NET Core 3.x
和ASP.NET Core 3.x
)。
用法
客户端
您可以像这样声明客户端变量
var apiKey = "... your api key...";
var strongGridClient = new StrongGrid.Client(apiKey);
如果您需要使用代理,可以将它传递给客户端
var apiKey = "... your api key...";
var proxy = new WebProxy("http://myproxy:1234");
var strongGridClient = new StrongGrid.Client(apiKey, proxy);
最常见的情况之一是发送事务性电子邮件。
以下是一些示例
// Send an email to a single recipient
var messageId = await strongGridClient.Mail.SendToSingleRecipientAsync(to, from, subject, html, text).ConfigureAwait(false);
// Send an email to multiple recipients
var messageId = await strongGridClient.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 strongGridClient.Mail.SendToSingleRecipientAsync(to, from, subject, html, text, attachments: attachments).ConfigureAwait(false);
您可以通过客户端访问大量的“资源”(如联系人、列表、分段、设置、发件人身份验证等),每个资源都提供多种方法,如检索、创建、更新、删除等。
以下是一些示例
// Import a new contact or update existing contact if a match is found
var importJobId = await client.Contacts.UpsertAsync(email, firstName, lastName, addressLine1, addressLine2, city, stateOrProvince, country, postalCode, alternateEmails, customFields, null, cancellationToken).ConfigureAwait(false);
// Import several new contacts or update existing contacts when a match is found
var contacts = new[]
{
new Models.Contact("[email protected]", "John", "Doe"),
new Models.Contact("[email protected]", "John", "Smith"),
new Models.Contact("[email protected]", "Bob", "Smith")
};
var importJobId = await client.Contacts.UpsertAsync(contacts, null, cancellationToken).ConfigureAwait(false);
// Send an email
await strongGridClient.Mail.SendToSingleRecipientAsync(to, from, subject, htmlContent, textContent);
// Retreive all the API keys in your account
var apiKeys = await strongGridClient.ApiKeys.GetAllAsync();
// Add an email address to a suppression group
await strongGridClient.Suppressions.AddAddressToUnsubscribeGroupAsync(groupId, "[email protected]");
// Get statistics between the two specific dates
var globalStats = await strongGridClient.Statistics.GetGlobalStatisticsAsync(startDate, endDate);
// Create a new email template
var template = await strongGridClient.Templates.CreateAsync("My template");
动态模板
2018年8月,SendGrid在其API中发布了新功能,允许您使用Handlebars语法指定内容中的合并字段。在StrongGrid中使用此强大的新功能非常简单。
首先,在创建新模板时,必须指定TemplateType.Dynamic
,如下例所示
var dynamicTemplate = await strongGridClient.Templates.CreateAsync("My dynamic template", TemplateType.Dynamic).ConfigureAwait(false);
其次,创建内容的版本,其中您使用Handlebars语法来定义合并字段,您还可以指定可选的“测试数据”,SendGrid UI将使用这些数据向您展示示例。请放心,这些测试数据绝不会发送给任何收件人。以下代码示例演示了创建包含简单替换的动态模板版本,用于CreditBalance
、用于Customer.first_name
和Customer.last_name
的深度对象替换以及显示多个订单信息的迭代器。
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 strongGridClient.Templates.CreateVersionAsync(dynamicTemplate.Id, "Version 1", subject, htmlContent, textContent, true, EditorType.Code, testData).ConfigureAwait(false);
最后,您可以向收件人发送电子邮件并指定适用于他们的动态数据,如下所示
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 strongGridClient.Mail.SendToSingleRecipientAsync(to, from, dynamicTemplate.Id, dynamicData).ConfigureAwait(false);
Webhook解析器
以下是一个基本示例,展示如何解析SendGrid的webhook的.net 6.0 API控制器
using Microsoft.AspNetCore.Mvc;
using StrongGrid;
namespace WebApplication1.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SendGridWebhooksController : ControllerBase
{
[HttpPost]
[Route("Events")]
public async Task<IActionResult> ReceiveEvents()
{
var parser = new WebhookParser();
var events = await parser.ParseEventsWebhookAsync(Request.Body).ConfigureAwait(false);
// ... do something with the events ...
return Ok();
}
[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();
}
}
}
解析已签名webhook
SendGrid 具备名为 签名的 Event Webhook 请求
的功能,您可以在登录 SendGrid 账户后,在 设置 > 邮件设置 > 事件设置
下启用该功能。启用此功能时,SendGrid 会将与每个 webhook 一起包含额外的信息,以便您验证该 webhook 确实来自 SendGrid,因此可以信任。具体来说,webhook 将包括一个“签名”和一个“时间戳”,您必须使用这两个值以及您在启用功能时 SendGrid 生成的公钥来验证提交给你的数据。请注意,SendGrid 有时将此值称为“验证键”。如果您对此验证数据的细节好奇并想了解更多信息,我邀请您阅读 SendGrid 关于此主题的 文档。
但是,如果您想避免学习如何执行验证,并且只想方便地自动执行此验证,StrongGrid 可以帮助您!WebhookParser
类有一个名为 ParseSignedEventsWebhookAsync
的方法,它将自动验证数据,如果验证失败,将引发安全异常。如果验证失败,您应将 webhook 数据视为无效。以下是其工作原理:
using Microsoft.AspNetCore.Mvc;
using StrongGrid;
using System.Security;
namespace WebApplication1.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SendGridWebhooksController : ControllerBase
{
[HttpPost]
[Route("SignedEvents")]
public async Task<IActionResult> ReceiveSignedEvents()
{
// 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();
}
}
}
预热引擎
SendGrid 已经提供了预热 IP 地址的方式,但您无法控制此过程。StrongGrid 通过为您提供可以根据您需求定制的预热引擎来解决此问题。
典型用法
// 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(...);
Send...
方法返回一个 WarmupResult
对象,它会告诉您是否已完成操作,并且还会提供使用 IP 池发送的邮件的消息 ID(如果适用)和默认 IP 地址发送的邮件的消息 ID(默认 IP 地址不会被预热)。预热引擎将使用 IP 池发送邮件,直到达到每天的容量限制,多余的邮件将使用默认 IP 地址发送。当您接近每天的容量限制时,预热引擎可能必须将给定的“发送”拆分为两个消息:其中一个使用 IP 池发送,另一个使用默认 IP 地址发送。让我们用一个例子来说明:假设您在自己达到每日预热限制之前还有 15 封邮件,您尝试向 20 个收件人发送邮件。在这种情况下,前 15 封邮件将使用预热 IP 池发送,剩下的 5 封邮件将使用默认 IP 地址发送。
更高级的用法
建议的每日容量:如果您不确定使用哪些每日限制,SendGrid 提供了建议的时间表,StrongGrid 提供了一个方便的方法来使用建议的时间表,该时间表根据您预期每天发送的电子邮件数量而定制。您只需提供一个关于每日容量的粗略估计值,StrongGrid 就可以配置适当的预热设置。以下是一个示例
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);
进度仓库:默认情况下,StrongGrid的WarmupEngine将在您的计算机的temp
文件夹中的文件写入进度信息,但您可以选择覆盖此设置。您可以更改保存此文件的文件夹,也可以选择使用完全不同的仓库。开箱即用,StrongGrid提供FileSystemWarmupProgressRepository
和MemoryWarmupProgressRepository
。它还提供一个名为IWarmupProgressRepository
的接口,允许您编写自己的实现,将进度数据保存到更适合您的位置,例如数据库、Azure、AWS等。请注意,MemoryWarmupProgressRepository
旨在用于测试,我们不推荐在生产中使用它。这个建议的主要原因是因为数据存储在内存中,当您重新启动计算机时,数据会丢失。这意味着每次您重新启动计算机,您的预热过程都会从头开始。
// 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);
购买新的IP地址:您可以使用SendGrid的用户界面购买新的IP地址,但StrongGrid的WarmupEngine使这个过程更加简单。您不需要调用PrepareWithExistingIpAddressesAsync
(如前所述),而是可以调用PrepareWithNewIpAddressesAsync
,StrongGrid将负责将新的IP地址添加到您的账户,并将它们添加到一个新的IP池中以便预热。提醒一下,请注意,应仅调用一次PrepareWithExistingIpAddressesAsync
和PrepareWithNewIpAddressesAsync
。如果再次调用任意一个方法,都将因为IP池已被创建而引发异常。
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);
预热过程结束:当过程完成时,IP池将被删除,预热好的IP地址将返回到默认池中。之后,您可以调用strongGridClient.Mail.SendAsync(...)
方法来发送您的电子邮件。
许可证
产品 | 版本 兼容的和附加的计算目标框架版本。 |
---|---|
.NET | net5.0 已计算。 net5.0-windows 已计算。 net6.0 兼容。 net6.0-android 已计算。 net6.0-ios 已计算。 net6.0-maccatalyst 已计算。 net6.0-macos 已计算。 net6.0-tvos 已计算。 net6.0-windows 已计算。 net7.0 兼容。 net7.0-android 已计算。 net7.0-ios 已计算。 net7.0-maccatalyst 已计算。 net7.0-macos 已计算。 net7.0-tvos 已计算。 net7.0-windows 已计算。 net8.0 已计算。 net8.0-android 已计算。 net8.0-browser 已计算。 net8.0-ios 已计算。 net8.0-maccatalyst 已计算。 net8.0-macos 已计算。 net8.0-tvos 已计算。 net8.0-windows 已计算。 |
.NET Core | netcoreapp3.0 已计算。 netcoreapp3.1 已计算。 |
.NET Standard | netstandard2.1 兼容。 |
.NET Framework | net48 兼容。 net481 已计算。 |
MonoAndroid | monoandroid 已计算。 |
MonoMac | monomac 已计算。 |
MonoTouch | monotouch 已计算。 |
Tizen | tizen60 已计算。 |
Xamarin.iOS | xamarinios 已计算。 |
Xamarin.Mac | xamarinmac 已计算。 |
Xamarin.TVOS | xamarintvos 已计算。 |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.8
- HttpMultipartParser (>= 8.4.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- MimeKitLite (>= 4.6.0)
- Pathoschild.Http.FluentClient (>= 4.4.0)
- System.Text.Json (>= 8.0.3)
- UTF.Unknown (>= 2.5.1)
-
.NETStandard 2.1
- HttpMultipartParser (>= 8.4.0)
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- MimeKitLite (>= 4.6.0)
- Pathoschild.Http.FluentClient (>= 4.4.0)
- System.Text.Encoding.CodePages (>= 8.0.0)
- System.Text.Json (>= 8.0.3)
- UTF.Unknown (>= 2.5.1)
-
net6.0
- HttpMultipartParser (>= 8.4.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- MimeKitLite (>= 4.6.0)
- Pathoschild.Http.FluentClient (>= 4.4.0)
- System.Text.Encoding.CodePages (>= 8.0.0)
- System.Text.Json (>= 8.0.3)
- UTF.Unknown (>= 2.5.1)
-
net7.0
- HttpMultipartParser (>= 8.4.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- MimeKitLite (>= 4.6.0)
- Pathoschild.Http.FluentClient (>= 4.4.0)
- System.Text.Encoding.CodePages (>= 8.0.0)
- System.Text.Json (>= 8.0.3)
- UTF.Unknown (>= 2.5.1)
NuGet 包 (7)
显示依赖 StrongGrid 的顶级 5 个 NuGet 包
包 | 下载 |
---|---|
Cake.SendGrid
Cake 构建插件,提供通过 SendGrid 发送电子邮件的别名。 |
|
AuthScape.TicketSystem
包描述 |
|
CodeStream.Comms.Messages
CodeStream Communication Messages为应用程序提供基础架构代码 |
|
Magnet.Providers.SendGrid
框架,用于在集成测试中接收短信和电子邮件。 |
|
Qw3.Mail.Service
用于与 stronggrid 库集成的简单包装服务。这使得可以一次性修改所有项目更容易。 |
GitHub 存储库 (1)
显示依赖 StrongGrid 的顶级 1 个流行 GitHub 存储库
存储库 | 星标 |
---|---|
SciSharp/BotSharp
.NET 中的 AI 代理框架
|
版本 | 下载 | 最后更新 |
---|---|---|
0.109.0 | 18,393 | 6/19/2024 |
0.108.0 | 12,655 | 5/26/2024 |
0.107.0 | 19,690 | 4/18/2024 |
0.106.0 | 23,837 | 2/16/2024 |
0.105.0 | 10,777 | 2/1/2024 |
0.104.0 | 9,754 | 1/19/2024 |
0.103.0 | 14,205 | 1/8/2024 |
0.102.0 | 11,401 | 11/18/2023 |
0.101.0 | 87,703 | 6/2/2023 |
0.100.0 | 4,901 | 6/1/2023 |
0.99.0 | 208 | 6/1/2023 |
0.98.0 | 117,808 | 1/20/2023 |
0.97.0 | 9,173 | 1/12/2023 |
0.96.0 | 30,649 | 12/2/2022 |
0.95.1 | 25,532 | 11/13/2022 |
0.94.0 | 31,640 | 9/30/2022 |
0.93.0 | 12,059 | 9/13/2022 |
0.92.0 | 10,775 | 8/22/2022 |
0.91.0 | 39,011 | 6/26/2022 |
0.90.0 | 30,411 | 4/21/2022 |
0.89.0 | 32,227 | 3/21/2022 |
0.88.2 | 22,179 | 3/15/2022 |
0.88.1 | 637 | 3/14/2022 |
0.88.0 | 7,552 | 2/5/2022 |
0.87.0 | 3,611 | 1/18/2022 |
0.86.0 | 636 | 1/14/2022 |
0.85.0 | 21,863 | 1/14/2022 |
0.84.0 | 61,081 | 11/25/2021 |
0.83.0 | 1,880 | 11/11/2021 |
0.82.0 | 115,958 | 5/23/2021 |
0.81.0 | 4,001 | 5/9/2021 |
0.80.0 | 723 | 5/5/2021 |
0.79.0 | 80,224 | 4/27/2021 |
0.78.0 | 1,583 | 4/15/2021 |
0.77.0 | 14,815 | 4/4/2021 |
0.76.0 | 55,035 | 1/20/2021 |
0.75.0 | 107,795 | 11/28/2020 |
0.74.0 | 1,024 | 11/26/2020 |
0.73.0 | 87,915 | 10/3/2020 |
0.72.1 | 61,372 | 9/15/2020 |
0.71.0 | 18,803 | 8/7/2020 |
0.70.0 | 32,741 | 6/24/2020 |
0.69.0 | 39,552 | 5/10/2020 |
0.68.0 | 14,200 | 4/13/2020 |
0.67.0 | 8,338 | 4/3/2020 |
0.66.0 | 23,859 | 3/26/2020 |
0.65.0 | 8,909 | 3/11/2020 |
0.64.0 | 6,736 | 3/6/2020 |
0.63.1 | 34,725 | 1/3/2020 |
0.62.0 | 23,851 | 11/29/2019 |
0.61.0 | 31,845 | 9/22/2019 |
0.60.0 | 61,978 | 7/7/2019 |
0.59.0 | 7,012 | 6/21/2019 |
0.58.0 | 3,730 | 6/6/2019 |
0.57.1 | 1,082 | 6/3/2019 |
0.56.1 | 900 | 5/30/2019 |
0.56.0 | 35,890 | 5/28/2019 |
0.55.0 | 15,335 | 5/16/2019 |
0.54.0 | 5,910 | 5/2/2019 |
0.53.0 | 3,714 | 4/23/2019 |
0.52.0 | 917 | 4/19/2019 |
0.51.0 | 3,239 | 4/14/2019 |
0.50.2 | 49,087 | 3/27/2019 |
0.50.1 | 921 | 3/27/2019 |
0.50.0 | 1,729 | 3/11/2019 |
0.49.1 | 14,842 | 11/9/2018 |
0.49.0 | 4,353 | 10/25/2018 |
0.48.0 | 24,115 | 8/20/2018 |
0.47.3 | 2,503 | 8/15/2018 |
0.47.2 | 1,024 | 8/14/2018 |
0.47.1 | 1,033 | 8/14/2018 |
0.47.0 | 2,681 | 8/4/2018 |
0.46.0 | 2,244 | 7/27/2018 |
0.45.0 | 14,352 | 6/12/2018 |
0.44.0 | 5,000 | 5/23/2018 |
0.43.0 | 11,261 | 5/5/2018 |
0.42.0 | 1,116 | 5/4/2018 |
0.41.0 | 1,199 | 5/2/2018 |
0.40.0 | 3,296 | 4/18/2018 |
0.39.0 | 1,905 | 4/9/2018 |
0.38.0 | 1,713 | 4/3/2018 |
0.37.0 | 2,476 | 3/20/2018 |
0.36.0 | 5,400 | 2/18/2018 |
0.35.0 | 8,503 | 1/17/2018 |
0.34.0 | 6,323 | 11/20/2017 |
0.33.0 | 3,027 | 11/16/2017 |
0.32.0 | 3,090 | 10/27/2017 |
0.31.0 | 4,091 | 10/4/2017 |
0.30.0 | 15,836 | 10/2/2017 |
0.29.0 | 2,367 | 9/17/2017 |
0.28.0 | 25,807 | 6/3/2017 |
0.27.0 | 6,328 | 4/24/2017 |
0.26.0 | 2,431 | 3/29/2017 |
0.25.0 | 1,549 | 3/24/2017 |
0.24.0 | 1,224 | 3/19/2017 |
0.23.0 | 1,392 | 3/9/2017 |
0.22.0 | 1,556 | 2/21/2017 |
0.21.0 | 1,254 | 2/19/2017 |
0.20.0 | 1,283 | 2/18/2017 |
0.19.0 | 1,288 | 2/13/2017 |
0.18.3 | 1,508 | 2/3/2017 |
0.18.2 | 1,204 | 2/2/2017 |
0.18.1 | 2,207 | 1/28/2017 |
0.18.0 | 11,432 | 1/5/2017 |
0.17.0 | 3,753 | 12/14/2016 |
0.16.0 | 2,934 | 12/7/2016 |
0.15.0 | 1,217 | 12/2/2016 |
0.14.0 | 1,228 | 11/30/2016 |
0.13.0 | 1,171 | 11/29/2016 |
0.12.0 | 1,190 | 11/26/2016 |
0.11.0 | 1,128 | 11/22/2016 |
0.10.0 | 1,372 | 11/14/2016 |
0.9.0 | 1,179 | 11/11/2016 |
0.8.0 | 1,194 | 11/10/2016 |
0.7.2 | 1,292 | 10/27/2016 |
0.7.1 | 1,111 | 10/27/2016 |
0.7.0 | 1,165 | 10/27/2016 |
0.6.0 | 1,183 | 10/25/2016 |
0.5.0 | 1,152 | 10/22/2016 |
0.4.0 | 1,154 | 10/20/2016 |
0.3.0 | 1,167 | 10/19/2016 |
0.2.0 | 1,168 | 10/17/2016 |
0.1.0 | 1,230 | 10/17/2016 |