├── .editorconfig ├── .env_sample ├── .github └── workflows │ ├── pr-lint.yml │ └── test-and-deploy.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── ExampleCoreProject ├── ExampleCoreProject.csproj └── Program.cs ├── ExampleNet45ASPNetProject ├── README.md ├── SendGrid.ASPSamples.sln ├── SendGrid.ASPSamples │ ├── App_Start │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ ├── IdentityConfig.cs │ │ ├── RouteConfig.cs │ │ └── Startup.Auth.cs │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap.css │ │ └── bootstrap.min.css │ ├── Controllers │ │ └── EmailController.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Models │ │ ├── EmailContract.cs │ │ ├── EmailServiceException.cs │ │ └── IdentityModels.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Scripts │ │ ├── _references.js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── jquery-1.10.2.intellisense.js │ │ ├── jquery-1.10.2.js │ │ ├── jquery-1.10.2.min.js │ │ ├── jquery-1.10.2.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── modernizr-2.6.2.js │ │ ├── respond.js │ │ └── respond.min.js │ ├── SendGrid.ASPSamples.csproj │ ├── Service │ │ └── SendGridEmailService.cs │ ├── Startup.cs │ ├── Views │ │ ├── Email │ │ │ └── Send.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ ├── Lockout.cshtml │ │ │ ├── _Layout.cshtml │ │ │ └── _LoginPartial.cshtml │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── favicon.ico │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── packages.config └── SendGrid.ASPWebFormsSamples │ ├── ApplicationInsights.config │ ├── Content │ └── Site.css │ ├── Default.aspx │ ├── Default.aspx.cs │ ├── Default.aspx.designer.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Models │ └── EmailMessageInfo.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── SendGrid.ASPWebFormsSamples.csproj │ ├── Services │ └── SendGridService.cs │ ├── Site.Master │ ├── Site.Master.cs │ ├── Site.Master.designer.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── favicon.ico │ └── packages.config ├── ExampleNet45Project ├── ExampleNet45.csproj └── Program.cs ├── FIRST_TIMERS.md ├── LICENSE ├── Makefile ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── SendGrid.sln ├── TROUBLESHOOTING.md ├── USAGE.md ├── USE_CASES.md ├── examples ├── accesssettings │ └── accesssettings.cs ├── alerts │ └── alerts.cs ├── apikeys │ └── apikeys.cs ├── asm │ └── asm.cs ├── browsers │ └── browsers.cs ├── campaigns │ └── campaigns.cs ├── categories │ └── categories.cs ├── clients │ ├── clientOptions.cs │ └── clients.cs ├── contactdb │ └── contactdb.cs ├── devices │ └── devices.cs ├── eventwebhook │ ├── RequestValidator.cs │ └── consumer │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── SendGridEventWebhookConsumer.sln │ │ ├── Src │ │ └── EventWebhook │ │ │ ├── Controllers │ │ │ └── EventWebhookController.cs │ │ │ ├── Converters │ │ │ ├── CategoryConverter.cs │ │ │ └── UriConverter.cs │ │ │ ├── EventWebhook.csproj │ │ │ ├── Models │ │ │ ├── BounceEvent.cs │ │ │ ├── BounceEventType.cs │ │ │ ├── Category.cs │ │ │ ├── ClickEvent.cs │ │ │ ├── DeferredEvent.cs │ │ │ ├── DeliveredEvent.cs │ │ │ ├── DroppedEvent.cs │ │ │ ├── Event.cs │ │ │ ├── EventType.cs │ │ │ ├── GroupResubscribeEvent.cs │ │ │ ├── GroupUnsubscribeEvent.cs │ │ │ ├── OpenEvent.cs │ │ │ ├── Pool.cs │ │ │ ├── ProcessedEvent.cs │ │ │ ├── SpamReportEvent.cs │ │ │ └── UnsubscribeEvent.cs │ │ │ ├── Parser │ │ │ ├── EventConverter.cs │ │ │ └── EventParser.cs │ │ │ ├── Program.cs │ │ │ ├── Startup.cs │ │ │ ├── Views │ │ │ └── EventWebhook │ │ │ │ └── Index.cshtml │ │ │ ├── appsettings.Development.json │ │ │ └── appsettings.json │ │ └── Tests │ │ └── EventWebhook.Tests │ │ ├── EventTests.cs │ │ ├── EventWebhook.Tests.csproj │ │ └── TestData │ │ └── events.json ├── geo │ └── geo.cs ├── inbound-webhook-handler │ ├── .dockerignore │ ├── .vscode │ │ ├── launch.json │ │ └── tasks.json │ ├── Dockerfile │ ├── README.md │ ├── SendGridInbound.sln │ ├── Src │ │ └── Inbound │ │ │ ├── Controllers │ │ │ └── InboundController.cs │ │ │ ├── Inbound.csproj │ │ │ ├── Models │ │ │ ├── InboundEmail.cs │ │ │ ├── InboundEmailAddress.cs │ │ │ ├── InboundEmailAttachment.cs │ │ │ └── InboundEmailEnvelope.cs │ │ │ ├── Parsers │ │ │ └── InboundWebhookParser.cs │ │ │ ├── Program.cs │ │ │ ├── Startup.cs │ │ │ ├── Util │ │ │ ├── Extensions.cs │ │ │ └── InboundWebhookParserHelper.cs │ │ │ ├── Views │ │ │ └── Inbound │ │ │ │ └── Index.cshtml │ │ │ ├── appsettings.Development.json │ │ │ └── appsettings.json │ └── Tests │ │ └── Inbound.Tests │ │ ├── Inbound.Tests.csproj │ │ ├── IntegrationTests │ │ └── InboundEndpointsTests.cs │ │ ├── Parsers │ │ └── InboundWebhookParserTests.cs │ │ └── sample_data │ │ ├── default_data.txt │ │ ├── raw_data_with_attachments.txt │ │ └── raw_email_with_attachments.txt ├── ips │ └── ips.cs ├── mail │ └── mail.cs ├── mailboxproviders │ └── mailboxproviders.cs ├── mailsettings │ └── mailsettings.cs ├── partnersettings │ └── partnersettings.cs ├── scopes │ └── scopes.cs ├── senderauthentication │ └── senderauthentication.cs ├── senders │ └── senders.cs ├── stats │ └── stats.cs ├── subusers │ └── subusers.cs ├── suppression │ └── suppression.cs ├── templates │ └── templates.cs ├── trackingsettings │ └── trackingsettings.cs └── user │ └── user.cs ├── src ├── SendGrid.Extensions.DependencyInjection │ ├── InjectableSendGridClient.cs │ ├── SendGrid.Extensions.DependencyInjection.csproj │ └── ServiceCollectionExtensions.cs └── SendGrid │ ├── BaseClient.cs │ ├── BaseClientOptions.cs │ ├── Helpers │ ├── Errors │ │ ├── ErrorHandler.cs │ │ └── Model │ │ │ ├── BadRequestException.cs │ │ │ ├── ForbiddenException.cs │ │ │ ├── MethodNotAllowedException.cs │ │ │ ├── NotFoundException.cs │ │ │ ├── PayloadTooLargeException.cs │ │ │ ├── RequestErrorException.cs │ │ │ ├── SendGridErrorResponse.cs │ │ │ ├── SendGridInternalException.cs │ │ │ ├── ServerUnavailableException.cs │ │ │ ├── ServiceNotAvailableException.cs │ │ │ ├── TooManyRequestsException.cs │ │ │ ├── UnauthorizedException.cs │ │ │ └── UnsupportedMediaTypeException.cs │ ├── EventWebhook │ │ └── RequestValidator.cs │ ├── Mail │ │ ├── MailHelper.cs │ │ ├── Model │ │ │ ├── ASM.cs │ │ │ ├── Attachment.cs │ │ │ ├── BCCSettings.cs │ │ │ ├── BypassBounceManagement.cs │ │ │ ├── BypassListManagement.cs │ │ │ ├── BypassSpamManagement.cs │ │ │ ├── BypassUnsubscribeManagement.cs │ │ │ ├── ClickTracking.cs │ │ │ ├── Content.cs │ │ │ ├── EmailAddress.cs │ │ │ ├── FooterSettings.cs │ │ │ ├── Ganalytics.cs │ │ │ ├── HtmlContent.cs │ │ │ ├── JsonConverters.cs │ │ │ ├── MailSettings.cs │ │ │ ├── OpenTracking.cs │ │ │ ├── Personalization.cs │ │ │ ├── PlainTextContent.cs │ │ │ ├── SandboxMode.cs │ │ │ ├── SpamCheck.cs │ │ │ ├── SubscriptionTracking.cs │ │ │ └── TrackingSettings.cs │ │ ├── README.md │ │ └── SendGridMessage.cs │ ├── Net40 │ │ └── TypeExtensions.cs │ └── TaskUtilities.cs │ ├── ISendGridClient.cs │ ├── MimeType.cs │ ├── Permissions │ ├── ScopeOptions.cs │ ├── SendGridClientExtensions.cs │ ├── SendGridPermission.cs │ ├── SendGridPermissionsBuilder.Scopes.cs │ └── SendGridPermissionsBuilder.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Reliability │ ├── ReliabilitySettings.cs │ └── RetryDelegatingHandler.cs │ ├── Response.cs │ ├── SendGrid.csproj │ ├── SendGrid.ruleset │ ├── SendGridClient.cs │ ├── SendGridClientOptions.cs │ ├── TwilioEmailClient.cs │ ├── TwilioEmailClientOptions.cs │ └── stylecop.json ├── static └── img │ ├── github-fork.png │ └── github-sign-up.png ├── tests ├── SendGrid.Extensions.DependencyInjection.Tests │ ├── SendGrid.Extensions.DependencyInjection.Tests.csproj │ └── ServiceCollectionExtensionsTests.cs └── SendGrid.Tests │ ├── Helpers │ ├── EventWebhook │ │ └── RequestValidatorTests.cs │ └── Mail │ │ ├── EmailAddressTests.cs │ │ ├── MailHelperTests.cs │ │ ├── NonReadableStream.cs │ │ └── SendGridMessageTests.cs │ ├── Integration.cs │ ├── LicenseTests.cs │ ├── PermissionsBuilderTests.cs │ ├── PreSendEmailValidation │ └── WhenCreatingASendGridMessage.cs │ ├── Reliability │ ├── ReliabilitySettingsTests.cs │ ├── RetryDelegatingHandlerTests.cs │ └── RetryTestBehaviourDelegatingHandler.cs │ ├── RequiredFilesExistTest.cs │ ├── ResponseTests.cs │ ├── SendGrid.Tests.csproj │ ├── SendGridClientExtensionsTests.cs │ ├── SendgridEmailClientTests.cs │ ├── TemplateDataSerialisationTests.cs │ └── TwilioEmailClientTests.cs ├── tools └── sendgrid-csharp.snk └── twilio_sendgrid_logo.png /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # IDE1006: Naming Styles 4 | dotnet_diagnostic.IDE1006.severity = none 5 | -------------------------------------------------------------------------------- /.env_sample: -------------------------------------------------------------------------------- 1 | SENDGRID_API_KEY='' 2 | -------------------------------------------------------------------------------- /.github/workflows/pr-lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint PR 2 | on: 3 | pull_request_target: 4 | types: [ opened, edited, synchronize, reopened ] 5 | 6 | jobs: 7 | validate: 8 | name: Validate title 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: amannn/action-semantic-pull-request@v4 12 | with: 13 | types: chore docs fix feat test misc 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mono:latest 2 | 3 | ENV FrameworkPathOverride /usr/lib/mono/4.5/ 4 | 5 | RUN apt-get update \ 6 | && apt-get install -y curl make apt-transport-https 7 | 8 | RUN curl -sSL https://packages.microsoft.com/config/ubuntu/19.10/packages-microsoft-prod.deb -o packages-microsoft-prod.deb \ 9 | && dpkg --install packages-microsoft-prod.deb 10 | 11 | RUN apt-get update \ 12 | && apt-get install -y dotnet-sdk-2.1 13 | 14 | COPY prism/prism/nginx/cert.crt /usr/local/share/ca-certificates/cert.crt 15 | RUN update-ca-certificates 16 | 17 | COPY . . 18 | 19 | RUN make install 20 | -------------------------------------------------------------------------------- /ExampleCoreProject/ExampleCoreProject.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.1 5 | Exe 6 | false 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ExampleCoreProject/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using SendGrid; 6 | using SendGrid.Extensions.DependencyInjection; 7 | using SendGrid.Helpers.Mail; 8 | 9 | namespace Example 10 | { 11 | internal class Program 12 | { 13 | private static IConfiguration Configuration { get; set; } 14 | 15 | private static async Task Main() 16 | { 17 | var env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production"; 18 | Configuration = new ConfigurationBuilder() 19 | .AddJsonFile("appsettings.json", optional: true) 20 | .AddJsonFile($"appsettings.{env}.json", optional: true) 21 | .Build(); 22 | var services = ConfigureServices(new ServiceCollection()).BuildServiceProvider(); 23 | var client = services.GetRequiredService(); 24 | var from = new EmailAddress(Configuration.GetValue("SendGrid:From", "test@example.com"), "Example User"); 25 | var to = new EmailAddress(Configuration.GetValue("SendGrid:To", "test@example.com"), "Example User"); 26 | var msg = new SendGridMessage 27 | { 28 | From = from, 29 | Subject = "Sending with Twilio SendGrid is Fun" 30 | }; 31 | msg.AddContent(MimeType.Text, "and easy to do anywhere, even with C#"); 32 | msg.AddTo(to); 33 | if (Configuration.GetValue("SendGrid:SandboxMode", false)) 34 | { 35 | msg.MailSettings = new MailSettings 36 | { 37 | SandboxMode = new SandboxMode 38 | { 39 | Enable = true 40 | } 41 | }; 42 | } 43 | Console.WriteLine($"Sending email with payload: \n{msg.Serialize()}"); 44 | var response = await client.SendEmailAsync(msg).ConfigureAwait(false); 45 | 46 | Console.WriteLine($"Response: {response.StatusCode}"); 47 | Console.WriteLine(response.Headers); 48 | } 49 | 50 | private static IServiceCollection ConfigureServices(IServiceCollection services) 51 | { 52 | services.AddSendGrid(options => { options.ApiKey = Environment.GetEnvironmentVariable("SENDGRID_API_KEY") ?? Configuration["SendGrid:ApiKey"]; }); 53 | 54 | return services; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/README.md: -------------------------------------------------------------------------------- 1 | **The Twilio SendGrid C# .NET library provides an easy way to send emails. This example application shows how to integrate with an ASP.NET application.** 2 | 3 | # Installation 4 | 5 | ## Prerequisites 6 | 7 | - .NET version 4.5.2 and higher 8 | - Visual Studio 2015 9 | 10 | ## Setup Environment Variables 11 | 12 | Update the "SendGridApiKey" appSettings variable within the web.config file. 13 | 14 | ## Steps 15 | 16 | 1. Open SendGrid.ASPSamples.sln 17 | 2. Switch to one of the example project (right-click on a project -> "Set as StartUp project") 18 | 3. Build and run the project 19 | 20 | You may need to download the latest Nuget executable and run `nuget.exe restore` 21 | 22 | 4. When you run the project, a web form will launch in your browser that will send an email. 23 | 24 | ## Happy coding 25 | 26 | Big thanks to [paritosh baghel](https://github.com/paritoshmmmec) for contributing this example code! 27 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SendGrid.ASPSamples", "SendGrid.ASPSamples\SendGrid.ASPSamples.csproj", "{14FA0F22-DFB2-4CE2-867A-242E75F64E1B}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SendGrid.ASPWebFormsSamples", "SendGrid.ASPWebFormsSamples\SendGrid.ASPWebFormsSamples.csproj", "{0A24E647-5885-477C-A766-7385BCC6982E}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {14FA0F22-DFB2-4CE2-867A-242E75F64E1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {14FA0F22-DFB2-4CE2-867A-242E75F64E1B}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {14FA0F22-DFB2-4CE2-867A-242E75F64E1B}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {14FA0F22-DFB2-4CE2-867A-242E75F64E1B}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {0A24E647-5885-477C-A766-7385BCC6982E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {0A24E647-5885-477C-A766-7385BCC6982E}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {0A24E647-5885-477C-A766-7385BCC6982E}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {0A24E647-5885-477C-A766-7385BCC6982E}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {36445F8F-3714-4B6A-89DB-17DC0C001CF5} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace SendGrid.ASPSamples 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace SendGrid.ASPSamples 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace SendGrid.ASPSamples 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Email", action = "Send", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Controllers/EmailController.cs: -------------------------------------------------------------------------------- 1 | using SendGrid.ASPSamples.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web; 6 | using System.Web.Mvc; 7 | 8 | namespace SendGrid.ASPSamples.Controllers 9 | { 10 | public class EmailController : Controller 11 | { 12 | private SendGridEmailService _sendGridEmailService; 13 | public EmailController() 14 | { 15 | _sendGridEmailService = new SendGridEmailService(); 16 | } 17 | 18 | public ActionResult Send() 19 | { 20 | return View(); 21 | } 22 | 23 | [HttpPost] 24 | public ActionResult Send(EmailContract emailContract) 25 | { 26 | if (!ModelState.IsValid) 27 | { 28 | return View(model); 29 | } 30 | 31 | try 32 | { 33 | var response= _sendGridEmailService.Send(emailContract); 34 | ViewBag.Success = true; 35 | return View(); 36 | } 37 | catch (Exception) 38 | { 39 | ViewBag.Success = false; 40 | return View(); 41 | } 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="SendGrid.ASPSamples.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace SendGrid.ASPSamples 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Models/EmailContract.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Web; 6 | 7 | namespace SendGrid.ASPSamples.Models 8 | { 9 | public class EmailContract 10 | { 11 | [Required] 12 | [Display(Name = "From Email Address")] 13 | [EmailAddress] 14 | public string FromEmailAddress { get; set; } 15 | 16 | public string Alias { get; set; } 17 | 18 | [Required] 19 | [Display(Name = "To Email Address")] 20 | [EmailAddress] 21 | public string ToEmailAddress { get; set; } 22 | 23 | [Display(Name = "Cc Email Address")] 24 | [EmailAddress] 25 | public string CcEmailAddress { get; set; } 26 | 27 | [Display(Name = "Bcc Email Address")] 28 | [EmailAddress] 29 | public string BccEmailAddress { get; set; } 30 | 31 | [Required] 32 | [Display(Name = "Subject")] 33 | public string Subject { get; set; } 34 | 35 | [Required] 36 | [Display(Name = "Body")] 37 | public string Body { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Models/EmailServiceException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace SendGrid.ASPSamples 5 | { 6 | public class EmailServiceException : Exception 7 | { 8 | public string Body { get;private set; } 9 | 10 | public EmailServiceException(string message, string body) : base(message) 11 | { 12 | Body = body; 13 | } 14 | 15 | public EmailServiceException(string message, string body, Exception innerException) : base(message, innerException) 16 | { 17 | Body = body; 18 | } 19 | } 20 | 21 | 22 | public class EmailResponse 23 | { 24 | public DateTime DateSent { get; internal set; } 25 | public string UniqueMessageId { get; internal set; } 26 | } 27 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Models/IdentityModels.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using System.Security.Claims; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.AspNet.Identity.EntityFramework; 6 | 7 | namespace SendGrid.ASPSamples.Models 8 | { 9 | // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. 10 | public class ApplicationUser : IdentityUser 11 | { 12 | public async Task GenerateUserIdentityAsync(UserManager manager) 13 | { 14 | // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 15 | var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 16 | // Add custom user claims here 17 | return userIdentity; 18 | } 19 | } 20 | 21 | public class ApplicationDbContext : IdentityDbContext 22 | { 23 | public ApplicationDbContext() 24 | : base("DefaultConnection", throwIfV1Schema: false) 25 | { 26 | } 27 | 28 | public static ApplicationDbContext Create() 29 | { 30 | return new ApplicationDbContext(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SendGrid.ASPSamples")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SendGrid.ASPSamples")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4e1c368a-1144-44ee-a8ba-3d2776537ecc")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/ExampleNet45ASPNetProject/SendGrid.ASPSamples/Scripts/_references.js -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Service/SendGridEmailService.cs: -------------------------------------------------------------------------------- 1 | using SendGrid.ASPSamples.Models; 2 | using SendGrid.Helpers.Mail; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Net.Http.Headers; 8 | using System.Web; 9 | 10 | namespace SendGrid.ASPSamples 11 | { 12 | public class SendGridEmailService 13 | { 14 | private readonly SendGridClient _client; 15 | private string apiKey = ConfigurationManager.AppSettings["SendGridApiKey"]; 16 | private static readonly string MessageId = "X-Message-Id"; 17 | 18 | public SendGridEmailService() 19 | { 20 | _client = new SendGridClient(apiKey); 21 | } 22 | 23 | public EmailResponse Send(EmailContract contract) 24 | { 25 | 26 | var emailMessage = new SendGridMessage() 27 | { 28 | From = new EmailAddress(contract.FromEmailAddress, contract.Alias), 29 | Subject = contract.Subject, 30 | HtmlContent = contract.Body 31 | }; 32 | 33 | emailMessage.AddTo(new EmailAddress(contract.ToEmailAddress)); 34 | if (!string.IsNullOrWhiteSpace(contract.BccEmailAddress)) 35 | { 36 | emailMessage.AddBcc(new EmailAddress(contract.BccEmailAddress)); 37 | } 38 | 39 | if (!string.IsNullOrWhiteSpace(contract.CcEmailAddress)) 40 | { 41 | emailMessage.AddCc(new EmailAddress(contract.CcEmailAddress)); 42 | } 43 | 44 | return ProcessResponse(_client.SendEmailAsync(emailMessage).Result); 45 | } 46 | 47 | private EmailResponse ProcessResponse(Response response) 48 | { 49 | if (response.StatusCode.Equals(System.Net.HttpStatusCode.Accepted) 50 | || response.StatusCode.Equals(System.Net.HttpStatusCode.OK)) 51 | { 52 | return ToMailResponse(response); 53 | } 54 | 55 | //TODO check for null 56 | var errorResponse = response.Body.ReadAsStringAsync().Result; 57 | 58 | throw new EmailServiceException(response.StatusCode.ToString(), errorResponse); 59 | } 60 | 61 | private static EmailResponse ToMailResponse(Response response) 62 | { 63 | if (response == null) 64 | return null; 65 | 66 | var headers = (HttpHeaders)response.Headers; 67 | var messageId = headers.GetValues(MessageId).FirstOrDefault(); 68 | return new EmailResponse() 69 | { 70 | UniqueMessageId = messageId, 71 | DateSent = DateTime.UtcNow, 72 | }; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin; 2 | using Owin; 3 | 4 | [assembly: OwinStartupAttribute(typeof(SendGrid.ASPSamples.Startup))] 5 | namespace SendGrid.ASPSamples 6 | { 7 | public partial class Startup 8 | { 9 | public void Configuration(IAppBuilder app) 10 | { 11 | ConfigureAuth(app); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/Email/Send.cshtml: -------------------------------------------------------------------------------- 1 | @model SendGrid.ASPSamples.Models.EmailContract 2 | @{ 3 | ViewBag.Title = "Register"; 4 | } 5 | 6 | @using (Html.BeginForm("Send", "Email", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 7 | { 8 | @Html.AntiForgeryToken() 9 |

Send an Email

10 |
11 | @Html.ValidationSummary("", new { @class = "text-danger" }) 12 | 13 | if (ViewBag.Success!=null && (bool)ViewBag.Success) 14 | { 15 |

Email sent. Happy coding

16 | } 17 | else if(ViewBag.Success != null && !(bool)ViewBag.Success) 18 | { 19 |

Ooops , retry ninja

20 | } 21 | 22 | 23 |
24 | @Html.LabelFor(m => m.FromEmailAddress, new { @class = "col-md-2 control-label" }) 25 |
26 | @Html.TextBoxFor(m => m.FromEmailAddress, new { @class = "form-control" }) 27 |
28 |
29 |
30 | @Html.LabelFor(m => m.ToEmailAddress, new { @class = "col-md-2 control-label" }) 31 |
32 | @Html.TextBoxFor(m => m.ToEmailAddress, new { @class = "form-control" }) 33 |
34 |
35 |
36 | @Html.LabelFor(m => m.BccEmailAddress, new {@class = "col-md-2 control-label"}) 37 |
38 | @Html.TextBoxFor(m => m.BccEmailAddress, new {@class = "form-control"}) 39 |
40 |
41 |
42 | @Html.LabelFor(m => m.CcEmailAddress, new {@class = "col-md-2 control-label"}) 43 |
44 | @Html.TextBoxFor(m => m.CcEmailAddress, new {@class = "form-control"}) 45 |
46 |
47 |
48 | @Html.LabelFor(m => m.Subject, new { @class = "col-md-2 control-label" }) 49 |
50 | @Html.TextBoxFor(m => m.Subject, new { @class = "form-control" }) 51 |
52 |
53 |
54 | @Html.LabelFor(m => m.Body, new { @class = "col-md-2 control-label" }) 55 |
56 | @Html.TextAreaFor(m => m.Body, new { @class = "form-control" }) 57 |
58 |
59 |
60 |
61 | 62 |
63 |
64 | } 65 | 66 | @section Scripts { 67 | @Scripts.Render("~/bundles/jqueryval") 68 | } 69 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model System.Web.Mvc.HandleErrorInfo 2 | 3 | @{ 4 | ViewBag.Title = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/Shared/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @model System.Web.Mvc.HandleErrorInfo 2 | 3 | @{ 4 | ViewBag.Title = "Locked Out"; 5 | } 6 | 7 |
8 |

Locked out.

9 |

This account has been locked out, please try again later.

10 |
11 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 12 | 32 |
33 | @RenderBody() 34 |
35 |
36 |

© @DateTime.Now.Year - My ASP.NET Application

37 |
38 |
39 | 40 | @Scripts.Render("~/bundles/jquery") 41 | @Scripts.Render("~/bundles/bootstrap") 42 | @RenderSection("scripts", required: false) 43 | 44 | 45 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNet.Identity 2 | @if (Request.IsAuthenticated) 3 | { 4 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) 5 | { 6 | @Html.AntiForgeryToken() 7 | 8 | 14 | } 15 | } 16 | else 17 | { 18 | 22 | } 23 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/ExampleNet45ASPNetProject/SendGrid.ASPSamples/favicon.ico -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/ExampleNet45ASPNetProject/SendGrid.ASPSamples/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/ExampleNet45ASPNetProject/SendGrid.ASPSamples/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPSamples/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/ExampleNet45ASPNetProject/SendGrid.ASPSamples/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/ApplicationInsights.config: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Content/Site.css: -------------------------------------------------------------------------------- 1 | /* Wrap content on words otherwise the body response overflows in the Well*/ 2 | .well { 3 | word-wrap: break-word; 4 | } 5 | 6 | /* Move down content because we have a fixed navbar that is 50px tall */ 7 | body { 8 | padding-top: 50px; 9 | padding-bottom: 20px; 10 | } 11 | 12 | /* Wrapping element */ 13 | /* Set some basic padding to keep content from hitting the edges */ 14 | .body-content { 15 | padding-left: 15px; 16 | padding-right: 15px; 17 | margin-top: 50px; 18 | } 19 | 20 | /* Responsive: Portrait tablets and up */ 21 | @media screen and (min-width: 768px) { 22 | .body-content { 23 | padding: 0; 24 | } 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Web.UI; 4 | using SendGrid.ASPWebFormsSamples.Models; 5 | using SendGrid.ASPWebFormsSamples.Services; 6 | 7 | namespace SendGrid.ASPWebFormsSamples 8 | { 9 | public partial class Default : Page 10 | { 11 | private readonly SendGridService _sendGridService; 12 | 13 | protected Default() 14 | { 15 | _sendGridService = new SendGridService(); 16 | } 17 | 18 | protected void Page_Load(object sender, EventArgs e) 19 | { 20 | responseInfo.Visible = false; 21 | } 22 | 23 | protected async void sendButton_Click(object sender, EventArgs e) 24 | { 25 | // Prepare the email message info model 26 | var messageInfo = new EmailMessageInfo 27 | { 28 | FromEmailAddress = fromInput.Value, 29 | ToEmailAddress = toInput.Value, 30 | CcEmailAddress = ccInput.Value, 31 | BccEmailAddress = bccInput.Value, 32 | EmailSubject = subjectInput.Value, 33 | EmailBody = bodyInput.Value 34 | }; 35 | 36 | // Make an API call, and save the response 37 | var apiResponse = await _sendGridService.Send(messageInfo); 38 | 39 | await SetResponseInfoContainers(apiResponse); 40 | } 41 | 42 | private async Task SetResponseInfoContainers(Response apiResponse) 43 | { 44 | responseInfo.Visible = true; 45 | responseStatus.InnerText = $"Statuscode {(int)apiResponse.StatusCode}: {apiResponse.StatusCode}"; 46 | responseBody.InnerText = await apiResponse.Body.ReadAsStringAsync(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="SendGrid.ASPWebFormsSamples.Global" Language="C#" %> 2 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | namespace SendGrid.ASPWebFormsSamples 5 | { 6 | public class Global : HttpApplication 7 | { 8 | void Application_Start(object sender, EventArgs e) 9 | { 10 | // Code that runs on application startup 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Models/EmailMessageInfo.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.ASPWebFormsSamples.Models 2 | { 3 | public class EmailMessageInfo 4 | { 5 | public string FromEmailAddress { get; set; } 6 | 7 | public string ToEmailAddress { get; set; } 8 | 9 | public string CcEmailAddress { get; set; } 10 | 11 | public string BccEmailAddress { get; set; } 12 | 13 | public string EmailSubject { get; set; } 14 | 15 | public string EmailBody { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SendGrid.ASPWebFormsSamples")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SendGrid.ASPWebFormsSamples")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0a24e647-5885-477c-a766-7385bcc6982e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Services/SendGridService.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Threading.Tasks; 3 | using SendGrid.ASPWebFormsSamples.Models; 4 | using SendGrid.Helpers.Mail; 5 | 6 | namespace SendGrid.ASPWebFormsSamples.Services 7 | { 8 | public class SendGridService 9 | { 10 | private readonly SendGridClient _client; 11 | 12 | public SendGridService() 13 | { 14 | // Retrieve the API key from an appSettings variable from the web.config 15 | var apiKey = ConfigurationManager.AppSettings["SendGrid_API_Key"]; 16 | 17 | // Initialize the Twilio SendGrid client 18 | _client = new SendGridClient(apiKey); 19 | } 20 | 21 | public async Task Send(EmailMessageInfo messageInfo) 22 | { 23 | // Prepare the Twilio SendGrid email message 24 | var sendgridMessage = new SendGridMessage 25 | { 26 | From = new EmailAddress(messageInfo.FromEmailAddress), 27 | Subject = messageInfo.EmailSubject, 28 | HtmlContent = messageInfo.EmailBody 29 | }; 30 | 31 | // Add the "To" email address to the message 32 | sendgridMessage.AddTo(new EmailAddress(messageInfo.ToEmailAddress)); 33 | 34 | // Check if any Cc email address was specified 35 | if (!string.IsNullOrWhiteSpace(messageInfo.CcEmailAddress)) 36 | { 37 | // Add the email address for Cc to the message 38 | sendgridMessage.AddCc(new EmailAddress(messageInfo.CcEmailAddress)); 39 | } 40 | 41 | // Check if any Bcc email address was specified 42 | if (!string.IsNullOrWhiteSpace(messageInfo.BccEmailAddress)) 43 | { 44 | // Add the email address for Bcc to the message 45 | sendgridMessage.AddBcc(new EmailAddress(messageInfo.BccEmailAddress)); 46 | } 47 | 48 | // Send the message to Twilio SendGrid, and save the API response 49 | var response = await _client.SendEmailAsync(sendgridMessage); 50 | 51 | // Return the Twilio SendGrid response 52 | return response; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Site.Master: -------------------------------------------------------------------------------- 1 | <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="SendGrid.ASPWebFormsSamples.SiteMaster" %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <%: Page.Title %> - WebForms Example 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 25 |
26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Site.Master.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace SendGrid.ASPWebFormsSamples 9 | { 10 | public partial class SiteMaster : MasterPage 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Site.Master.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace SendGrid.ASPWebFormsSamples { 11 | 12 | 13 | public partial class SiteMaster { 14 | 15 | /// 16 | /// MainContent control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/favicon.ico -------------------------------------------------------------------------------- /ExampleNet45ASPNetProject/SendGrid.ASPWebFormsSamples/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ExampleNet45Project/ExampleNet45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452 5 | Exe 6 | false 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /FIRST_TIMERS.md: -------------------------------------------------------------------------------- 1 | # How To Contribute to Twilio SendGrid Repositories via GitHub 2 | Contributing to the Twilio SendGrid repositories is easy! All you need to do is find an open issue (see the bottom of this page for a list of repositories containing open issues), fix it and submit a pull request. Once you have submitted your pull request, the team can easily review it before it is merged into the repository. 3 | 4 | To make a pull request, follow these steps: 5 | 6 | 1. Log into GitHub. If you do not already have a GitHub account, you will have to create one in order to submit a change. Click the Sign up link in the upper right-hand corner to create an account. Enter your username, password, and email address. If you are an employee of Twilio SendGrid, please use your full name with your GitHub account and enter Twilio SendGrid as your company so we can easily identify you. 7 | 8 | 9 | 10 | 2. __[Fork](https://help.github.com/fork-a-repo/)__ the [sendgrid-csharp](https://github.com/sendgrid/sendgrid-csharp) repository: 11 | 12 | 13 | 14 | 3. __Clone__ your fork via the following commands: 15 | 16 | ```bash 17 | # Clone your fork of the repo into the current directory 18 | git clone https://github.com/your_username/sendgrid-csharp 19 | # Navigate to the newly cloned directory 20 | cd sendgrid-csharp 21 | # Assign the original repo to a remote called "upstream" 22 | git remote add upstream https://github.com/sendgrid/sendgrid-csharp 23 | ``` 24 | 25 | > Don't forget to replace *your_username* in the URL by your real GitHub username. 26 | 27 | 4. __Create a new topic branch__ (off the main project development branch) to contain your feature, change, or fix: 28 | 29 | ```bash 30 | git checkout -b 31 | ``` 32 | 33 | 5. __Commit your changes__ in logical chunks. 34 | 35 | Please adhere to these [git commit message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) or your code is unlikely be merged into the main project. Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public. Probably you will also have to create tests (if needed) or create or update the example code that demonstrates the functionality of this change to the code. 36 | 37 | 6. __Locally merge (or rebase)__ the upstream development branch into your topic branch: 38 | 39 | ```bash 40 | git pull [--rebase] upstream main 41 | ``` 42 | 43 | 7. __Push__ your topic branch up to your fork: 44 | 45 | ```bash 46 | git push origin 47 | ``` 48 | 49 | 8. __[Open a Pull Request](https://help.github.com/articles/creating-a-pull-request/#changing-the-branch-range-and-destination-repository/)__ with a clear title and description against the `main` branch. All tests must be passing before we will review the PR. 50 | 51 | ## Important notice 52 | 53 | Before creating a pull request, make sure that you respect the repository's constraints regarding contributions. You can find them in the [CONTRIBUTING.md](CONTRIBUTING.md) file. 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2024, Twilio SendGrid, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean install test test-integ test-docker release 2 | 3 | clean: 4 | dotnet clean 5 | 6 | install: 7 | @dotnet --version || (echo "Dotnet is not installed, please install Dotnet CLI"; exit 1); 8 | 9 | test: 10 | dotnet build -c Release 11 | dotnet test -c Release 12 | curl -s https://codecov.io/bash > .codecov 13 | chmod +x .codecov 14 | ./.codecov 15 | 16 | test-integ: test 17 | 18 | test-docker: 19 | curl -s https://raw.githubusercontent.com/sendgrid/sendgrid-oai/HEAD/prism/prism.sh -o prism.sh 20 | bash ./prism.sh 21 | 22 | release: 23 | dotnet pack -c Release 24 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | # Fixes # 18 | 19 | A short description of what this PR does. 20 | 21 | ### Checklist 22 | - [x] I acknowledge that all my contributions will be made under the project's license 23 | - [ ] I have made a material change to the repo (functionality, testing, spelling, grammar) 24 | - [ ] I have read the [Contribution Guidelines](https://github.com/sendgrid/sendgrid-csharp/blob/main/CONTRIBUTING.md) and my PR follows them 25 | - [ ] I have titled the PR appropriately 26 | - [ ] I have updated my branch with the main branch 27 | - [ ] I have added tests that prove my fix is effective or that my feature works 28 | - [ ] I have added the necessary documentation about the functionality in the appropriate .md file 29 | - [ ] I have added inline documentation to the code I modified 30 | 31 | If you have questions, please file a [support ticket](https://support.sendgrid.com), or create a GitHub Issue in this repository. 32 | -------------------------------------------------------------------------------- /examples/alerts/alerts.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Create a new Alert 12 | // POST /alerts 13 | 14 | string data = @"{ 15 | 'email_to': 'example@example.com', 16 | 'frequency': 'daily', 17 | 'type': 'stats_notification' 18 | }"; 19 | Object json = JsonConvert.DeserializeObject(data); 20 | data = json.ToString(); 21 | var response = await client.RequestAsync(method: SendGridClient.Method.POST, urlPath: "alerts", requestBody: data); 22 | Console.WriteLine(response.StatusCode); 23 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 24 | Console.WriteLine(response.Headers.ToString()); 25 | Console.ReadLine(); 26 | 27 | //////////////////////////////////////////////////////// 28 | // Retrieve all alerts 29 | // GET /alerts 30 | 31 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "alerts"); 32 | Console.WriteLine(response.StatusCode); 33 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 34 | Console.WriteLine(response.Headers.ToString()); 35 | Console.ReadLine(); 36 | 37 | //////////////////////////////////////////////////////// 38 | // Update an alert 39 | // PATCH /alerts/{alert_id} 40 | 41 | string data = @"{ 42 | 'email_to': 'example@example.com' 43 | }"; 44 | Object json = JsonConvert.DeserializeObject(data); 45 | data = json.ToString(); 46 | var alert_id = "test_url_param"; 47 | var response = await client.RequestAsync(method: SendGridClient.Method.PATCH, urlPath: "alerts/" + alert_id, requestBody: data); 48 | Console.WriteLine(response.StatusCode); 49 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 50 | Console.WriteLine(response.Headers.ToString()); 51 | Console.ReadLine(); 52 | 53 | //////////////////////////////////////////////////////// 54 | // Retrieve a specific alert 55 | // GET /alerts/{alert_id} 56 | 57 | var alert_id = "test_url_param"; 58 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "alerts/" + alert_id); 59 | Console.WriteLine(response.StatusCode); 60 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 61 | Console.WriteLine(response.Headers.ToString()); 62 | Console.ReadLine(); 63 | 64 | //////////////////////////////////////////////////////// 65 | // Delete an alert 66 | // DELETE /alerts/{alert_id} 67 | 68 | var alert_id = "test_url_param"; 69 | var response = await client.RequestAsync(method: SendGridClient.Method.DELETE, urlPath: "alerts/" + alert_id); 70 | Console.WriteLine(response.StatusCode); 71 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 72 | Console.WriteLine(response.Headers.ToString()); 73 | Console.ReadLine(); 74 | 75 | -------------------------------------------------------------------------------- /examples/browsers/browsers.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve email statistics by browser. 12 | // GET /browsers/stats 13 | 14 | string queryParams = @"{ 15 | 'aggregated_by': 'day', 16 | 'browsers': 'test_string', 17 | 'end_date': '2016-04-01', 18 | 'limit': 'test_string', 19 | 'offset': 'test_string', 20 | 'start_date': '2016-01-01' 21 | }"; 22 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "browsers/stats", queryParams: queryParams); 23 | Console.WriteLine(response.StatusCode); 24 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 25 | Console.WriteLine(response.Headers.ToString()); 26 | Console.ReadLine(); 27 | 28 | -------------------------------------------------------------------------------- /examples/categories/categories.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve all categories 12 | // GET /categories 13 | 14 | string queryParams = @"{ 15 | 'category': 'test_string', 16 | 'limit': 1, 17 | 'offset': 1 18 | }"; 19 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "categories", queryParams: queryParams); 20 | Console.WriteLine(response.StatusCode); 21 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 22 | Console.WriteLine(response.Headers.ToString()); 23 | Console.ReadLine(); 24 | 25 | //////////////////////////////////////////////////////// 26 | // Retrieve Email Statistics for Categories 27 | // GET /categories/stats 28 | 29 | string queryParams = @"{ 30 | 'aggregated_by': 'day', 31 | 'categories': 'test_string', 32 | 'end_date': '2016-04-01', 33 | 'limit': 1, 34 | 'offset': 1, 35 | 'start_date': '2016-01-01' 36 | }"; 37 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "categories/stats", queryParams: queryParams); 38 | Console.WriteLine(response.StatusCode); 39 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 40 | Console.WriteLine(response.Headers.ToString()); 41 | Console.ReadLine(); 42 | 43 | //////////////////////////////////////////////////////// 44 | // Retrieve sums of email stats for each category [Needs: Stats object defined, has category ID?] 45 | // GET /categories/stats/sums 46 | 47 | string queryParams = @"{ 48 | 'aggregated_by': 'day', 49 | 'end_date': '2016-04-01', 50 | 'limit': 1, 51 | 'offset': 1, 52 | 'sort_by_direction': 'asc', 53 | 'sort_by_metric': 'test_string', 54 | 'start_date': '2016-01-01' 55 | }"; 56 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "categories/stats/sums", queryParams: queryParams); 57 | Console.WriteLine(response.StatusCode); 58 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 59 | Console.WriteLine(response.Headers.ToString()); 60 | Console.ReadLine(); 61 | 62 | -------------------------------------------------------------------------------- /examples/clients/clientOptions.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var options = new SendGridClientOptions(); 9 | 10 | 11 | //////////////////////////////////////////////////////// 12 | // Available Sendgrid Client Options to set region as "eu" 13 | 14 | var client_option_region = "eu"; 15 | options.SetDataResidency(client_option_region); 16 | var client = new SendGridClient(options); 17 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "clients/stats"); 18 | Console.WriteLine(response.StatusCode); 19 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 20 | Console.WriteLine(response.Headers.ToString()); 21 | Console.ReadLine(); 22 | 23 | //////////////////////////////////////////////////////// 24 | // Available Sendgrid Client Options to set region as "global" 25 | 26 | var client_option_region = "global"; 27 | options.SetDataResidency(client_option_region); 28 | var client = new SendGridClient(options); 29 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "clients/stats"); 30 | Console.WriteLine(response.StatusCode); 31 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 32 | Console.WriteLine(response.Headers.ToString()); 33 | Console.ReadLine(); 34 | 35 | -------------------------------------------------------------------------------- /examples/clients/clients.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve email statistics by client type. 12 | // GET /clients/stats 13 | 14 | string queryParams = @"{ 15 | 'aggregated_by': 'day', 16 | 'end_date': '2016-04-01', 17 | 'start_date': '2016-01-01' 18 | }"; 19 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "clients/stats", queryParams: queryParams); 20 | Console.WriteLine(response.StatusCode); 21 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 22 | Console.WriteLine(response.Headers.ToString()); 23 | Console.ReadLine(); 24 | 25 | //////////////////////////////////////////////////////// 26 | // Retrieve stats by a specific client type. 27 | // GET /clients/{client_type}/stats 28 | 29 | string queryParams = @"{ 30 | 'aggregated_by': 'day', 31 | 'end_date': '2016-04-01', 32 | 'start_date': '2016-01-01' 33 | }"; 34 | var client_type = "test_url_param"; 35 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "clients/" + client_type + "/stats", queryParams: queryParams); 36 | Console.WriteLine(response.StatusCode); 37 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 38 | Console.WriteLine(response.Headers.ToString()); 39 | Console.ReadLine(); 40 | 41 | -------------------------------------------------------------------------------- /examples/devices/devices.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve email statistics by device type. 12 | // GET /devices/stats 13 | 14 | string queryParams = @"{ 15 | 'aggregated_by': 'day', 16 | 'end_date': '2016-04-01', 17 | 'limit': 1, 18 | 'offset': 1, 19 | 'start_date': '2016-01-01' 20 | }"; 21 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "devices/stats", queryParams: queryParams); 22 | Console.WriteLine(response.StatusCode); 23 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 24 | Console.WriteLine(response.Headers.ToString()); 25 | Console.ReadLine(); 26 | 27 | -------------------------------------------------------------------------------- /examples/eventwebhook/RequestValidator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using SendGrid.Helpers.EventWebhook; 3 | using System.IO; 4 | 5 | public bool IsValidSignature(HttpRequest request) 6 | { 7 | var publicKey = "base64-encoded public key"; 8 | string requestBody; 9 | 10 | using (var reader = new StreamReader(request.Body)) 11 | { 12 | requestBody = reader.ReadToEnd(); 13 | } 14 | 15 | var validator = new RequestValidator(); 16 | var ecPublicKey = validator.ConvertPublicKeyToECDSA(publicKey); 17 | 18 | return validator.VerifySignature( 19 | ecPublicKey, 20 | requestBody, 21 | request.Headers[RequestValidator.SIGNATURE_HEADER], 22 | request.Headers[RequestValidator.TIMESTAMP_HEADER] 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:2.1-sdk AS build 2 | WORKDIR /App 3 | 4 | # copy csproj and restore as distinct layers 5 | COPY *.sln . 6 | COPY Src/EventWebhook/*.csproj ./Src/EventWebhook/ 7 | COPY Tests/EventWebhook.Tests/*.csproj ./Tests/EventWebhook.Tests/ 8 | RUN dotnet restore 9 | 10 | # copy everything else and build app 11 | COPY Src/EventWebhook/. ./Src/EventWebhook/ 12 | WORKDIR /App/Src/EventWebhook 13 | RUN dotnet publish -c Release -o Out 14 | 15 | FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime 16 | WORKDIR /App 17 | COPY --from=build /App/Src/EventWebhook/Out ./ 18 | 19 | RUN echo "ASPNETCORE_URLS=http://0.0.0.0:\$PORT\nDOTNET_RUNNING_IN_CONTAINER=true" > /App/SetupHerokuEnv.sh && chmod +x /App/SetupHerokuEnv.sh 20 | 21 | CMD /bin/bash -c "source /App/SetupHerokuEnv.sh && dotnet EventWebhook.dll" -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Controllers/EventWebhookController.cs: -------------------------------------------------------------------------------- 1 | using EventWebhook.Models; 2 | using EventWebhook.Parser; 3 | using Microsoft.AspNetCore.Mvc; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | namespace EventWebhook.Controllers 8 | { 9 | [Route("/")] 10 | public class EventWebhookController : Controller 11 | { 12 | /// 13 | /// GET : Index page 14 | /// 15 | [Route("")] 16 | public IActionResult Index() 17 | { 18 | return View(); 19 | } 20 | 21 | /// 22 | /// POST : Event webhook handler 23 | /// 24 | /// 25 | [Route("/events")] 26 | [HttpPost] 27 | public async Task Events() 28 | { 29 | IEnumerable events = await EventParser.ParseAsync(Request.Body); 30 | 31 | return Ok(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Converters/CategoryConverter.cs: -------------------------------------------------------------------------------- 1 | using EventWebhook.Models; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Linq; 5 | 6 | namespace EventWebhook.Converters 7 | { 8 | public class CategoryConverter : JsonConverter 9 | { 10 | private readonly Type[] _types; 11 | 12 | public CategoryConverter() 13 | { 14 | _types = new Type[] { typeof(string), typeof(string[]) }; 15 | } 16 | 17 | public override bool CanConvert(Type objectType) 18 | { 19 | return _types.Any(t => t == objectType); 20 | } 21 | 22 | public override bool CanWrite => true; 23 | 24 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 25 | { 26 | if (reader.TokenType == JsonToken.StartArray) 27 | { 28 | return new Category(serializer.Deserialize(reader), JsonToken.StartArray); 29 | } 30 | else 31 | { 32 | return new Category(new[] { serializer.Deserialize(reader) }, reader.TokenType); 33 | } 34 | } 35 | 36 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 37 | { 38 | if (value is Category category) 39 | { 40 | if (category.IsArray) 41 | { 42 | serializer.Serialize(writer, category); 43 | } else 44 | { 45 | serializer.Serialize(writer, category.Value[0]); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Converters/UriConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace EventWebhook.Converters 5 | { 6 | public class UriConverter : JsonConverter 7 | { 8 | public override bool CanConvert(Type objectType) => objectType == typeof(string); 9 | 10 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 11 | { 12 | if (reader.TokenType == JsonToken.Null) 13 | { 14 | return null; 15 | } 16 | 17 | if (reader.TokenType == JsonToken.String) 18 | { 19 | return new Uri((string)reader.Value); 20 | } 21 | 22 | throw new InvalidOperationException("Invalid Url"); 23 | } 24 | 25 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 26 | { 27 | if (null == value) 28 | { 29 | writer.WriteNull(); 30 | return; 31 | } 32 | 33 | if (value is Uri) 34 | { 35 | writer.WriteValue(((Uri)value).OriginalString); 36 | return; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/EventWebhook.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/BounceEvent.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | 4 | namespace EventWebhook.Models 5 | { 6 | public class BounceEvent : DroppedEvent 7 | { 8 | [JsonConverter(typeof(StringEnumConverter))] 9 | public BounceEventType BounceType { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/BounceEventType.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public enum BounceEventType 4 | { 5 | Bounce, 6 | Blocked, 7 | Expired 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/Category.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace EventWebhook.Models 4 | { 5 | public class Category 6 | { 7 | public string[] Value { get; } 8 | private JsonToken _jsonToken; 9 | 10 | public Category(string[] value, JsonToken jsonToken) 11 | { 12 | Value = value; 13 | _jsonToken = jsonToken; 14 | } 15 | 16 | [JsonIgnore] 17 | public bool IsArray => _jsonToken == JsonToken.StartArray; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/ClickEvent.cs: -------------------------------------------------------------------------------- 1 | using EventWebhook.Converters; 2 | using Newtonsoft.Json; 3 | using System; 4 | 5 | namespace EventWebhook.Models 6 | { 7 | public class ClickEvent : OpenEvent 8 | { 9 | [JsonConverter(typeof(UriConverter))] 10 | public Uri Url { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/DeferredEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class DeferredEvent : DeliveredEvent 4 | { 5 | public int Attempt { get; set; } 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/DeliveredEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class DeliveredEvent : Event 4 | { 5 | public string Response { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/DroppedEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class DroppedEvent : Event 4 | { 5 | public string Reason { get; set; } 6 | public string Status { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/Event.cs: -------------------------------------------------------------------------------- 1 | using EventWebhook.Converters; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Converters; 4 | using Newtonsoft.Json.Linq; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace EventWebhook.Models 9 | { 10 | public class Event 11 | { 12 | public string Email { get; set; } 13 | 14 | [JsonConverter(typeof(UnixDateTimeConverter))] 15 | public DateTime Timestamp { get; set; } 16 | 17 | [JsonProperty("smtp-id")] 18 | public string SmtpId { get; set; } 19 | 20 | [JsonProperty("event")] 21 | [JsonConverter(typeof(StringEnumConverter))] 22 | public EventType EventType { get; set; } 23 | 24 | [JsonConverter(typeof(CategoryConverter))] 25 | public Category Category { get; set; } 26 | 27 | [JsonProperty("sg_event_id")] 28 | public string SendGridEventId { get; set; } 29 | 30 | [JsonProperty("sg_message_id")] 31 | public string SendGridMessageId { get; set; } 32 | 33 | public string TLS { get; set; } 34 | 35 | [JsonExtensionData] 36 | public IDictionary UniqueArgs { get; set; } 37 | 38 | [JsonProperty("marketing_campaign_id")] 39 | public string MarketingCampainId { get; set; } 40 | 41 | [JsonProperty("marketing_campaign_name")] 42 | public string MarketingCampainName { get; set; } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/EventType.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace EventWebhook.Models 4 | { 5 | public enum EventType 6 | { 7 | Processed, 8 | Deferred, 9 | Delivered, 10 | Open, 11 | Click, 12 | Bounce, 13 | Dropped, 14 | SpamReport, 15 | Unsubscribe, 16 | [EnumMember(Value = "group_unsubscribe")] 17 | GroupUnsubscribe, 18 | [EnumMember(Value = "group_resubscribe")] 19 | GroupResubscribe 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/GroupResubscribeEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class GroupResubscribeEvent : GroupUnsubscribeEvent { } 4 | } 5 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/GroupUnsubscribeEvent.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace EventWebhook.Models 4 | { 5 | public class GroupUnsubscribeEvent : ClickEvent 6 | { 7 | [JsonProperty("asm_group_id")] 8 | public int AsmGroupId { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/OpenEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class OpenEvent : Event 4 | { 5 | public string UserAgent { get; set; } 6 | 7 | public string IP { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/Pool.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class Pool 4 | { 5 | public string Name { get; set; } 6 | public int Id { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/ProcessedEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class ProcessedEvent : Event 4 | { 5 | public Pool Pool { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/SpamReportEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class SpamReportEvent : Event { } 4 | } 5 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Models/UnsubscribeEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventWebhook.Models 2 | { 3 | public class UnsubscribeEvent : Event { } 4 | } 5 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Parser/EventConverter.cs: -------------------------------------------------------------------------------- 1 | using EventWebhook.Models; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Linq; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace EventWebhook.Parser 8 | { 9 | public class EventConverter : JsonConverter 10 | { 11 | private static readonly Dictionary> eventConverters = 12 | new Dictionary>() 13 | { 14 | { EventType.Bounce, (json) => JsonConvert.DeserializeObject(json) }, 15 | { EventType.Click, (json) => JsonConvert.DeserializeObject(json) }, 16 | { EventType.Deferred, (json) => JsonConvert.DeserializeObject(json) }, 17 | { EventType.Delivered, (json) => JsonConvert.DeserializeObject(json) }, 18 | { EventType.Dropped, (json) => JsonConvert.DeserializeObject(json) }, 19 | { EventType.GroupResubscribe, (json) => JsonConvert.DeserializeObject(json) }, 20 | { EventType.GroupUnsubscribe, (json) => JsonConvert.DeserializeObject(json) }, 21 | { EventType.Open, (json) => JsonConvert.DeserializeObject(json) }, 22 | { EventType.Processed, (json) => JsonConvert.DeserializeObject(json) }, 23 | { EventType.SpamReport, (json) => JsonConvert.DeserializeObject(json) }, 24 | { EventType.Unsubscribe, (json) => JsonConvert.DeserializeObject(json) }, 25 | }; 26 | 27 | private static Event DeserializeEvent(EventType type, string json) 28 | { 29 | if (!eventConverters.ContainsKey(type)) 30 | { 31 | throw new ArgumentOutOfRangeException($"Unknown event type: {type.ToString()}"); 32 | } 33 | 34 | return eventConverters.GetValueOrDefault(type)(json); 35 | } 36 | 37 | public override bool CanConvert(Type objectType) => typeof(Event) == objectType; 38 | 39 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 40 | { 41 | var jsonObject = JObject.Load(reader); 42 | 43 | jsonObject.TryGetValue("event", StringComparison.OrdinalIgnoreCase, out JToken eventTypeJsonProperty); 44 | 45 | var eventType = (EventType)eventTypeJsonProperty.ToObject(typeof(EventType)); 46 | 47 | var webhookEvent = DeserializeEvent(eventType, jsonObject.ToString()); 48 | 49 | return webhookEvent; 50 | } 51 | 52 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 53 | { 54 | throw new NotImplementedException(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Parser/EventParser.cs: -------------------------------------------------------------------------------- 1 | using EventWebhook.Models; 2 | using Newtonsoft.Json; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace EventWebhook.Parser 9 | { 10 | public class EventParser 11 | { 12 | public static async Task> ParseAsync(string json) 13 | { 14 | using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) 15 | { 16 | return await ParseAsync(stream); 17 | } 18 | } 19 | 20 | public static async Task> ParseAsync(Stream stream) 21 | { 22 | var reader = new StreamReader(stream); 23 | 24 | var json = await reader.ReadToEndAsync(); 25 | 26 | return JsonConvert.DeserializeObject>(json, new EventConverter()); 27 | } 28 | 29 | public static IEnumerable Parse(string json) 30 | { 31 | using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) 32 | { 33 | return Parse(stream); 34 | } 35 | } 36 | 37 | public static IEnumerable Parse(Stream stream) 38 | { 39 | var reader = new StreamReader(stream); 40 | 41 | var json = reader.ReadToEnd(); 42 | 43 | return JsonConvert.DeserializeObject>(json, new EventConverter()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace EventWebhook 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace EventWebhook 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 29 | } 30 | 31 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 32 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 33 | { 34 | if (env.IsDevelopment()) 35 | { 36 | app.UseDeveloperExceptionPage(); 37 | } 38 | else 39 | { 40 | app.UseHsts(); 41 | } 42 | 43 | app.UseHttpsRedirection(); 44 | app.UseMvc(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/Views/EventWebhook/Index.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | ViewData["Title"] = "Index"; 4 | } 5 | 6 |

You have successfully launched the server!

7 |

8 | Check out the documentation on how to use this webhook to utilize the SendGrid Event webhook. 9 |

10 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Src/EventWebhook/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /examples/eventwebhook/consumer/Tests/EventWebhook.Tests/EventWebhook.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Always 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/geo/geo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve email statistics by country and state/province. 12 | // GET /geo/stats 13 | 14 | string queryParams = @"{ 15 | 'aggregated_by': 'day', 16 | 'country': 'US', 17 | 'end_date': '2016-04-01', 18 | 'limit': 1, 19 | 'offset': 1, 20 | 'start_date': '2016-01-01' 21 | }"; 22 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "geo/stats", queryParams: queryParams); 23 | Console.WriteLine(response.StatusCode); 24 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 25 | Console.WriteLine(response.Headers.ToString()); 26 | Console.ReadLine(); 27 | 28 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/.dockerignore: -------------------------------------------------------------------------------- 1 | # directories 2 | **/bin/ 3 | **/obj/ 4 | **/out/ 5 | 6 | # files 7 | Dockerfile* 8 | **/*.trx 9 | **/*.md 10 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | "program": "${workspaceFolder}/src/inbound/bin/Debug/netcoreapp2.1/inbound.dll", 13 | "args": [], 14 | "cwd": "${workspaceFolder}/src/inbound", 15 | "stopAtEntry": false, 16 | "internalConsoleOptions": "openOnSessionStart", 17 | "launchBrowser": { 18 | "enabled": true, 19 | "args": "${auto-detect-url}", 20 | "windows": { 21 | "command": "cmd.exe", 22 | "args": "/C start ${auto-detect-url}" 23 | }, 24 | "osx": { 25 | "command": "open" 26 | }, 27 | "linux": { 28 | "command": "xdg-open" 29 | } 30 | }, 31 | "env": { 32 | "ASPNETCORE_ENVIRONMENT": "Development" 33 | }, 34 | "sourceFileMap": { 35 | "/Views": "${workspaceFolder}/Views" 36 | } 37 | }, 38 | { 39 | "name": ".NET Core Attach", 40 | "type": "coreclr", 41 | "request": "attach", 42 | "processId": "${command:pickProcess}" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/src/inbound/inbound.csproj" 11 | ], 12 | "problemMatcher": "$msCompile" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:2.1-sdk AS build 2 | WORKDIR /App 3 | 4 | # copy csproj and restore as distinct layers 5 | COPY *.sln . 6 | COPY Src/Inbound/*.csproj ./Src/Inbound/ 7 | COPY Tests/Inbound.Tests/*.csproj ./Tests/Inbound.Tests/ 8 | RUN dotnet restore 9 | 10 | # copy everything else and build app 11 | COPY Src/Inbound/. ./Src/Inbound/ 12 | WORKDIR /App/Src/Inbound 13 | RUN dotnet publish -c Release -o Out 14 | 15 | FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime 16 | WORKDIR /App 17 | COPY --from=build /App/Src/Inbound/Out ./ 18 | 19 | RUN echo "ASPNETCORE_URLS=http://0.0.0.0:\$PORT\nDOTNET_RUNNING_IN_CONTAINER=true" > /App/SetupHerokuEnv.sh && chmod +x /App/SetupHerokuEnv.sh 20 | 21 | CMD /bin/bash -c "source /App/SetupHerokuEnv.sh && dotnet Inbound.dll" 22 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Controllers/InboundController.cs: -------------------------------------------------------------------------------- 1 | using Inbound.Parsers; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Inbound.Controllers 8 | { 9 | [Route("/")] 10 | [ApiController] 11 | public class InboundController : Controller 12 | { 13 | [HttpGet] 14 | public IActionResult Index() 15 | { 16 | return View(); 17 | } 18 | 19 | // Process POST from Inbound Parse and print received data. 20 | [HttpPost] 21 | [Route("inbound")] 22 | public IActionResult InboundParse() 23 | { 24 | InboundWebhookParser _inboundParser = new InboundWebhookParser(Request.Body); 25 | 26 | var inboundEmail = _inboundParser.Parse(); 27 | 28 | return Ok(); 29 | } 30 | 31 | private void Log(IDictionary keyValues) 32 | { 33 | if(keyValues == null) 34 | { 35 | return; 36 | } 37 | Console.WriteLine(JsonConvert.SerializeObject(keyValues)); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Inbound.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Models/InboundEmailAddress.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Inbound.Models 4 | { 5 | /// 6 | /// The address for Email recipient, including the name and email address. 7 | /// 8 | public class InboundEmailAddress 9 | { 10 | /// 11 | /// Gets or sets the email. 12 | /// 13 | /// 14 | /// The email. 15 | /// 16 | [JsonProperty("email", NullValueHandling = NullValueHandling.Ignore)] 17 | public string Email { get; set; } 18 | 19 | /// 20 | /// Gets or sets the name. 21 | /// 22 | /// 23 | /// The name. 24 | /// 25 | [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] 26 | public string Name { get; set; } 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | /// The email. 32 | /// The name. 33 | public InboundEmailAddress(string email, string name) 34 | { 35 | Email = email; 36 | Name = name; 37 | } 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Models/InboundEmailAttachment.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | 4 | namespace Inbound.Models 5 | { 6 | /// 7 | /// Strongly typed representation of the information sudmited by SendGrid in a 'inbound parse' webhook. 8 | /// 9 | public class InboundEmailAttachment 10 | { 11 | /// 12 | /// Gets or sets the identifier. 13 | /// 14 | /// 15 | /// The identifier. 16 | /// 17 | public string Id { get; set; } 18 | 19 | /// 20 | /// Gets or sets the content-type. Defaults to text/plain if unspecified. 21 | /// 22 | /// 23 | /// The content-type. 24 | /// 25 | [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] 26 | public string ContentType { get; set; } 27 | 28 | /// 29 | /// Gets or sets the data. 30 | /// 31 | /// 32 | /// The data. 33 | /// 34 | public Stream Data { get; set; } 35 | 36 | /// 37 | /// Gets or sets the file name. 38 | /// 39 | /// 40 | /// The name of the file. 41 | /// 42 | [JsonProperty("filename", NullValueHandling = NullValueHandling.Ignore)] 43 | public string FileName { get; set; } 44 | 45 | /// 46 | /// Gets or sets the name. 47 | /// 48 | /// 49 | /// The name. 50 | /// 51 | [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] 52 | public string Name { get; set; } 53 | 54 | /// 55 | /// Gets or sets the content identifier. 56 | /// 57 | /// 58 | /// The content identifier. 59 | /// 60 | [JsonProperty("content-id", NullValueHandling = NullValueHandling.Ignore)] 61 | public string ContentId { get; set; } 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Models/InboundEmailEnvelope.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Inbound.Models 4 | { 5 | /// 6 | /// The SMTP envelope. 7 | /// 8 | public class InboundEmailEnvelope 9 | { 10 | /// 11 | /// Gets or sets to, which is a single-element array containing the address that we received the email to. 12 | /// 13 | /// 14 | /// To. 15 | /// 16 | [JsonProperty("to", NullValueHandling = NullValueHandling.Ignore)] 17 | public string[] To { get; set; } 18 | 19 | /// 20 | /// Gets or sets from, which is the return path for the message. 21 | /// 22 | /// 23 | /// From. 24 | /// 25 | [JsonProperty("from", NullValueHandling = NullValueHandling.Ignore)] 26 | public string From { get; set; } 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Inbound 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace Inbound 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 29 | } 30 | 31 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 32 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 33 | { 34 | if (env.IsDevelopment()) 35 | { 36 | app.UseDeveloperExceptionPage(); 37 | } 38 | else 39 | { 40 | app.UseHsts(); 41 | } 42 | 43 | app.UseHttpsRedirection(); 44 | app.UseMvc(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Util/Extensions.cs: -------------------------------------------------------------------------------- 1 | using HttpMultipartParser; 2 | 3 | namespace Inbound.Util 4 | { 5 | public static class Extensions 6 | { 7 | /// 8 | /// Returns the value of a parameter or the default value if it doesn't exist. 9 | /// 10 | /// The parser. 11 | /// The name of the parameter. 12 | /// The default value. 13 | /// The value of the parameter. 14 | public static string GetParameterValue(this MultipartFormDataParser parser, string name, string defaultValue) 15 | { 16 | return parser.HasParameter(name) ? parser.GetParameterValue(name) : defaultValue; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/Views/Inbound/Index.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | SendGrid Incoming Parse 4 | 5 | 6 |

You have successfully launched the server!

7 | 8 | Check out the documentation on how to use this software to utilize the SendGrid Inbound Parse webhook. 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Src/Inbound/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Tests/Inbound.Tests/Inbound.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.dll 29 | 30 | 31 | 32 | 33 | 34 | Always 35 | 36 | 37 | Always 38 | 39 | 40 | Always 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Tests/Inbound.Tests/IntegrationTests/InboundEndpointsTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Testing; 2 | using Shouldly; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | using Xunit; 8 | 9 | namespace Inbound.Tests.IntegrationTests 10 | { 11 | public class InboundEndpointsTests : IClassFixture> 12 | { 13 | private readonly WebApplicationFactory applicationFactory; 14 | 15 | public InboundEndpointsTests(WebApplicationFactory factory) 16 | => applicationFactory = factory; 17 | 18 | [Fact] 19 | public async Task Get_IndexPageReturnsSuccessAndCorrectContentType() 20 | { 21 | const string URL = "/"; 22 | 23 | var client = applicationFactory.CreateClient(); 24 | var response = await client.GetAsync(URL); 25 | response.EnsureSuccessStatusCode(); 26 | response.Content.Headers.ContentType.MediaType.ShouldBe("text/html"); 27 | } 28 | 29 | [Fact] 30 | public async Task Get_InboundEndpointReturnsNotFound() 31 | { 32 | const string URL = "/inbound"; 33 | var client = applicationFactory.CreateClient(); 34 | var response = await client.GetAsync(URL); 35 | response.StatusCode.ShouldBe(HttpStatusCode.NotFound); 36 | } 37 | 38 | [Fact] 39 | public async Task Post_InboundEndpointWithDefaultPayload() 40 | { 41 | const string URL = "/inbound"; 42 | var data = File.ReadAllTextAsync("sample_data/default_data.txt").Result; 43 | 44 | var content = new StringContent(data); 45 | content.Headers.Clear(); 46 | content.Headers.Add("Content-Type", "multipart/form-data; boundary=xYzZY"); 47 | 48 | var client = applicationFactory.CreateClient(); 49 | var response = await client.PostAsync(URL, content); 50 | response.EnsureSuccessStatusCode(); 51 | } 52 | 53 | [Fact] 54 | public async Task Post_InboundEndpointWithRawPayloadWithAttachments() 55 | { 56 | const string URL = "/inbound"; 57 | var data = File.ReadAllTextAsync("sample_data/raw_data_with_attachments.txt").Result; 58 | 59 | var content = new StringContent(data); 60 | content.Headers.Clear(); 61 | content.Headers.Add("Content-Type", "multipart/form-data; boundary=xYzZY"); 62 | 63 | var client = applicationFactory.CreateClient(); 64 | var response = await client.PostAsync(URL, content); 65 | response.EnsureSuccessStatusCode(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/inbound-webhook-handler/Tests/Inbound.Tests/sample_data/default_data.txt: -------------------------------------------------------------------------------- 1 | --xYzZY 2 | Content-Disposition: form-data; name="headers" 3 | 4 | MIME-Version: 1.0 5 | Received: by 0.0.0.0 with HTTP; Wed, 10 Aug 2016 18:10:13 -0700 (PDT) 6 | From: Example User 7 | Date: Wed, 10 Aug 2016 18:10:13 -0700 8 | Subject: Inbound Parse Test Data 9 | To: inbound@inbound.example.com 10 | Content-Type: multipart/alternative; boundary=001a113df448cad2d00539c16e89 11 | 12 | --xYzZY 13 | Content-Disposition: form-data; name="dkim" 14 | 15 | {@sendgrid.com : pass} 16 | --xYzZY 17 | Content-Disposition: form-data; name="to" 18 | 19 | inbound@inbound.example.com 20 | --xYzZY 21 | Content-Disposition: form-data; name="html" 22 | 23 | Hello SendGrid! 24 | 25 | --xYzZY 26 | Content-Disposition: form-data; name="from" 27 | 28 | Example User 29 | --xYzZY 30 | Content-Disposition: form-data; name="text" 31 | 32 | Hello SendGrid! 33 | 34 | --xYzZY 35 | Content-Disposition: form-data; name="sender_ip" 36 | 37 | 0.0.0.0 38 | --xYzZY 39 | Content-Disposition: form-data; name="envelope" 40 | 41 | {"to":["inbound@inbound.example.com"],"from":"test@example.com"} 42 | --xYzZY 43 | Content-Disposition: form-data; name="attachments" 44 | 45 | 0 46 | --xYzZY 47 | Content-Disposition: form-data; name="subject" 48 | 49 | Testing non-raw 50 | --xYzZY 51 | Content-Disposition: form-data; name="charsets" 52 | 53 | {"to":"UTF-8","html":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"UTF-8"} 54 | --xYzZY 55 | Content-Disposition: form-data; name="SPF" 56 | 57 | pass 58 | --xYzZY-- -------------------------------------------------------------------------------- /examples/mailboxproviders/mailboxproviders.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve email statistics by mailbox provider. 12 | // GET /mailbox_providers/stats 13 | 14 | string queryParams = @"{ 15 | 'aggregated_by': 'day', 16 | 'end_date': '2016-04-01', 17 | 'limit': 1, 18 | 'mailbox_providers': 'test_string', 19 | 'offset': 1, 20 | 'start_date': '2016-01-01' 21 | }"; 22 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "mailbox_providers/stats", queryParams: queryParams); 23 | Console.WriteLine(response.StatusCode); 24 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 25 | Console.WriteLine(response.Headers.ToString()); 26 | Console.ReadLine(); 27 | 28 | -------------------------------------------------------------------------------- /examples/partnersettings/partnersettings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Returns a list of all partner settings. 12 | // GET /partner_settings 13 | 14 | string queryParams = @"{ 15 | 'limit': 1, 16 | 'offset': 1 17 | }"; 18 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "partner_settings", queryParams: queryParams); 19 | Console.WriteLine(response.StatusCode); 20 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 21 | Console.WriteLine(response.Headers.ToString()); 22 | Console.ReadLine(); 23 | 24 | //////////////////////////////////////////////////////// 25 | // Updates New Relic partner settings. 26 | // PATCH /partner_settings/new_relic 27 | 28 | string data = @"{ 29 | 'enable_subuser_statistics': true, 30 | 'enabled': true, 31 | 'license_key': '' 32 | }"; 33 | Object json = JsonConvert.DeserializeObject(data); 34 | data = json.ToString(); 35 | var response = await client.RequestAsync(method: SendGridClient.Method.PATCH, urlPath: "partner_settings/new_relic", requestBody: data); 36 | Console.WriteLine(response.StatusCode); 37 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 38 | Console.WriteLine(response.Headers.ToString()); 39 | Console.ReadLine(); 40 | 41 | //////////////////////////////////////////////////////// 42 | // Returns all New Relic partner settings. 43 | // GET /partner_settings/new_relic 44 | 45 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "partner_settings/new_relic"); 46 | Console.WriteLine(response.StatusCode); 47 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 48 | Console.WriteLine(response.Headers.ToString()); 49 | Console.ReadLine(); 50 | 51 | -------------------------------------------------------------------------------- /examples/scopes/scopes.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve a list of scopes for which this user has access. 12 | // GET /scopes 13 | 14 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "scopes"); 15 | Console.WriteLine(response.StatusCode); 16 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 17 | Console.WriteLine(response.Headers.ToString()); 18 | Console.ReadLine(); 19 | 20 | -------------------------------------------------------------------------------- /examples/stats/stats.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid; 3 | using SendGrid.Helpers.Mail; // If you are using the Mail Helper 4 | using System; 5 | 6 | 7 | var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY"); 8 | var client = new SendGridClient(apiKey); 9 | 10 | //////////////////////////////////////////////////////// 11 | // Retrieve global email statistics 12 | // GET /stats 13 | 14 | string queryParams = @"{ 15 | 'aggregated_by': 'day', 16 | 'end_date': '2016-04-01', 17 | 'limit': 1, 18 | 'offset': 1, 19 | 'start_date': '2016-01-01' 20 | }"; 21 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "stats", queryParams: queryParams); 22 | Console.WriteLine(response.StatusCode); 23 | Console.WriteLine(response.Body.ReadAsStringAsync().Result); 24 | Console.WriteLine(response.Headers.ToString()); 25 | Console.ReadLine(); 26 | 27 | -------------------------------------------------------------------------------- /src/SendGrid.Extensions.DependencyInjection/InjectableSendGridClient.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Microsoft.Extensions.Options; 7 | using System.Net.Http; 8 | 9 | namespace SendGrid.Extensions.DependencyInjection 10 | { 11 | /// 12 | /// A wrapped SendGridClient with single constructor to inject an whose lifetime is managed externally, e.g. by an DI container. 13 | /// 14 | internal class InjectableSendGridClient : BaseClient 15 | { 16 | public InjectableSendGridClient(HttpClient httpClient, IOptions options) 17 | : base(httpClient, options.Value) 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/SendGrid.Extensions.DependencyInjection/SendGrid.Extensions.DependencyInjection.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1.0.1 5 | netstandard2.0 6 | ../../tools/sendgrid-csharp.snk 7 | true 8 | true 9 | ..\SendGrid\SendGrid.ruleset 10 | 11 | 12 | 13 | Elmer Thomas;Twilio DX Team 14 | Twilio SendGrid 15 | Twilio SendGrid 16 | MIT 17 | https://sendgrid.com/ 18 | https://github.com/sendgrid/sendgrid-csharp.git 19 | git 20 | https://sendgrid.com/wp-content/themes/sgdotcom/pages/resource/brand//2016/SendGrid-Logomark.png 21 | integrate SendGrid with HttpClientFactory and Microsoft.Extensions.DependencyInjection 22 | Please see: https://github.com/sendgrid/sendgrid-csharp/releases 23 | Twilio;SendGrid;Email;Mail;Microsoft;Azure;Transactional;.NET Core 24 | Twilio SendGrid, Inc. 2019 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/SendGrid.Extensions.DependencyInjection/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.DependencyInjection.Extensions; 8 | using System; 9 | 10 | namespace SendGrid.Extensions.DependencyInjection 11 | { 12 | /// 13 | /// extension methods for . 14 | /// 15 | public static class ServiceCollectionExtensions 16 | { 17 | /// 18 | /// Adds the with and related services to the . 19 | /// 20 | /// The . 21 | /// A delegate that is used to configure a . 22 | /// An that can be used to configure the client. 23 | public static IHttpClientBuilder AddSendGrid(this IServiceCollection services, Action configureOptions) 24 | { 25 | services.AddOptions().Configure((options, resolver) => configureOptions(resolver, options)) 26 | .PostConfigure(options => 27 | { 28 | // validation 29 | if (string.IsNullOrWhiteSpace(options.ApiKey)) 30 | { 31 | throw new ArgumentNullException(nameof(options.ApiKey)); 32 | } 33 | }); 34 | 35 | services.TryAddTransient(resolver => resolver.GetRequiredService()); 36 | 37 | return services.AddHttpClient(); 38 | } 39 | 40 | /// 41 | /// Adds the with and related services to the . 42 | /// 43 | /// The . 44 | /// A delegate that is used to configure a . 45 | /// An that can be used to configure the client. 46 | public static IHttpClientBuilder AddSendGrid(this IServiceCollection services, Action configureOptions) 47 | { 48 | return services.AddSendGrid((_, options) => configureOptions(options)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/SendGrid/BaseClientOptions.cs: -------------------------------------------------------------------------------- 1 | using SendGrid.Helpers.Reliability; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Net.Http.Headers; 5 | 6 | namespace SendGrid 7 | { 8 | /// 9 | /// Defines the options to use with the client. 10 | /// 11 | public class BaseClientOptions 12 | { 13 | private ReliabilitySettings reliabilitySettings = new ReliabilitySettings(); 14 | 15 | /// 16 | /// The reliability settings to use on HTTP Requests. 17 | /// 18 | public ReliabilitySettings ReliabilitySettings 19 | { 20 | get => reliabilitySettings; 21 | set => reliabilitySettings = value ?? throw new ArgumentNullException(nameof(reliabilitySettings)); 22 | } 23 | 24 | /// 25 | /// The request headers to use on HTTP Requests. 26 | /// 27 | public Dictionary RequestHeaders { get; set; } = new Dictionary(); 28 | 29 | /// 30 | /// The base URL. 31 | /// 32 | public string Host { get; set; } 33 | 34 | /// 35 | /// The API version (defaults to "v3"). 36 | /// 37 | public string Version { get; set; } = "v3"; 38 | 39 | /// 40 | /// The path to the API endpoint. 41 | /// 42 | public string UrlPath { get; set; } 43 | 44 | /// 45 | /// The Auth header value. 46 | /// 47 | public AuthenticationHeaderValue Auth { get; set; } 48 | 49 | /// 50 | /// Gets or sets a value indicating whether HTTP error responses should be raised as exceptions. Default is false. 51 | /// 52 | public bool HttpErrorAsException { get; set; } = false; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/BadRequestException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 400 7 | /// 8 | public class BadRequestException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public BadRequestException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public BadRequestException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public BadRequestException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/ForbiddenException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 403 7 | /// 8 | public class ForbiddenException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public ForbiddenException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public ForbiddenException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public ForbiddenException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/MethodNotAllowedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 405 7 | /// 8 | public class MethodNotAllowedException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public MethodNotAllowedException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public MethodNotAllowedException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public MethodNotAllowedException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/NotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 404 7 | /// 8 | public class NotFoundException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public NotFoundException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public NotFoundException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public NotFoundException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/PayloadTooLargeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 413 7 | /// 8 | public class PayloadTooLargeException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public PayloadTooLargeException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public PayloadTooLargeException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public PayloadTooLargeException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/RequestErrorException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 4xx. Being x any number 7 | /// 8 | public class RequestErrorException : Exception 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public RequestErrorException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public RequestErrorException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public RequestErrorException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/SendGridErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Helpers.Errors.Model 2 | { 3 | /// 4 | /// Base class for the json error response 5 | /// 6 | public class SendGridErrorResponse 7 | { 8 | /// 9 | /// Gets or sets the error Status Code 10 | /// 11 | public int ErrorHttpStatusCode { get; set; } 12 | 13 | /// 14 | /// Gets or sets the error Reason Phrase 15 | /// 16 | public string ErrorReasonPhrase { get; set; } 17 | 18 | /// 19 | /// Gets or sets the SendGrid error message 20 | /// 21 | public string SendGridErrorMessage { get; set; } 22 | 23 | /// 24 | /// Gets or sets the field that has the error 25 | /// 26 | public string FieldWithError { get; set; } 27 | 28 | /// 29 | /// Gets or sets the error default help 30 | /// 31 | public string HelpLink { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/SendGridInternalException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 5xx. Being x any number 7 | /// 8 | public class SendGridInternalException : Exception 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public SendGridInternalException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public SendGridInternalException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public SendGridInternalException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/ServerUnavailableException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 500 7 | /// 8 | public class ServerUnavailableException : SendGridInternalException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public ServerUnavailableException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public ServerUnavailableException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public ServerUnavailableException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/ServiceNotAvailableException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 503 7 | /// 8 | public class ServiceNotAvailableException : SendGridInternalException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public ServiceNotAvailableException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public ServiceNotAvailableException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public ServiceNotAvailableException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/TooManyRequestsException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 429 7 | /// 8 | public class TooManyRequestsException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public TooManyRequestsException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public TooManyRequestsException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public TooManyRequestsException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/UnauthorizedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 401 7 | /// 8 | public class UnauthorizedException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public UnauthorizedException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public UnauthorizedException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public UnauthorizedException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Errors/Model/UnsupportedMediaTypeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Errors.Model 4 | { 5 | /// 6 | /// Represents errors with status code 415 7 | /// 8 | public class UnsupportedMediaTypeException : RequestErrorException 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public UnsupportedMediaTypeException() 14 | : base() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class with a specified error. 20 | /// 21 | /// The error message that explains the reason for the exception. 22 | public UnsupportedMediaTypeException(string message) 23 | : base(message) 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class with a specified error and a reference to the inner exception that is the cause of this exception. 29 | /// 30 | /// The error message that explains the reason for the exception. 31 | /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. 32 | public UnsupportedMediaTypeException(string message, Exception innerException) 33 | : base(message, innerException) 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/EventWebhook/RequestValidator.cs: -------------------------------------------------------------------------------- 1 | using EllipticCurve; 2 | 3 | namespace SendGrid.Helpers.EventWebhook 4 | { 5 | /// 6 | /// This class allows you to use the Event Webhook feature. Read the docs for 7 | /// more details: https://sendgrid.com/docs/for-developers/tracking-events/event 8 | /// 9 | public class RequestValidator 10 | { 11 | /// 12 | /// Signature verification HTTP header name for the signature being sent. 13 | /// 14 | public const string SIGNATURE_HEADER = "X-Twilio-Email-Event-Webhook-Signature"; 15 | 16 | /// 17 | /// Timestamp HTTP header name for timestamp. 18 | /// 19 | public const string TIMESTAMP_HEADER = "X-Twilio-Email-Event-Webhook-Timestamp"; 20 | 21 | /// 22 | /// Convert the public key string to a . 23 | /// 24 | /// verification key under Mail Settings 25 | /// public key using the ECDSA algorithm 26 | public PublicKey ConvertPublicKeyToECDSA(string publicKey) 27 | { 28 | return PublicKey.fromPem(publicKey); 29 | } 30 | 31 | /// 32 | /// Verify signed event webhook requests. 33 | /// 34 | /// elliptic curve public key 35 | /// event payload in the request body 36 | /// value obtained from the 'X-Twilio-Email-Event-Webhook-Signature' header 37 | /// value obtained from the 'X-Twilio-Email-Event-Webhook-Timestamp' header 38 | /// true or false if signature is valid 39 | public bool VerifySignature(PublicKey publicKey, string payload, string signature, string timestamp) 40 | { 41 | var timestampedPayload = timestamp + payload; 42 | var decodedSignature = Signature.fromBase64(signature); 43 | 44 | return Ecdsa.verify(timestampedPayload, decodedSignature, publicKey); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/ASM.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | using System.Collections.Generic; 8 | 9 | namespace SendGrid.Helpers.Mail 10 | { 11 | /// 12 | /// An object allowing you to specify how to handle unsubscribes. 13 | /// 14 | [JsonObject(IsReference = false)] 15 | public class ASM 16 | { 17 | /// 18 | /// Gets or sets the unsubscribe group to associate with this email. 19 | /// 20 | [JsonProperty(PropertyName = "group_id")] 21 | public int GroupId { get; set; } 22 | 23 | /// 24 | /// Gets or sets an array containing the unsubscribe groups that you would like to be displayed on the unsubscribe preferences page. 25 | /// https://sendgrid.com/docs/User_Guide/Suppressions/recipient_subscription_preferences.html. 26 | /// 27 | [JsonProperty(PropertyName = "groups_to_display", IsReference = false)] 28 | public List GroupsToDisplay { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/Attachment.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Gets or sets an array of objects in which you can specify any attachments you want to include. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class Attachment 15 | { 16 | /// 17 | /// Gets or sets the Base64 encoded content of the attachment. 18 | /// 19 | [JsonProperty(PropertyName = "content")] 20 | public string Content { get; set; } 21 | 22 | /// 23 | /// Gets or sets the mime type of the content you are attaching. For example, application/pdf or image/jpeg. 24 | /// 25 | [JsonProperty(PropertyName = "type")] 26 | public string Type { get; set; } 27 | 28 | /// 29 | /// Gets or sets the filename of the attachment. 30 | /// 31 | [JsonProperty(PropertyName = "filename")] 32 | public string Filename { get; set; } 33 | 34 | /// 35 | /// Gets or sets the content-disposition of the attachment specifying how you would like the attachment to be displayed. For example, "inline" results in the attached file being displayed automatically within the message while "attachment" results in the attached file requiring some action to be taken before it is displayed (e.g. opening or downloading the file). Defaults to "attachment". Can be either "attachment" or "inline". 36 | /// 37 | [JsonProperty(PropertyName = "disposition")] 38 | public string Disposition { get; set; } 39 | 40 | /// 41 | /// Gets or sets a unique id that you specify for the attachment. This is used when the disposition is set to "inline" and the attachment is an image, allowing the file to be displayed within the body of your email. Ex: . 42 | /// 43 | [JsonProperty(PropertyName = "content_id")] 44 | public string ContentId { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/BCCSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Gets or sets the address specified in the mail_settings.bcc object will receive a blind carbon copy (BCC) of the very first personalization defined in the personalizations array. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class BCCSettings 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool? Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets the email address that you would like to receive the BCC. 24 | /// 25 | [JsonProperty(PropertyName = "email")] 26 | public string Email { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/BypassBounceManagement.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to bypass the bounce list to ensure that the email is delivered to recipients. Spam report and unsubscribe lists will still be checked; addresses on these other lists will not receive the message. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class BypassBounceManagement 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool Enable { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/BypassListManagement.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to bypass all unsubscribe groups and suppressions to ensure that the email is delivered to every single recipient. This should only be used in emergencies when it is absolutely necessary that every recipient receives your email. Ex: outage emails, or forgot password emails. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class BypassListManagement 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool Enable { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/BypassSpamManagement.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to bypass the spam report list to ensure that the email is delivered to recipients. Bounce and unsubscribe lists will still be checked; addresses on these other lists will not receive the message. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class BypassSpamManagement 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool Enable { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/BypassUnsubscribeManagement.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to bypass the global unsubscribe list to ensure that the email is delivered to recipients. Bounce and spam report lists will still be checked; addresses on these other lists will not receive the message. This filter applies only to global unsubscribes and will not bypass group unsubscribes. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class BypassUnsubscribeManagement 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool Enable { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/ClickTracking.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to track whether a recipient clicked a link in your email. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class ClickTracking 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool? Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets if this setting should be included in the text/plain portion of your email. 24 | /// 25 | [JsonProperty(PropertyName = "enable_text")] 26 | public bool? EnableText { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/Content.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Specifies the content of your email. You can include multiple mime types of content, but you must specify at least one. To include more than one mime type, simply add another object to the array containing the type and value parameters. If included, text/plain and text/html must be the first indices of the array in this order. If you choose to include the text/plain or text/html mime types, they must be the first indices of the content array in the order text/plain, text/html.*Content is NOT mandatory if you using a transactional template and have defined the template_id in the Request. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class Content 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public Content() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// The mime type of the content you are including in your email. For example, text/plain or text/html. 27 | /// The actual content of the specified mime type that you are including in your email. 28 | public Content(string type, string value) 29 | { 30 | this.Type = type; 31 | this.Value = value; 32 | } 33 | 34 | /// 35 | /// Gets or sets the mime type of the content you are including in your email. For example, text/plain or text/html. 36 | /// 37 | [JsonProperty(PropertyName = "type")] 38 | public string Type { get; set; } 39 | 40 | /// 41 | /// Gets or sets the actual content of the specified mime type that you are including in your email. 42 | /// 43 | [JsonProperty(PropertyName = "value")] 44 | public string Value { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/FooterSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// The default footer that you would like appended to the bottom of every email. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class FooterSettings 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets the plain text content of your footer. 24 | /// 25 | [JsonProperty(PropertyName = "text")] 26 | public string Text { get; set; } 27 | 28 | /// 29 | /// Gets or sets the HTML content of your footer. 30 | /// 31 | [JsonProperty(PropertyName = "html")] 32 | public string Html { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/Ganalytics.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to enable tracking provided by Google Analytics. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class Ganalytics 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool? Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets the name of the referrer source (e.g. Google, SomeDomain.com, or Marketing Email). 24 | /// 25 | [JsonProperty(PropertyName = "utm_source")] 26 | public string UtmSource { get; set; } 27 | 28 | /// 29 | /// Gets or sets the name of the marketing medium (e.g. Email). 30 | /// 31 | [JsonProperty(PropertyName = "utm_medium")] 32 | public string UtmMedium { get; set; } 33 | 34 | /// 35 | /// Gets or sets the identification of any paid keywords. 36 | /// 37 | [JsonProperty(PropertyName = "utm_term")] 38 | public string UtmTerm { get; set; } 39 | 40 | /// 41 | /// Gets or sets the differentiation of your campaign from advertisements. 42 | /// 43 | [JsonProperty(PropertyName = "utm_content")] 44 | public string UtmContent { get; set; } 45 | 46 | /// 47 | /// Gets or sets the name of the campaign. 48 | /// 49 | [JsonProperty(PropertyName = "utm_campaign")] 50 | public string UtmCampaign { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/HtmlContent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail.Model 9 | { 10 | /// 11 | /// Helper class for plain html mime types. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class HtmlContent : Content 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// The actual content of the specified mime type that you are including in your email. 20 | public HtmlContent(string value) 21 | { 22 | this.Type = MimeType.Html; 23 | this.Value = value; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/JsonConverters.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | #if NET40 11 | using SendGrid.Helpers.Net40; 12 | #else 13 | using System.Reflection; 14 | #endif 15 | 16 | namespace SendGrid.Helpers.Mail 17 | { 18 | /// 19 | /// Removes duplicates when writing the JSON representation of the object. 20 | /// 21 | public class RemoveDuplicatesConverter : JsonConverter 22 | { 23 | /// 24 | /// Determines whether this instance can convert the specified object type. 25 | /// 26 | public override bool CanConvert(Type objectType) 27 | { 28 | return typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); 29 | } 30 | 31 | /// 32 | /// Writes the JSON representation of the object. 33 | /// 34 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 35 | { 36 | writer.WriteStartArray(); 37 | foreach (T item in ((IEnumerable)value).Distinct()) 38 | { 39 | serializer.Serialize(writer, item); 40 | } 41 | writer.WriteEndArray(); 42 | } 43 | 44 | /// 45 | /// Determines whether this instance can convert the specified object type. 46 | /// 47 | public override bool CanRead 48 | { 49 | get { return false; } 50 | } 51 | 52 | /// 53 | /// Reads the JSON representation of the object. 54 | /// 55 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 56 | { 57 | throw new NotImplementedException(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/OpenTracking.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to track whether the email was opened or not, but including a single pixel image in the body of the content. When the pixel is loaded, we can log that the email was opened. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class OpenTracking 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool? Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets the ability to specify a substitution tag that you can insert in the body of your email at a location that you desire. This tag will be replaced by the open tracking pixel. 24 | /// 25 | [JsonProperty(PropertyName = "substitution_tag")] 26 | public string SubstitutionTag { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/PlainTextContent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace SendGrid.Helpers.Mail.Model 7 | { 8 | /// 9 | /// Helper class for plain text mime types. 10 | /// 11 | public class PlainTextContent : Content 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The actual content of the specified mime type that you are including in your email. 17 | public PlainTextContent(string value) 18 | { 19 | this.Type = MimeType.Text; 20 | this.Value = value; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/SandboxMode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// This allows you to send a test email to ensure that your request body is valid and formatted correctly. For more information, please see our Classroom. 12 | /// https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/sandbox_mode.html. 13 | /// 14 | [JsonObject(IsReference = false)] 15 | public class SandboxMode 16 | { 17 | /// 18 | /// Gets or sets a value indicating whether this setting is enabled. 19 | /// 20 | [JsonProperty(PropertyName = "enable")] 21 | public bool? Enable { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/SpamCheck.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// This allows you to test the content of your email for spam. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class SpamCheck 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool? Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets the threshold used to determine if your content qualifies as spam on a scale from 1 to 10, with 10 being most strict, or most likely to be considered as spam. 24 | /// 25 | [JsonProperty(PropertyName = "threshold")] 26 | public int? Threshold { get; set; } 27 | 28 | /// 29 | /// Gets or sets an Inbound Parse URL that you would like a copy of your email along with the spam report to be sent to. The post_to_url parameter must start with http:// or https://. 30 | /// 31 | [JsonProperty(PropertyName = "post_to_url")] 32 | public string PostToUrl { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/SubscriptionTracking.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Allows you to insert a subscription management link at the bottom of the text and html bodies of your email. If you would like to specify the location of the link within your email, you may use the substitution_tag. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class SubscriptionTracking 15 | { 16 | /// 17 | /// Gets or sets a value indicating whether this setting is enabled. 18 | /// 19 | [JsonProperty(PropertyName = "enable")] 20 | public bool Enable { get; set; } 21 | 22 | /// 23 | /// Gets or sets the text to be appended to the email, with the subscription tracking link. You may control where the link is by using the tag (percent symbol) (percent symbol). 24 | /// 25 | [JsonProperty(PropertyName = "text")] 26 | public string Text { get; set; } 27 | 28 | /// 29 | /// Gets or sets the HTML to be appended to the email, with the subscription tracking link. You may control where the link is by using the tag (percent symbol) (percent symbol). 30 | /// 31 | [JsonProperty(PropertyName = "html")] 32 | public string Html { get; set; } 33 | 34 | /// 35 | /// Gets or sets a tag that will be replaced with the unsubscribe URL. for example: [unsubscribe_url]. If this parameter is used, it will override both the textand html parameters. The URL of the link will be placed at the substitution tag’s location, with no additional formatting. 36 | /// 37 | [JsonProperty(PropertyName = "substitution_tag")] 38 | public string SubstitutionTag { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/Model/TrackingSettings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using Newtonsoft.Json; 7 | 8 | namespace SendGrid.Helpers.Mail 9 | { 10 | /// 11 | /// Settings to determine how you would like to track the metrics of how your recipients interact with your email. 12 | /// 13 | [JsonObject(IsReference = false)] 14 | public class TrackingSettings 15 | { 16 | /// 17 | /// Gets or sets tracking whether a recipient clicked a link in your email. 18 | /// 19 | [JsonProperty(PropertyName = "click_tracking")] 20 | public ClickTracking ClickTracking { get; set; } 21 | 22 | /// 23 | /// Gets or sets tracking whether the email was opened or not, but including a single pixel image in the body of the content. When the pixel is loaded, we can log that the email was opened. 24 | /// 25 | [JsonProperty(PropertyName = "open_tracking")] 26 | public OpenTracking OpenTracking { get; set; } 27 | 28 | /// 29 | /// Gets or sets a subscription management link at the bottom of the text and html bodies of your email. If you would like to specify the location of the link within your email, you may use the substitution_tag. 30 | /// 31 | [JsonProperty(PropertyName = "subscription_tracking")] 32 | public SubscriptionTracking SubscriptionTracking { get; set; } 33 | 34 | /// 35 | /// Gets or sets tracking provided by Google Analytics. 36 | /// 37 | [JsonProperty(PropertyName = "ganalytics")] 38 | public Ganalytics Ganalytics { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Mail/README.md: -------------------------------------------------------------------------------- 1 | **This helper allows you to quickly and easily build a Mail object for sending email through the Twilio SendGrid v3 API.** 2 | 3 | # Quick Start 4 | 5 | Run the [Example Project](../../../../ExampleCoreProject) (make sure you have set your Environment variable to include your SENDGRID_API_KEY). 6 | 7 | Click on the Example project, then click the `Start` button on the menu. 8 | 9 | ## Usage 10 | 11 | - See the [example](../../../../ExampleCoreProject/Program.cs) for a complete working example. 12 | - [Documentation](https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html) 13 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/Net40/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SendGrid.Helpers.Net40 4 | { 5 | internal static class TypeExtensions 6 | { 7 | public static Type GetTypeInfo(this Type type) => type; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/SendGrid/Helpers/TaskUtilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace SendGrid.Helpers 6 | { 7 | internal static class TaskUtilities 8 | { 9 | public static Task Delay(TimeSpan delay, CancellationToken cancellationToken = default) 10 | { 11 | #if NET40 12 | return TaskEx.Delay(delay, cancellationToken); 13 | #else 14 | return Task.Delay(delay, cancellationToken); 15 | #endif 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/SendGrid/MimeType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | namespace SendGrid 7 | { 8 | /// 9 | /// Helper for the common Twilio SendGrid email mime types. 10 | /// 11 | public class MimeType 12 | { 13 | /// 14 | /// The mime type for HTML content. 15 | /// 16 | public static readonly string Html = "text/html"; 17 | 18 | /// 19 | /// The mime type for plain text content. 20 | /// 21 | public static readonly string Text = "text/plain"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/SendGrid/Permissions/ScopeOptions.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Permissions 2 | { 3 | /// 4 | /// Represents a set of possible scope options 5 | /// 6 | /// 7 | public enum ScopeOptions 8 | { 9 | /// 10 | /// All scopes. When filtering scopes no scopes will be exluded 11 | /// 12 | All, 13 | 14 | /// 15 | /// Read-only scopes. When fitlering scopes this will include only those that end with ".read" 16 | /// 17 | ReadOnly 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/SendGrid/Permissions/SendGridClientExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using Newtonsoft.Json; 4 | using Newtonsoft.Json.Linq; 5 | 6 | namespace SendGrid.Permissions 7 | { 8 | /// 9 | /// Utility extension methods that bridge the gap between the and the . 10 | /// 11 | public static class SendGridClientExtensions 12 | { 13 | /// 14 | /// Create a permissions builder instance that masks the emitted scopes to exclude any scopes not 15 | /// contained in the list of scopes already granted for the given API Key the was initialized with. 16 | /// 17 | /// The SendGrid client. 18 | /// A instance. 19 | public static async Task CreateMaskedPermissionsBuilderForClient(this ISendGridClient client) 20 | { 21 | var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "scopes"); 22 | var body = await response.DeserializeResponseBodyAsync(); 23 | var userScopesJArray = (body["scopes"] as JArray); 24 | var includedScopes = userScopesJArray.Values().ToArray(); 25 | var builder = new SendGridPermissionsBuilder(); 26 | builder.Exclude(scope => !includedScopes.Contains(scope)); 27 | return builder; 28 | } 29 | 30 | /// 31 | /// Create a new API key for the scopes contained in the . 32 | /// 33 | /// The SendGrid client. 34 | /// The permissions builder. 35 | /// The API key name. 36 | /// The from the SendGrid API call. 37 | public static async Task CreateApiKey(this ISendGridClient client, SendGridPermissionsBuilder permissions, string name) 38 | { 39 | var scopes = permissions.Build(); 40 | var payload = new 41 | { 42 | name, 43 | scopes 44 | }; 45 | var data = JsonConvert.SerializeObject(payload); 46 | var response = await client.RequestAsync(method: SendGridClient.Method.POST, urlPath: "api_keys", requestBody: data); 47 | return response; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/SendGrid/Permissions/SendGridPermission.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SendGrid.Permissions 6 | { 7 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 8 | public enum SendGridPermission 9 | 10 | { 11 | Admin, 12 | Alerts, 13 | ApiKeys, 14 | ASMGroups, 15 | Billing, 16 | Categories, 17 | Clients, 18 | Credentials, 19 | DomainAuthentication, 20 | IPs, 21 | Mail, 22 | MailSettings, 23 | MarketingCampaigns, 24 | Newsletter, 25 | PartnerSettings, 26 | ReverseDNS, 27 | ScheduledSends, 28 | Stats, 29 | Subusers, 30 | Suppressions, 31 | Teammates, 32 | Templates, 33 | Tracking, 34 | UserSettings, 35 | Webhook 36 | } 37 | #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 38 | } 39 | -------------------------------------------------------------------------------- /src/SendGrid/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Twilio SendGrid. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | using System.Runtime.InteropServices; 7 | 8 | // Setting ComVisible to false makes the types in this assembly not visible 9 | // to COM components. If you need to access a type in this assembly from 10 | // COM, set the ComVisible attribute to true on that type. 11 | [assembly: ComVisible(false)] 12 | 13 | // The following GUID is for the ID of the typelib if this project is exposed to COM 14 | [assembly: Guid("377c20e4-2297-488f-933b-fb635c56d8fc")] 15 | -------------------------------------------------------------------------------- /src/SendGrid/SendGridClientOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.Http.Headers; 4 | 5 | namespace SendGrid 6 | { 7 | /// 8 | /// Defines the options to use with the SendGrid client. 9 | /// 10 | public class SendGridClientOptions : BaseClientOptions 11 | { 12 | Dictionary REGION_HOST_MAP = new Dictionary 13 | { 14 | {"eu", "https://api.eu.sendgrid.com/"}, 15 | {"global", "https://api.sendgrid.com/"} 16 | }; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | public SendGridClientOptions() 22 | { 23 | Host = "https://api.sendgrid.com"; 24 | } 25 | 26 | private string apiKey; 27 | 28 | /// 29 | /// The Twilio SendGrid API key. 30 | /// 31 | public string ApiKey 32 | { 33 | get => apiKey; 34 | 35 | set 36 | { 37 | if (string.IsNullOrWhiteSpace(value)) 38 | { 39 | throw new ArgumentNullException(nameof(apiKey)); 40 | } 41 | 42 | apiKey = value; 43 | Auth = new AuthenticationHeaderValue("Bearer", apiKey); 44 | } 45 | } 46 | 47 | /// 48 | /// Sets the data residency for the SendGrid client. 49 | /// 50 | /// The desired data residency region ("global" or "eu"). 51 | /// Global is the default residency (or region) 52 | /// Global region means the message will be sent through https://api.sendgrid.com 53 | /// EU region means the message will be sent through https://api.eu.sendgrid.com 54 | /// The updated SendGridClientOptions instance. 55 | public SendGridClientOptions SetDataResidency(string region) 56 | { 57 | if (string.IsNullOrWhiteSpace(region)) 58 | { 59 | throw new ArgumentNullException(nameof(region)); 60 | } 61 | 62 | if (!REGION_HOST_MAP.ContainsKey(region)) 63 | { 64 | throw new InvalidOperationException("Region can only be 'global' or 'eu'."); 65 | } 66 | string result = REGION_HOST_MAP.ContainsKey(region) ? REGION_HOST_MAP[region] : "https://api.sendgrid.com"; 67 | Host = result; 68 | return this; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/SendGrid/TwilioEmailClient.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | 4 | namespace SendGrid 5 | { 6 | /// 7 | /// An HTTP client wrapper for interacting with the Twilio Email API. 8 | /// 9 | public class TwilioEmailClient : BaseClient 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// Web proxy. 15 | /// Your Twilio Email API key SID or Account SID. 16 | /// Your Twilio Email API key secret or Account Auth Token. 17 | /// Interface to the Twilio Email REST API. 18 | public TwilioEmailClient(IWebProxy webProxy, string username, string password) 19 | : base(webProxy, new TwilioEmailClientOptions(username, password)) 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// An optional http client which may me injected in order to facilitate testing. 27 | /// Your Twilio Email API key SID or Account SID. 28 | /// Your Twilio Email API key secret or Account Auth Token. 29 | /// Interface to the Twilio Email REST API. 30 | public TwilioEmailClient(HttpClient httpClient, string username, string password) 31 | : base(httpClient, new TwilioEmailClientOptions(username, password)) 32 | { 33 | } 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | /// Your Twilio Email API key SID or Account SID. 39 | /// Your Twilio Email API key secret or Account Auth Token. 40 | /// Interface to the Twilio Email REST API. 41 | public TwilioEmailClient(string username, string password) 42 | : base(new TwilioEmailClientOptions(username, password)) 43 | { 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/SendGrid/TwilioEmailClientOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http.Headers; 3 | 4 | namespace SendGrid 5 | { 6 | /// 7 | /// Defines the options to use with the Twilio Email client. 8 | /// 9 | public class TwilioEmailClientOptions : BaseClientOptions 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | public TwilioEmailClientOptions() 15 | { 16 | Host = "https://email.twilio.com"; 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// Your Twilio Email API key SID or Account SID. 22 | /// Your Twilio Email API key secret or Account Auth Token. 23 | /// 24 | public TwilioEmailClientOptions(string username, string password) 25 | : this() 26 | { 27 | if (string.IsNullOrWhiteSpace(username)) 28 | { 29 | throw new ArgumentNullException(nameof(username)); 30 | } 31 | 32 | if (string.IsNullOrWhiteSpace(password)) 33 | { 34 | throw new ArgumentNullException(nameof(password)); 35 | } 36 | 37 | var credentials = username + ":" + password; 38 | var credentialBytes = System.Text.Encoding.UTF8.GetBytes(credentials); 39 | var encodedCredentials = System.Convert.ToBase64String(credentialBytes); 40 | 41 | Auth = new AuthenticationHeaderValue("Basic", encodedCredentials); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/SendGrid/stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "indentation": { 5 | "useTabs": false, 6 | "indentationSize": 4, 7 | "tabSize": 4 8 | }, 9 | "documentationRules": { 10 | "companyName": "Twilio SendGrid", 11 | "copyrightText": "Copyright (c) {companyName}. All rights reserved.\nLicensed under the {licenseName} license. See {licenseFile} file in the project root for full license information.", 12 | "variables": { 13 | "licenseName": "MIT", 14 | "licenseFile": "LICENSE" 15 | }, 16 | "documentExposedElements": true, 17 | "documentInternalElements": false, 18 | "documentPrivateElements": false, 19 | "documentInterfaces": true, 20 | "documentPrivateFields": false 21 | }, 22 | "layoutRules": { 23 | "newlineAtEndOfFile": "require" 24 | }, 25 | "orderingRules": { 26 | "usingDirectivesPlacement": "outsideNamespace", 27 | "systemUsingDirectivesFirst": false, 28 | "elementOrder": [ 29 | "kind", 30 | "accessibility", 31 | "constant", 32 | "static", 33 | "readonly" 34 | ] 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /static/img/github-fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/static/img/github-fork.png -------------------------------------------------------------------------------- /static/img/github-sign-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/static/img/github-sign-up.png -------------------------------------------------------------------------------- /tests/SendGrid.Extensions.DependencyInjection.Tests/SendGrid.Extensions.DependencyInjection.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.1 5 | true 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/SendGrid.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Options; 5 | using Xunit; 6 | 7 | namespace SendGrid.Extensions.DependencyInjection.Tests 8 | { 9 | public class ServiceCollectionExtensionsTests 10 | { 11 | [Fact] 12 | public void TestAddSendGridWithoutApiKey() 13 | { 14 | // Arrange 15 | var services = new ServiceCollection().AddSendGrid(options => { }).Services.BuildServiceProvider(); 16 | 17 | // Act && Assert 18 | Assert.Throws(() => services.GetRequiredService()); 19 | } 20 | 21 | [Fact] 22 | public void TestAddSendGridReturnHttpClientBuilder() 23 | { 24 | // Arrange 25 | var collection = new ServiceCollection(); 26 | 27 | // Act 28 | var builder = collection.AddSendGrid(options => options.ApiKey = "FAKE_API_KEY"); 29 | 30 | // Assert 31 | Assert.NotNull(builder); 32 | Assert.IsAssignableFrom(builder); 33 | } 34 | 35 | [Fact] 36 | public void TestAddSendGridRegisteredWithTransientLifeTime() 37 | { 38 | // Arrange 39 | var collection = new ServiceCollection(); 40 | 41 | // Act 42 | var builder = collection.AddSendGrid(options => options.ApiKey = "FAKE_API_KEY"); 43 | 44 | // Assert 45 | var serviceDescriptor = collection.FirstOrDefault(x => x.ServiceType == typeof(ISendGridClient)); 46 | Assert.NotNull(serviceDescriptor); 47 | Assert.Equal(ServiceLifetime.Transient, serviceDescriptor.Lifetime); 48 | } 49 | 50 | [Fact] 51 | public void TestAddSendGridCanResolveSendGridClientOptions() 52 | { 53 | // Arrange 54 | var services = new ServiceCollection().AddSendGrid(options => options.ApiKey = "FAKE_API_KEY").Services.BuildServiceProvider(); 55 | 56 | // Act 57 | var sendGridClientOptions = services.GetService>(); 58 | 59 | // Assert 60 | Assert.NotNull(sendGridClientOptions); 61 | } 62 | 63 | [Fact] 64 | public void TestAddSendGridCanResolveSendGridClient() 65 | { 66 | // Arrange 67 | var services = new ServiceCollection().AddSendGrid(options => options.ApiKey = "FAKE_API_KEY").Services.BuildServiceProvider(); 68 | 69 | // Act 70 | var sendGrid = services.GetService(); 71 | 72 | // Assert 73 | Assert.NotNull(sendGrid); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/Helpers/Mail/EmailAddressTests.cs: -------------------------------------------------------------------------------- 1 | using SendGrid.Helpers.Mail; 2 | using Xunit; 3 | 4 | namespace SendGrid.Tests.Helpers.Mail 5 | { 6 | public class EmailAddressTests 7 | { 8 | [Fact] 9 | public void TestEmailAddressEquality() 10 | { 11 | var left = new EmailAddress("test1@sendgrid.com", "test"); 12 | var right = new EmailAddress("test1@sendGrid.com", "Test"); 13 | var up = new EmailAddress("test2@sendgrid.com", "test"); 14 | var down = new EmailAddress("test2@sendgrid.com", "Test"); 15 | 16 | Assert.True(left.Equals(left)); 17 | Assert.True(left.Equals(right)); 18 | Assert.False(left.Equals(up)); 19 | Assert.False(left.Equals(down)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/Helpers/Mail/NonReadableStream.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace SendGrid.Tests.Helpers.Mail 4 | { 5 | 6 | public class NonReadableStream : Stream 7 | { 8 | public override bool CanRead => false; 9 | 10 | public override bool CanSeek => throw new System.NotImplementedException(); 11 | 12 | public override bool CanWrite => throw new System.NotImplementedException(); 13 | 14 | public override long Length => throw new System.NotImplementedException(); 15 | 16 | public override long Position { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } 17 | 18 | public override void Flush() 19 | { 20 | throw new System.NotImplementedException(); 21 | } 22 | 23 | public override int Read(byte[] buffer, int offset, int count) 24 | { 25 | throw new System.NotImplementedException(); 26 | } 27 | 28 | public override long Seek(long offset, SeekOrigin origin) 29 | { 30 | throw new System.NotImplementedException(); 31 | } 32 | 33 | public override void SetLength(long value) 34 | { 35 | throw new System.NotImplementedException(); 36 | } 37 | 38 | public override void Write(byte[] buffer, int offset, int count) 39 | { 40 | throw new System.NotImplementedException(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/LicenseTests.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Tests 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using Xunit; 8 | 9 | public class LicenseTests 10 | { 11 | [Fact] 12 | public void ShouldHaveCurrentYearInLicense() 13 | { 14 | var directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory()); 15 | var line = File.ReadLines(Path.Combine(directoryInfo.Parent.Parent.Parent.Parent.Parent.FullName, "LICENSE")).Skip(2).Take(1).First(); 16 | Assert.Contains(DateTime.Now.Year.ToString(), line); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/Reliability/RetryTestBehaviourDelegatingHandler.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Tests.Reliability 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | public class RetryTestBehaviourDelegatingHandler : DelegatingHandler 11 | { 12 | private readonly List>> behaviours; 13 | 14 | public RetryTestBehaviourDelegatingHandler() 15 | { 16 | behaviours = new List>>(); 17 | } 18 | 19 | public int InvocationCount { get; private set; } 20 | 21 | public void AddBehaviour(Func> configuredBehavior) 22 | { 23 | Task behaviour() 24 | { 25 | InvocationCount++; 26 | return configuredBehavior(); 27 | } 28 | 29 | behaviours.Add(behaviour); 30 | } 31 | 32 | public Task OK() 33 | { 34 | return CreateHttpResponse(HttpStatusCode.OK); 35 | } 36 | 37 | public Task InternalServerError() 38 | { 39 | return CreateHttpResponse(HttpStatusCode.InternalServerError); 40 | } 41 | public Task ServiceUnavailable() 42 | { 43 | return CreateHttpResponse(HttpStatusCode.ServiceUnavailable); 44 | } 45 | 46 | public Task AuthenticationError() 47 | { 48 | return CreateHttpResponse(HttpStatusCode.Unauthorized); 49 | } 50 | public Task HttpVersionNotSupported() 51 | { 52 | return CreateHttpResponse(HttpStatusCode.HttpVersionNotSupported); 53 | } 54 | public Task NotImplemented() 55 | { 56 | return CreateHttpResponse(HttpStatusCode.NotImplemented); 57 | } 58 | 59 | public Task CreateHttpResponse(HttpStatusCode statusCode) 60 | { 61 | var httpResponseMessage = new HttpResponseMessage(statusCode) { Content = new StringContent(string.Empty) }; 62 | return Task.Factory.StartNew(() => httpResponseMessage); 63 | } 64 | 65 | public Task TaskCancelled() 66 | { 67 | throw new TaskCanceledException(); 68 | } 69 | 70 | public Task NonTransientException() 71 | { 72 | throw new InvalidOperationException(); 73 | } 74 | 75 | protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 76 | { 77 | return behaviours[InvocationCount](); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/RequiredFilesExistTest.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Tests 2 | { 3 | using System.IO; 4 | using Xunit; 5 | 6 | public class TestRequiredFilesExist 7 | { 8 | 9 | // ./Docker or docker/Docker 10 | public void checkDockerExists() 11 | { 12 | bool dockerExists = File.Exists("./Dockerfile") || 13 | File.Exists("./docker/Dockerfile"); 14 | Assert.True(dockerExists); 15 | } 16 | 17 | // ./docker-compose.yml or ./docker/docker-compose.yml 18 | public void checkDockerComposeExists() 19 | { 20 | bool dockerComposeExists = File.Exists("./docker-compose.yml") || 21 | File.Exists("./docker/docker-compose.yml"); 22 | Assert.True(dockerComposeExists); 23 | } 24 | 25 | // ./.env_sample 26 | public void checkEnvSampleExists() 27 | { 28 | Assert.True(File.Exists("./.env_sample")); 29 | } 30 | 31 | // ./.gitignore 32 | public void checkGitIgnoreExists() 33 | { 34 | Assert.True(File.Exists("./.gitignore")); 35 | } 36 | 37 | 38 | // ./CHANGELOG.md 39 | public void checkChangelogExists() 40 | { 41 | Assert.True(File.Exists("./CHANGELOG.md")); 42 | } 43 | 44 | // ./CODE_OF_CONDUCT.md 45 | public void checkCodeOfConductExists() 46 | { 47 | Assert.True(File.Exists("./CODE_OF_CONDUCT.md")); 48 | } 49 | 50 | // ./CONTRIBUTING.md 51 | public void checkContributingGuideExists() 52 | { 53 | Assert.True(File.Exists("./CONTRIBUTING.md")); 54 | } 55 | 56 | // ./LICENSE 57 | public void checkLicenseExists() 58 | { 59 | Assert.True(File.Exists("./LICENSE")); 60 | } 61 | 62 | // ./PULL_REQUEST_TEMPLATE.md 63 | public void checkPullRequestExists() 64 | { 65 | Assert.True(File.Exists("./PULL_REQUEST_TEMPLATE.md")); 66 | } 67 | 68 | // ./README.md 69 | public void checkReadMeExists() 70 | { 71 | Assert.True(File.Exists("./README.md")); 72 | } 73 | 74 | // ./TROUBLESHOOTING.md 75 | public void checkTroubleShootingGuideExists() 76 | { 77 | Assert.True(File.Exists("./TROUBLESHOOTING.md")); 78 | } 79 | 80 | // ./USAGE.md 81 | public void checkUsageGuideExists() 82 | { 83 | Assert.True(File.Exists("./USAGE.md")); 84 | } 85 | 86 | // ./USE_CASES.md 87 | public void checkUseCases() 88 | { 89 | Assert.True(File.Exists("./USE_CASES.md")); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/SendGrid.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.1 5 | true 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/SendGridClientExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Moq; 7 | using Newtonsoft.Json; 8 | using Newtonsoft.Json.Linq; 9 | using SendGrid.Permissions; 10 | using Xunit; 11 | 12 | namespace SendGrid.Tests 13 | { 14 | public class SendGridClientExtensionsTests 15 | { 16 | [Fact] 17 | public async Task MasksPermissionsForAGivenClient() 18 | { 19 | var content = "{\"scopes\": [\"alerts.read\"]}"; 20 | var response = new Response(HttpStatusCode.OK, new StringContent(content), null); 21 | var mockClient = new Mock(); 22 | mockClient.Setup(x => x.RequestAsync(BaseClient.Method.GET, null, null, "scopes", default)) 23 | .ReturnsAsync(response); 24 | 25 | var builder = await mockClient.Object.CreateMaskedPermissionsBuilderForClient(); 26 | 27 | builder.Include("mail.send", "alerts.read"); 28 | var scopes = builder.Build().ToArray(); 29 | 30 | Assert.Single(scopes); 31 | Assert.Contains("alerts.read", scopes); 32 | } 33 | 34 | [Fact] 35 | public async Task CallsApiWithBuiltScopes() 36 | { 37 | string[] requestedScopes = null; 38 | string requestedApiKeyName = null; 39 | var mockClient = new Mock(); 40 | mockClient.Setup(x => x.RequestAsync(BaseClient.Method.POST, It.IsAny(), null, "api_keys", default)) 41 | .Callback((method, body, query, path, token) => 42 | { 43 | JObject json = JsonConvert.DeserializeObject(body) as JObject; 44 | requestedScopes = (json["scopes"] as JArray).Select(x => x.Value()).ToArray(); 45 | requestedApiKeyName = (json["name"]).Value(); 46 | }) 47 | .ReturnsAsync(new Response(HttpStatusCode.Created, null, null)); 48 | 49 | var builder = new SendGridPermissionsBuilder(); 50 | builder.AddPermissionsFor(SendGridPermission.Alerts); 51 | var response = await mockClient.Object.CreateApiKey(builder, "Alerts Test"); 52 | 53 | Assert.Equal(4, requestedScopes.Length); 54 | Assert.Contains("alerts.create", requestedScopes); 55 | Assert.Contains("alerts.delete", requestedScopes); 56 | Assert.Contains("alerts.read", requestedScopes); 57 | Assert.Contains("alerts.update", requestedScopes); 58 | 59 | Assert.Equal("Alerts Test", requestedApiKeyName); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/SendgridEmailClientTests.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Tests 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | using SendGrid.Helpers.Mail; 6 | using Xunit; 7 | 8 | public class SendgridEmailClientTests 9 | { 10 | [Fact] 11 | public void TestClientOptionsConstruction() 12 | { 13 | var options = new SendGridClientOptions(); 14 | Assert.Equal("https://api.sendgrid.com", options.Host); 15 | } 16 | [Fact] 17 | public void TestClientOptionsSetDataResidency() 18 | { 19 | var options = new SendGridClientOptions(); 20 | options.SetDataResidency("eu"); 21 | Assert.Equal("https://api.eu.sendgrid.com/", options.Host); 22 | } 23 | [Fact] 24 | public void TestClientOptionsSetDataResidencyEU() 25 | { 26 | var options = new SendGridClientOptions(); 27 | options.SetDataResidency("eu"); 28 | Assert.Equal("https://api.eu.sendgrid.com/", options.Host); 29 | } 30 | 31 | [Fact] 32 | public void TestClientOptionsSetViaSendgridClient() 33 | { 34 | var options = new SendGridClientOptions(); 35 | options.SetDataResidency("eu"); 36 | var sg = new SendGridClient(options); 37 | Assert.Equal("https://api.eu.sendgrid.com/", options.Host); 38 | } 39 | 40 | [Fact] 41 | public void TestErrorClientOptionsNUllEmpty() 42 | { 43 | var options = new SendGridClientOptions(); 44 | Assert.Throws(() => options.SetDataResidency("")); 45 | Assert.Throws(() => options.SetDataResidency(null)); 46 | } 47 | 48 | [Fact] 49 | public void TestErrorClientOptions() 50 | { 51 | var options = new SendGridClientOptions(); 52 | Assert.Throws(() => options.SetDataResidency("foo")); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/TemplateDataSerialisationTests.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SendGrid.Helpers.Mail; 3 | using Xunit; 4 | 5 | namespace SendGrid.Tests 6 | { 7 | public class TemplateDataSerialisationTests 8 | { 9 | [Fact] 10 | public void TestSetTemplateDataWorksWithSpecifiedJsonPropertyNames() 11 | { 12 | var msg = new SendGridMessage(); 13 | 14 | var dynamicTemplateData = new TestTemplateData 15 | { 16 | MyCamelCaseProperty = "camelCase", 17 | MyKebabCaseProperty = "kebab-case", 18 | MyPascalCaseProperty = "PascalCase", 19 | MySnakeCaseProperty = "snake_case", 20 | }; 21 | 22 | msg.SetTemplateData(dynamicTemplateData); 23 | Assert.Equal("{\"personalizations\":[{\"dynamic_template_data\":{\"myCamelCaseProperty\":\"camelCase\",\"my-kebab-case-property\":\"kebab-case\",\"MyPascalCaseProperty\":\"PascalCase\",\"my_snake_case_property\":\"snake_case\"}}]}", msg.Serialize()); 24 | } 25 | 26 | private class TestTemplateData 27 | { 28 | [JsonProperty("myCamelCaseProperty")] 29 | public string MyCamelCaseProperty { get; set; } 30 | 31 | [JsonProperty("my-kebab-case-property")] 32 | public string MyKebabCaseProperty { get; set; } 33 | 34 | public string MyPascalCaseProperty { get; set; } 35 | 36 | [JsonProperty("my_snake_case_property")] 37 | public string MySnakeCaseProperty { get; set; } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/SendGrid.Tests/TwilioEmailClientTests.cs: -------------------------------------------------------------------------------- 1 | namespace SendGrid.Tests 2 | { 3 | using System; 4 | using Xunit; 5 | 6 | public class TwilioEmailClientTests 7 | { 8 | [Fact] 9 | public void TestClientOptionsConstruction() 10 | { 11 | var options = new TwilioEmailClientOptions("username", "password"); 12 | Assert.Equal("https://email.twilio.com", options.Host); 13 | Assert.Equal("Basic", options.Auth.Scheme); 14 | Assert.Equal("dXNlcm5hbWU6cGFzc3dvcmQ=", options.Auth.Parameter); 15 | } 16 | 17 | [Fact] 18 | public void TestNullUsernameOrPassword() 19 | { 20 | Assert.Throws(() => new TwilioEmailClientOptions(null, "password")); 21 | Assert.Throws(() => new TwilioEmailClientOptions("username", null)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tools/sendgrid-csharp.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/tools/sendgrid-csharp.snk -------------------------------------------------------------------------------- /twilio_sendgrid_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-csharp/4a315350e910ef10c6579ca5291ed7f82ad9d376/twilio_sendgrid_logo.png --------------------------------------------------------------------------------