-
Couldn't load subscription status.
- Fork 1
Feature - Add batch email support to .NET client #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dr-3lo
wants to merge
28
commits into
main
Choose a base branch
from
feature/95-batch-email
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
1ce3733
Created BulkEmailRequest model and validators. Refactored existing em…
zhaparoff 55b2dcd
Renamed abstractions to align with API naming.
zhaparoff e580b58
Updates NuGet
zhaparoff 07bd2ca
Add response, cleanup tests.
zhaparoff 9607b81
Batch WiP
zhaparoff 8c2c6d1
Merge latest main
zhaparoff dc773a0
Batch emails implementation + tests
zhaparoff 56ab5e7
Adds integration tests for batch email
zhaparoff 59fc39f
Merge branch 'main' into feature/bulk-email
dr-3lo 5b0b289
Merge branch 'main' into feature/bulk-email
dr-3lo 22b16ba
Merge branch 'main' into feature/bulk-email
dr-3lo 0cd488b
post merge fix
dr-3lo e6a91af
Feature - Batch Email Send (#95)
dr-3lo 82059b6
Merge branch 'main' into feature/95-batch-email
dr-3lo df86eae
Merge branch 'feature/95-batch-email' of https://github.com/railsware…
dr-3lo 374bd14
post merge fix
dr-3lo 47ce28a
Feature - Batch Email Send (#95)
dr-3lo 31347a0
Feature - Batch Email Send (#95)
dr-3lo 7d85d61
Feature - Batch Email Send (#95)
dr-3lo 5978b8e
Feature - Batch Email Send (#95)
dr-3lo 68dedc0
Feature - Batch Email Send (#95)
dr-3lo 1c7b1ea
Feature - Batch Email Send (#95)
dr-3lo c5f73f6
Coderabbit comments fix
dr-3lo 7cbeecb
Fixes for PR #158 comments:
dr-3lo 64a6f28
Add validation tests for empty recipients in BatchEmailRequest and Se…
dr-3lo f31e167
using consistent assertion style.
dr-3lo a363f83
Refactor email request validation and documentation for clarity and c…
dr-3lo 97038d1
Remove redundant test case for zero total recipients in "exceed" vali…
dr-3lo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,316 @@ | ||
| --- | ||
| uid: batch-send-email | ||
| --- | ||
|
|
||
| # Sending Batch Emails | ||
| This article covers scenarios for forming and sending batch emails using the Mailtrap API client. | ||
|
|
||
| ## Creating batch request | ||
| Batch email API uses @Mailtrap.Emails.Requests.BatchEmailRequest to create a payload for the API request. | ||
| You can set up a base request and a collection of individual requests. | ||
|
|
||
| ### Fluent builder | ||
| You can use the fluent builder extensions in @Mailtrap.Emails.Requests.BatchEmailRequestBuilder to create batch requests in a fluent style: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| var batchRequest = BatchEmailRequest | ||
| .Create() | ||
| .Base(b => b | ||
| .From("[email protected]", "John Doe") | ||
| .Subject("Batch Invitation")) | ||
| .Requests(r => r | ||
| .To("[email protected]") | ||
| .Text("Dear Bill,\n\nSee you soon!")) | ||
| .Requests(SendEmailRequest.Create() | ||
| .From("[email protected]", " It's a John Cena") // Overwrite the base attributes | ||
| .To("[email protected]") | ||
| .Cc("[email protected]") | ||
| .Subject("Invitation to Earth")); | ||
| ... | ||
| ``` | ||
|
|
||
| ### Regular initialization | ||
| Alternatively, you can use object initialization: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| var baseRequest = new EmailRequest | ||
| { | ||
| From = new EmailAddress("[email protected]", "John Doe"), | ||
| Subject = "Batch Invitation" | ||
| }; | ||
|
|
||
| // You can specify up to 1000 recipients in total across the To, Cc, and Bcc fields (i.e. To + CC + Bcc <=1000). | ||
| // At least one of recipient collections must contain at least one recipient. | ||
| var requests = new List<SendEmailRequest> | ||
| { | ||
| new SendEmailRequest | ||
| { | ||
| To = { new EmailAddress("[email protected]") }, | ||
| TextBody = "Dear Bill,\n\nSee you soon!" | ||
| }, | ||
| new SendEmailRequest | ||
| { | ||
| Cc = { new EmailAddress("[email protected]") }, | ||
| TextBody = "Dear Lord,\n\nSee you soon!" | ||
| }, | ||
| new SendEmailRequest | ||
| { | ||
| Bcc = { new EmailAddress("[email protected]") }, | ||
| TextBody = "Dear Sara,\n\nKeep you posted!" | ||
| } | ||
| }; | ||
|
|
||
| var batchRequest = new BatchEmailRequest | ||
| { | ||
| Base = baseRequest, | ||
| Requests = requests | ||
| }; | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > You can specify up to 500 requests in a single batch. | ||
| > Each request will inherit properties from the base request unless overridden. | ||
|
|
||
| ## Attaching files | ||
| You can attach files to Base and individual requests in the batch, just as with single emails in two ways for inlining (embedding) or as a standalone downloadable file: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| var batchRequest = BatchEmailRequest | ||
| .Create() | ||
| .Base(b => b | ||
| .From("[email protected]", "John Doe") | ||
| .Subject("Latest Notes") | ||
| .Attach( | ||
| content: Convert.ToBase64String(File.ReadAllBytes(@"C:\files\note.pdf")), | ||
| fileName: "note.pdf", | ||
| disposition: DispositionType.Attachment, // Downloadable | ||
| mimeType: MediaTypeNames.Application.Pdf)) | ||
| .Requests(r => r | ||
| .To("[email protected]") | ||
| .Text("Dear Bill,\n\nSee you soon!") | ||
| .Attach( | ||
| content: Convert.ToBase64String(File.ReadAllBytes(@"C:\files\preview.pdf")), | ||
| fileName: "preview.pdf", | ||
| disposition: DispositionType.Inline, // For embedding | ||
| mimeType: MediaTypeNames.Application.Pdf)); | ||
| ``` | ||
|
|
||
| ## Email from template | ||
| You can use templates in batch requests as well. | ||
| You can create a template and obtain its ID via Mailtrap.EmailTemplates APIs. | ||
| Then you can use it in emails: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| var batchRequest = BatchEmailRequest | ||
| .Create() | ||
| .Base(b => b.From("[email protected]", "John Doe")) | ||
| .Requests(r => r | ||
| .To("[email protected]") | ||
| .Template("60dca11e-0bc2-42ea-91a8-5ff196acb3f9") | ||
| .TemplateVariables(new Dictionary<string, string> | ||
| { | ||
| { "name", "Bill" }, | ||
| { "sender", "John" } | ||
| })); | ||
| ``` | ||
|
|
||
| ## Kitchen sink | ||
| Overview of all possible settings for batch requests: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| var batchRequest = BatchEmailRequest.Create(); | ||
|
|
||
| batchRequest.Base(b => b | ||
| .From("[email protected]", "John Doe") | ||
| .ReplyTo("[email protected]") | ||
| .Subject("Batch Invitation")); | ||
|
|
||
| // Categorize | ||
| batchRequest.Base | ||
| .Category("Invitation"); | ||
|
|
||
| // HTML body. | ||
| // At least one of Text or Html body must be specified. | ||
| batchRequest.Base | ||
| .Html( | ||
| "<h2>Greetings, Bill!</h2>" + | ||
| "<p>It will be a great pleasure to see you on our blue planet next weekend.</p>" + | ||
| "<p>Regards,<br/>" + | ||
| "John</p>"); | ||
|
|
||
| // Add custom variables | ||
| batchRequest.Base | ||
| .CustomVariable("var_key", "var_value"); | ||
|
|
||
| // Add custom headers | ||
| batchRequest.Base | ||
| .Header( | ||
| new("X-Custom-Header-1", "Custom Value 1"), | ||
| new("X-Custom-Header-2", "Custom Value 2"), | ||
| new("X-Custom-Header-3", "Custom Value 3")); | ||
|
|
||
| batchRequest.Requests(r => r | ||
| .From("[email protected]", "John R. Doe") | ||
| .To("[email protected]") | ||
| .Cc("[email protected]", "James") | ||
| .Bcc(new EmailAddress("[email protected]"), new EmailAddress("[email protected]")) | ||
| .Html("<h2>Greetings, Bill!</h2><p>See you soon!</p>") | ||
| .Text("Dear Bill,\n\nSee you soon!") | ||
| .Attach( | ||
| content: Convert.ToBase64String(File.ReadAllBytes(@"C:\files\preview.pdf")), | ||
| fileName: "preview.pdf", | ||
| disposition: DispositionType.Attachment, | ||
| mimeType: MediaTypeNames.Application.Pdf) | ||
| .CustomVariable("var_key", "var_value") | ||
| .Header("X-Custom-Header", "Custom Value")); | ||
| ``` | ||
|
|
||
| ## Request validation | ||
| After creating a batch request, validate it on a client side to ensure it meets API requirements and sending won't throw validation exceptions it also will minimize unnecessary HTTP round-trips. | ||
| @Mailtrap.Emails.Requests.BatchEmailRequest implements @Mailtrap.Core.Validation.IValidatable interface, which can be used to perform that task. | ||
|
|
||
| @Mailtrap.Core.Validation.IValidatable.Validate method verifies request data and returns a @Mailtrap.Core.Validation.ValidationResult instance that contains validation result: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| var batchRequest = new BatchEmailRequest(); | ||
|
|
||
| var validationResult = batchRequest.Validate(); | ||
|
|
||
| if (validationResult.IsValid) | ||
| { | ||
| // Send | ||
| } | ||
| else | ||
| { | ||
| // Handle invalid batch request | ||
| } | ||
| ``` | ||
|
|
||
| Alternatively, use `EnsureValidity` to throw on validation errors: | ||
| ```csharp | ||
| using Mailtrap.Emails.Requests; | ||
|
|
||
| ... | ||
|
|
||
| try | ||
| { | ||
| var batchRequest = new BatchEmailRequest(); | ||
|
|
||
| batchRequest.Validate().EnsureValidity(nameof(batchRequest)); // Will throw if request isn't valid. | ||
| } | ||
| catch (ArgumentException aex) | ||
| { | ||
| // Handle validation issues | ||
| } | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > The client validates batch requests before sending. | ||
|
|
||
| ## Using batch send API | ||
| After forming a valid batch request, send it using the batch API: | ||
| ```csharp | ||
| using Mailtrap; | ||
| using Mailtrap.Emails.Models; | ||
| using Mailtrap.Emails.Requests; | ||
| using Mailtrap.Emails.Responses; | ||
|
|
||
| ... | ||
|
|
||
| private readonly IMailtrapClient _mailtrapClient; | ||
|
|
||
| try | ||
| { | ||
| BatchEmailRequest batchRequest = BatchEmailRequest | ||
| .Create() | ||
| .Base(b => b.From("[email protected]", "John Doe")) | ||
| .Requests(r => r.To("[email protected]").Text("Dear Bill,\n\nSee you soon!")); | ||
|
|
||
| if (batchRequest.Validate().IsValid) | ||
| { | ||
| using var cts = new CancellationTokenSource(); | ||
|
|
||
| BatchSendEmailResponse response = await _mailtrapClient | ||
| .BatchEmail() | ||
| .Send(batchRequest, cts.Token); | ||
|
|
||
| var messageIds = response.MessageIds; | ||
| } | ||
| else | ||
| { | ||
| // handle validation issues | ||
| } | ||
| } | ||
| catch (MailtrapApiException mtex) | ||
| { | ||
| // handle Mailtrap specific exceptions | ||
| } | ||
| catch (ArgumentException aex) | ||
| { | ||
| // handle request validation issues | ||
| } | ||
| catch (JsonException jex) | ||
| { | ||
| // handle serialization issues | ||
| } | ||
| catch (HttpRequestException hrex) | ||
| { | ||
| // handle HTTP errors | ||
| } | ||
| catch (OperationCanceledException ocex) | ||
| { | ||
| // handle cancellation | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| // handle other exceptions | ||
| } | ||
| ``` | ||
|
|
||
| > [!IMPORTANT] | ||
| > @Mailtrap.IMailtrapClient.BatchEmail will use the batch send API as defined in client configuration. | ||
|
|
||
| Additionally, you can always use specific send API (transactional, bulk or test) explicitly, to route emails to: | ||
| ```csharp | ||
| var inboxId = 12345; | ||
| IBatchEmailClient batchEmailClient = _mailtrapClient.BatchTest(inboxId); // Batch Emails will be sent using Email Testing API | ||
| // IBatchEmailClient batchEmailClient = _mailtrapClient.BatchTransactional(); // Batch Emails will be sent using Email Sending API | ||
| // IBatchEmailClient batchEmailClient = _mailtrapClient.BatchBulk(); // Batch Emails will be sent using Bulk Sending API | ||
|
|
||
| var response = await batchEmailClient.Send(request); | ||
| ``` | ||
|
|
||
| > [!TIP] | ||
| > @Mailtrap.IMailtrapClient.BatchTransactional, @Mailtrap.IMailtrapClient.BatchBulk and @Mailtrap.IMailtrapClient.BatchTest(System.Int64) | ||
| > are factory methods that will create new @Mailtrap.Emails.IBatchEmailClient instance every time when called. | ||
| > Thus, if you need to perform multiple `Send()` calls to the same endpoint, it will be a good idea | ||
| > to spawn client once and then reuse it: | ||
| > ```csharp | ||
| > IBatchEmailClient batchEmailClient = _mailtrapClient.BatchBulk(); // Caching client instance | ||
| > | ||
| > foreach(var request in batchRequests) | ||
| > { | ||
| > var response = await batchEmailClient.Send(request); | ||
| > } | ||
| >``` | ||
|
|
||
| ## See also | ||
| More examples available [Mailtrap .NET examples on GitHub](https://github.com/railsware/mailtrap-dotnet/tree/main/examples). | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.