-
Notifications
You must be signed in to change notification settings - Fork 11
Batch Sending Api #63
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
base: main
Are you sure you want to change the base?
Conversation
…, bulk, and sandbox emails in batch
Warning Rate limit exceeded@narekhovhannisyan has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 49 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe changes introduce batch email sending functionality to the codebase. This includes a new Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MailtrapClient
participant MailtrapAPI
User->>MailtrapClient: batchSend(BatchSendRequest)
MailtrapClient->>MailtrapAPI: POST /api/batch (payload with base + requests)
MailtrapAPI-->>MailtrapClient: BatchSendResponse (message_ids)
MailtrapClient-->>User: Promise resolves with BatchSendResponse
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (10)
README.md (1)
69-74
: The new Batch Sending API section looks good, but fix the list indentation.The addition of the Batch Sending API section with links to examples aligns perfectly with the PR objectives. However, there's a minor formatting issue with the list items.
Fix the markdown list indentation by removing the leading space before each dash:
### Batch Sending API - - [Send a batch of emails](examples/batch/send-batch.ts) - - [Send a batch of transactional emails](examples/batch/transactional-batch.ts) - - [Send a batch of bulk emails](examples/batch/bulk-batch.ts) - - [Send a batch of sandbox emails](examples/batch/sandbox-batch.ts) + - [Send a batch of emails](examples/batch/send-batch.ts) + - [Send a batch of transactional emails](examples/batch/transactional-batch.ts) + - [Send a batch of bulk emails](examples/batch/bulk-batch.ts) + - [Send a batch of sandbox emails](examples/batch/sandbox-batch.ts)🧰 Tools
🪛 LanguageTool
[grammar] ~72-~72: Possible verb agreement error. Did you mean “sends”? (Some collective nouns can be treated as both singular and plural, so ‘Send’ is not always incorrect.)
Context: ...ails](examples/batch/send-batch.ts) - [Send a batch of transactional emails](exampl...(COLLECTIVE_NOUN_VERB_AGREEMENT_VBP)
🪛 markdownlint-cli2 (0.17.2)
71-71: Unordered list indentation
Expected: 0; Actual: 1(MD007, ul-indent)
72-72: Unordered list indentation
Expected: 0; Actual: 1(MD007, ul-indent)
73-73: Unordered list indentation
Expected: 0; Actual: 1(MD007, ul-indent)
74-74: Unordered list indentation
Expected: 0; Actual: 1(MD007, ul-indent)
examples/testing/send-mail.ts (1)
6-7
: Redundant documentation links - consider consolidating.There are two @see links pointing to the same article, with the second one just adding a fragment identifier to the URL.
Consider consolidating these links or making the purpose of the second link more explicit:
* @see https://help.mailtrap.io/article/69-sending-domain-setup -* @see https://help.mailtrap.io/article/69-sending-domain-setup#Demo-Domain--oYOU5" +* @see https://help.mailtrap.io/article/69-sending-domain-setup#Demo-Domain--oYOU5 "Demo Domain Setup Details"Alternatively, remove the first link if the second one with the fragment identifier is more specific and useful.
examples/batch/template.ts (1)
1-39
: Well-structured example for template-based batch sending.This example clearly demonstrates how to use the new batch sending functionality with templates. The code is well-organized with proper comments explaining prerequisites and an intuitive structure separating base properties from individual request properties.
Consider enhancing the example by adding a comment showing what the expected response structure would look like, to help users better understand the API:
}) - .then(console.log) + .then((response) => { + // Example response structure: + // { + // success: true, + // message_ids: ["msg_1234abcd", "msg_5678efgh"] + // } + console.log(response); + }) .catch(console.error);examples/batch/bulk.ts (1)
20-21
: Subject line doesn't match example typeThe subject line contains "Sandbox Email" but this is a bulk email example. This could be confusing to users.
- subject: "Sandbox Email", + subject: "Bulk Email",src/lib/MailtrapClient.ts (2)
147-149
: Consider simplifying the conditional URL constructionThe variable name
ifSandbox
is not very descriptive, and the conditional logic could be simplified for better readability.- const ifSandbox = - this.sandbox && this.testInboxId ? `/${this.testInboxId}` : ""; - const url = `${host}/api/batch${ifSandbox}`; + const testInboxPath = this.sandbox && this.testInboxId ? `/${this.testInboxId}` : ""; + const url = `${host}/api/batch${testInboxPath}`;
152-157
: Consider handling optional fields more elegantlyThe current implementation includes all fields in the mapped requests, even if they're undefined. You might want to only include fields that are actually present in the request.
- const preparedRequests = request.requests.map((req) => ({ - to: req.to, - cc: req.cc, - bcc: req.bcc, - custom_variables: req.custom_variables, - })); + const preparedRequests = request.requests.map((req) => { + const mappedRequest: Record<string, any> = { to: req.to }; + + if (req.cc) mappedRequest.cc = req.cc; + if (req.bcc) mappedRequest.bcc = req.bcc; + if (req.custom_variables) mappedRequest.custom_variables = req.custom_variables; + + return mappedRequest; + });src/types/mailtrap.ts (2)
72-77
: Consider reusing the existingSendResponse
type.The new
BatchSendResponse
type has the same structure as the existingSendResponse
type. To avoid duplication and ensure consistency, consider reusingSendResponse
instead of creating a new type.-export type BatchSendResponse = { - success: true; - message_ids: string[]; -}; +export type BatchSendResponse = SendResponse;
87-101
: Consider using union types to better represent content vs template emails.The
base
object combines properties for both content-based emails (text
,html
) and template-based emails (template_uuid
). Consider modeling this similar to the existing pattern whereexport type BatchSendRequest = { - base: { - from: Address; - subject?: string; - text?: string | Buffer; - html?: string | Buffer; - template_uuid?: string; - category?: string; - attachments?: Attachment[]; - headers?: MailtrapHeaders; - custom_variables?: CustomVariables; - reply_to?: Address; - }; + base: { + from: Address; + category?: string; + attachments?: Attachment[]; + headers?: MailtrapHeaders; + custom_variables?: CustomVariables; + reply_to?: Address; + } & ( + { + subject: string; + text?: string | Buffer; + html?: string | Buffer; + } | { + template_uuid: string; + } + ); requests: BatchSendRequestItem[]; };src/__tests__/lib/mailtrap-client.test.ts (2)
521-538
: Enhance test coverage with template variables.The test data for template-based batch sending doesn't exercise the
template_variables
property withinBatchSendRequestItem
. Add a test with different template variables for each recipient to ensure this functionality works correctly.requests: [ { to: [ { email: "[email protected]", name: "recipient1", }, ], + template_variables: { + user_name: "John Doe", + product_name: "Product A" + } }, { to: [ { email: "[email protected]", name: "recipient2", }, ], + template_variables: { + user_name: "Jane Smith", + product_name: "Product B" + } }, ],
386-691
: Consider refactoring tests to reduce duplication.The batch sending tests contain significant duplication in test data and assertion patterns. Consider extracting common setup and test data into helper functions or variables to improve maintainability.
For example, you could create a helper function for batch test setup:
function setupBatchTest(clientConfig, endpoint) { const client = new MailtrapClient(clientConfig); const expectedResponseData = { success: true, message_ids: ["0c7fd939-02cf-11ed-88c2-0a58a9feac02"], }; mock.onPost(endpoint).reply(200, expectedResponseData); const batchData = { base: { from: { email: "[email protected]", name: "Mailtrap", }, subject: "Batch Subject", text: "Batch Text", }, requests: [ { to: [ { email: "[email protected]", name: "recipient1", }, ], }, { to: [ { email: "[email protected]", name: "recipient2", }, ], }, ], }; return { client, expectedResponseData, batchData }; }Then use it in your tests:
it("successfully sends a batch of emails in bulk mode", async () => { const { client, expectedResponseData, batchData } = setupBatchTest( { token: "MY_API_TOKEN", bulk: true }, `${BULK_ENDPOINT}/api/batch` ); const result = await client.batchSend(batchData); expect(mock.history.post[0].url).toEqual(`${BULK_ENDPOINT}/api/batch`); expect(mock.history.post[0].data).toEqual( JSON.stringify({ base: batchData.base, requests: batchData.requests.map((req) => ({ to: req.to, })), }) ); expect(result).toEqual(expectedResponseData); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (10)
README.md
(1 hunks)examples/batch/bulk.ts
(1 hunks)examples/batch/sandbox.ts
(1 hunks)examples/batch/template.ts
(1 hunks)examples/batch/transactional.ts
(1 hunks)examples/testing/send-mail.ts
(1 hunks)src/__tests__/lib/mailtrap-client.test.ts
(1 hunks)src/lib/MailtrapClient.ts
(2 hunks)src/lib/mail-buffer-encoder.ts
(1 hunks)src/types/mailtrap.ts
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/lib/MailtrapClient.ts (2)
src/types/mailtrap.ts (2)
BatchSendRequest
(87-101)BatchSendResponse
(74-77)src/lib/mail-buffer-encoder.ts (1)
encodeMailBuffers
(8-33)
src/lib/mail-buffer-encoder.ts (1)
src/types/mailtrap.ts (1)
src/__tests__/lib/mailtrap-client.test.ts (1)
src/lib/MailtrapError.ts (1)
MailtrapError
(1-1)
🪛 LanguageTool
README.md
[grammar] ~72-~72: Possible verb agreement error. Did you mean “sends”? (Some collective nouns can be treated as both singular and plural, so ‘Send’ is not always incorrect.)
Context: ...ails](examples/batch/send-batch.ts) - [Send a batch of transactional emails](exampl...
(COLLECTIVE_NOUN_VERB_AGREEMENT_VBP)
🪛 markdownlint-cli2 (0.17.2)
README.md
71-71: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
72-72: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
73-73: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
74-74: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
🔇 Additional comments (10)
src/lib/mail-buffer-encoder.ts (1)
8-8
: Good improvement to function signature flexibility.Changing the function signature to accept
Partial<Mail>
instead of justThis change aligns well with the batch sending functionality being added in this PR and follows good TypeScript practices.
examples/batch/bulk.ts (1)
1-40
: Overall, the example looks goodThis example clearly demonstrates how to use the batch sending API in bulk mode. The code structure is clean and includes proper error handling with promise chaining.
examples/batch/transactional.ts (1)
1-38
: Example looks goodThis transactional batch sending example is well-structured and demonstrates the API usage clearly. It includes proper documentation, placeholder values, and error handling.
examples/batch/sandbox.ts (1)
1-43
: Example looks goodThe sandbox mode batch sending example is well-implemented with all the necessary configuration options. The code is clean and follows the same pattern as the other examples, ensuring consistency across the codebase.
src/lib/MailtrapClient.ts (2)
14-20
: Imports look goodThe updated import statement correctly includes the new batch-related types that are used in the implementation.
139-163
: Implementation is solidThe
batchSend
method implementation looks good. It:
- Properly determines the host based on the client configuration
- Correctly constructs the API URL with conditional test inbox ID for sandbox mode
- Uses the existing
encodeMailBuffers
function to process the base mail- Maps request items to include only the necessary fields
- Makes a POST request to the batch API endpoint with properly structured data
The implementation follows the same patterns as the existing code, which ensures consistency.
src/types/mailtrap.ts (1)
79-85
: LGTM: Clear and well-structured recipient details type.The
BatchSendRequestItem
type is well-defined with appropriate optional fields for customizing individual recipients in a batch.src/__tests__/lib/mailtrap-client.test.ts (3)
555-607
: LGTM: Comprehensive test for transactional batch sending.This test thoroughly verifies the functionality of transactional batch sending, covering the proper endpoint construction, request payload formatting, and response handling.
609-652
: LGTM: Proper API error handling test.This test effectively validates that API errors are properly caught and converted to
MailtrapError
instances with the correct error message.
654-690
: LGTM: Proper HTTP transport error handling test.This test ensures that HTTP transport errors are correctly handled and converted to
MailtrapError
instances with appropriate error messages.
…ne/template structures
… in batch sending
@coderabbitai check |
Tip For best results, initiate chat on the files or code changes. @narekhovhannisyan I've checked the PR implementation and everything looks good! The batch sending API is well-implemented with:
The approach of having a base email template with individual recipient customizations is a solid design pattern for batch operations. The implementation aligns well with the existing codebase structure while extending functionality in a useful way. |
- [Send a batch of emails](examples/batch/send-batch.ts) | ||
- [Send a batch of transactional emails](examples/batch/transactional-batch.ts) | ||
- [Send a batch of bulk emails](examples/batch/bulk-batch.ts) | ||
- [Send a batch of sandbox emails](examples/batch/sandbox-batch.ts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I see, these are the actual files in examples
folder
- [Send a batch of emails](examples/batch/send-batch.ts) | |
- [Send a batch of transactional emails](examples/batch/transactional-batch.ts) | |
- [Send a batch of bulk emails](examples/batch/bulk-batch.ts) | |
- [Send a batch of sandbox emails](examples/batch/sandbox-batch.ts) | |
- [Send a batch of transactional emails](examples/batch/transactional.ts) | |
- [Send a batch of bulk emails](examples/batch/bulk.ts) | |
- [Send a batch of sandbox emails](examples/batch/sandbox.ts) | |
- [Send a batch of emails from template](examples/batch/template.ts) |
}) | ||
.then(console.log) | ||
.catch(console.error); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}; | ||
|
||
try { | ||
await batchClient.batchSend(batchData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we raise incompatibility error much earlier, during initialization of MailtrapClient
?
const expectedResponseData = { | ||
success: true, | ||
message_ids: ["0c7fd939-02cf-11ed-88c2-0a58a9feac02"], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a correct schema of the Batch API response, please check https://api-docs.mailtrap.io/docs/mailtrap-api-docs/f96000c8de409-batch-send-email-including-templates
const expectedResponseData = { | ||
success: true, | ||
message_ids: ["0c7fd939-02cf-11ed-88c2-0a58a9feac02"], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual response schema: https://api-docs.mailtrap.io/docs/mailtrap-api-docs/48b526aa487b1-batch-send-email-including-templates
const responseData = { | ||
success: false, | ||
errors: ["from is required", "subject is required"], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This too doesn't match the way error response is returned from the Batch API
} | ||
|
||
export interface BatchSendRequest { | ||
base: InlineBatchSendBase | TemplateBatchSendBase; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
base
is not required, so I guess it should be base?
?
to: BaseAddress[]; | ||
cc?: BaseAddress[]; | ||
bcc?: BaseAddress[]; | ||
custom_variables?: Record<string, string>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's much more supported attributes on this level too, e.g. reply_to
, text
, html
, category
..., even template_uuid
.
From API docs:
base
- General properties of all emails in the batch. Each of them can be overridden in requests for individual emails.
requests
- The list of emails. Each of them requires recipients (one of to, cc, or bcc). Each email inherits properties from base but can override them.
template_uuid: string; // Required for template usage | ||
template_variables?: Record<string, string>; | ||
custom_variables?: Record<string, string>; | ||
category?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think category
is actually not allowed when using a template (since category is set on template already)
Motivation
Integrate Batch Sending API into current node.js SDK to support sending multiple emails in a single request, improving efficiency and reducing API calls.
Changes
batchSend
method toMailtrapClient
classHow to test
npm test
Summary by CodeRabbit
New Features
Documentation
Tests