- 
                Notifications
    You must be signed in to change notification settings 
- 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
          
     Merged
      
      
    
  
     Merged
                    Changes from 23 commits
      Commits
    
    
            Show all changes
          
          
            29 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 9f1dbc8
              
                Merge branch 'main' into feature/95-batch-email
              
              
                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,309 @@ | ||
| --- | ||
| 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]", "John Doe") | ||
| .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" | ||
| }; | ||
|  | ||
| var requests = new List<SendEmailRequest> | ||
| { | ||
| new SendEmailRequest | ||
| { | ||
| To = { new EmailAddress("[email protected]") }, | ||
| TextBody = "Dear Bill,\n\nSee you soon!" | ||
| }, | ||
| new SendEmailRequest | ||
| { | ||
| To = { new EmailAddress("[email protected]") }, | ||
| TextBody = "Dear Lord,\n\nSee you soon!" | ||
| } | ||
| }; | ||
|  | ||
| 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")); | ||
|  | ||
|         
                  dr-3lo marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| 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 in case when you need to perform multiple `Send()` calls to the same endpoint it will be 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). | ||
  
    
      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
    
  
  
    
              
      
      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.