-
Notifications
You must be signed in to change notification settings - Fork 6
Batch Sending Api #53
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
""" WalkthroughThis update introduces batch email sending capabilities to the Mailtrap Ruby client. It adds new methods for constructing batch emails, a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MailtrapClient
participant MailtrapAPI
User->>MailtrapClient: Initialize with api_key (and options)
User->>MailtrapClient: send_batch(base_mail, recipient_mails)
MailtrapClient->>MailtrapAPI: POST /api/batch with base_mail and recipient_mails
MailtrapAPI-->>MailtrapClient: Batch send response (success/errors)
MailtrapClient-->>User: Returns API response
Possibly related issues
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
✨ 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 (7)
examples/batch.rb (2)
10-15
: PreferBase64.strict_encode64
to avoid soft line-breaks
Base64.encode64
inserts\n
every 60 chars, which can mangle attachments or exceed Mailtrap’s size limits.- content: Base64.encode64('Attachment content'), # base64 encoded content or IO string + content: Base64.strict_encode64('Attachment content'), # single-line base64
24-24
: Use ENV for secrets in examplesHard-coding even a placeholder key encourages bad habits.
-client = Mailtrap::Client.new(api_key: 'your-api-key') +client = Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY'))lib/mailtrap/client.rb (2)
67-70
: Consider optimizing the validation logic.The
all?
method call could be more efficient by usingis_a?
with the method argument.- unless requests.all?(Mail::Base) - raise ArgumentError, - 'requests should be an array of Mailtrap::Mail::Base objects' - end + unless requests.all? { |request| request.is_a?(Mail::Base) } + raise ArgumentError, + 'requests should be an array of Mailtrap::Mail::Base objects' + end
31-55
: Note: Cyclomatic complexity increase due to additional validation.The pipeline failure indicates that the
initialize
method's cyclomatic complexity has exceeded the threshold (8/7). While the new validation on line 42 is necessary and follows the existing pattern, consider refactoring the initialization logic to reduce complexity.Consider extracting validation logic into a separate private method:
private def validate_configuration!(sandbox, bulk, inbox_id) raise ArgumentError, 'bulk mode is not applicable for sandbox API' if sandbox && bulk raise ArgumentError, 'inbox_id is required for sandbox API' if sandbox && inbox_id.nil? endWould you like me to generate a refactored version of the
initialize
method to address the complexity issue?spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/in_sandbox_mode/successfully_sends_a_batch_of_emails.yml (1)
8-10
: Use reserved example domains to avoid accidental trafficThe cassette payload embeds
[email protected]
and[email protected]
. While harmless, RFC 2606 recommendsexample.com
,example.org
, orexample.net
for documentation & fixtures to guarantee they never resolve in production.
Switching keeps us 100 % safe from stray e-mails if the cassette is ever replayed against live endpoints.spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_template/successfully_sends_a_batch_of_emails_with_template.yml (1)
8-9
: Consider RFC-2606 example domains in fixture addressesSame note as the sandbox cassette—replace real-looking domains (
[email protected]
,[email protected]
) withexample.com
variants to remove any chance of misrouting.spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/in_bulk_mode/successfully_sends_a_batch_of_emails.yml (1)
8-9
: Prefer placeholder domains reserved for docsFor consistency and zero-risk, substitute
[email protected]
/[email protected]
withexample.com
addresses in the recorded JSON string.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
examples/batch.rb
(1 hunks)lib/mailtrap/client.rb
(4 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/in_bulk_mode/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/in_sandbox_mode/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_API_errors/handles_API_errors.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_template/successfully_sends_a_batch_of_emails_with_template.yml
(1 hunks)spec/mailtrap/client_spec.rb
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
examples/batch.rb (2)
lib/mailtrap/action_mailer/delivery_method.rb (1)
client
(22-24)lib/mailtrap/client.rb (1)
send_batch
(64-76)
spec/mailtrap/client_spec.rb (2)
lib/mailtrap/action_mailer/delivery_method.rb (1)
client
(22-24)lib/mailtrap/client.rb (1)
send_batch
(64-76)
lib/mailtrap/client.rb (3)
lib/mailtrap/mail/from_template.rb (1)
as_json
(34-41)lib/mailtrap/mail/base.rb (1)
as_json
(39-55)lib/mailtrap/attachment.rb (1)
as_json
(19-27)
🪛 RuboCop (1.75.5)
spec/mailtrap/client_spec.rb
[convention] 303-303: Context description should match /^when\b/, /^with\b/, or /^without\b/.
(RSpec/ContextWording)
[convention] 320-320: Context description should match /^when\b/, /^with\b/, or /^without\b/.
(RSpec/ContextWording)
🪛 GitHub Actions: Ruby
spec/mailtrap/client_spec.rb
[error] 303-303: Rubocop RSpec/ContextWording: Context description should match /^when\b/, /^with\b/, or /^without\b/.
[error] 320-320: Rubocop RSpec/ContextWording: Context description should match /^when\b/, /^with\b/, or /^without\b/.
lib/mailtrap/client.rb
[error] 31-31: Rubocop Metrics/CyclomaticComplexity: Cyclomatic complexity for initialize is too high. [8/7]
🔇 Additional comments (6)
examples/batch.rb (1)
35-46
: Confirm per-recipient minimal payload is acceptedEach
Mailtrap::Mail::Base
inrequests
only setsto:
. If the API does not auto-inheritfrom
andsubject
frombase
, the call will reproduce the 422 validation error captured in the cassette ('from' is required
,'subject' is required
). Please verify this with a live call or spec.spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_API_errors/handles_API_errors.yml (1)
45-47
: Check double-quoted field names in error stringsThe response shows
''from'' is required
(double single-quotes). If the client surfaces these messages directly, they’ll look odd to users. Consider normalising or stripping surplus quotes when presenting validation errors.spec/mailtrap/client_spec.rb (1)
254-390
: Comprehensive test coverage for the batch sending feature.The test suite thoroughly covers various scenarios including bulk mode, sandbox mode, template usage, and error handling. The use of VCR cassettes for HTTP interaction recording is appropriate for integration testing.
lib/mailtrap/client.rb (3)
57-76
: Well-implemented batch sending method with proper validation.The implementation follows established patterns from the existing
send
method and includes comprehensive parameter validation. The use ofcompact_with_empty_arrays
for data cleaning is appropriate for API payloads.
146-148
: Consistent path generation following established patterns.The
batch_request_path
method properly mirrors the structure ofsend_path
with appropriate sandbox inbox ID handling.
215-217
: Useful utility method for API payload cleaning.The
compact_with_empty_arrays
method provides more thorough data cleaning than the standardcompact
method by also removing empty arrays, which is appropriate for API payloads.
lib/mailtrap/client.rb
Outdated
perform_request(:post, api_host, batch_request_path, { | ||
base: compact_with_empty_arrays(base.as_json), | ||
requests: | ||
}) |
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.
💡 Verification agent
🧩 Analysis chain
Verify the requests array transformation in the API payload.
The requests
array is passed directly without applying compact_with_empty_arrays
transformation. Ensure this is intentional and that individual request objects don't require the same cleaning as the base object.
🏁 Script executed:
#!/bin/bash
# Description: Check how requests array is handled in the codebase and verify the API expects raw request objects
# Search for batch API usage patterns and documentation
rg -A 10 -B 5 "batch.*api|api.*batch" --type md
# Look for any examples or documentation about batch request format
fd -e rb -e md | xargs rg -l "send_batch|batch.*request" | head -5 | xargs cat
Length of output: 20855
🏁 Script executed:
#!/bin/bash
# Inspect Mailtrap::Mail::Base class and its JSON serialization methods
rg -n "class Base" -A10 -B2 --type rb
Length of output: 66
🏁 Script executed:
#!/bin/bash
# Locate and inspect Mailtrap::Mail::Base#as_json implementation
files=$(fd -e rb base.rb)
for f in $files; do
echo "=== Inspecting $f ==="
rg -n "def as_json" -A20 -B2 "$f"
done
Length of output: 887
🏁 Script executed:
#!/bin/bash
# Display Mailtrap::Mail::Base to inspect defaults, initialize, and to_json
sed -n '1,200p' lib/mailtrap/mail/base.rb
Length of output: 2019
Clean request objects in batch payload
In send_batch
(lib/mailtrap/client.rb), we apply compact_with_empty_arrays
to the base JSON but pass each request raw. Since Mailtrap::Mail::Base#as_json
only uses Hash#compact
(removing nils but not empty arrays), any empty‐array fields (e.g. cc
, bcc
, attachments
, headers
, custom_variables
) will still be sent. To ensure consistency and avoid sending unwanted empty arrays, wrap each request in the same cleanup:
• File: lib/mailtrap/client.rb
Method: send_batch
Proposed change:
- perform_request(:post, api_host, batch_request_path, {
- base: compact_with_empty_arrays(base.as_json),
- requests:
- })
+ perform_request(:post, api_host, batch_request_path, {
+ base: compact_with_empty_arrays(base.as_json),
+ requests: requests.map { |req|
+ compact_with_empty_arrays(req.as_json)
+ }
+ })
If the API is fine with empty arrays in individual requests, please confirm this is intentional.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
perform_request(:post, api_host, batch_request_path, { | |
base: compact_with_empty_arrays(base.as_json), | |
requests: | |
}) | |
perform_request(:post, api_host, batch_request_path, { | |
base: compact_with_empty_arrays(base.as_json), | |
requests: requests.map { |req| | |
compact_with_empty_arrays(req.as_json) | |
} | |
}) |
🤖 Prompt for AI Agents
In lib/mailtrap/client.rb around lines 72 to 75, the send_batch method applies
compact_with_empty_arrays to the base JSON but sends each request without
cleaning empty arrays, causing unwanted empty array fields to be included. To
fix this, apply compact_with_empty_arrays to each request's as_json output
before including it in the requests array, ensuring all empty arrays are removed
consistently from both base and individual requests.
lib/mailtrap/client.rb
Outdated
@@ -53,6 +51,27 @@ def initialize( # rubocop:disable Metrics/ParameterLists | |||
@http_clients = {} | |||
end | |||
|
|||
# Sends a batch of emails | |||
# @param base [Mailtrap::Mail::Base] The base email configuration |
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.
According to API, base
parameter has less fields than Mailtrap::Mail::Base
. Please consider those options:
- Dedicated class for
base
e.g.Mailtrap::Batch::Base
- Raise
ArgumentError
ifbase
hasto
,cc
,bcc
@IgorDobryn what do you think?
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 would go with dedicated class, so in batch_send
method we won't need to do base.as_json.except('to', 'cc', 'bcc')
and having dedicated class would be more descriptive and straitforward
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 problem with the dedicated class is that you'd need two of them: one for regular emails, another for template emails. This creates potentially confusing hierarchy. Having said that, I agree with your point.
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.
Valid point. In that case, what about having dedicated serializer for Mailtrap::Mail::Base
handling batch case and raise errors there, like
perform_request(:post, api_host, batch_request_path, {
base: BaseBatchSerializer(base).to_h,
...,
})
class BaseBatchSerializer
def initialize(base)
raise ArgumentError unless base.to.empty?
end
def to_h
@base.as_json(%w[to cc, bcc])
end
ans as result we will have dedicated batch logic encapsulated somewhere
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.
Let's use separate class. Otherwise it will create misexpectations. I.e. when somebody constructs mail object with to/cc/bcc
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.
- please remove unnecessary requires
- update formatting making it similar to the existing example files
- make sure the example works
- the the example more unique by removing the comments that present in other files.
Mailtrap::Mail::Base.new( | ||
to: [ | ||
{ | ||
email: ENV.fetch('MAILTRAP_TO_EMAIL', '[email protected]'), |
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.
Why do you need ENV.fetch
here? Could you please explain the use case?
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.
Only to not expose own email address, as sender [email protected]
allows you to send only to account owner.
lib/mailtrap/client.rb
Outdated
end | ||
|
||
perform_request(:post, api_host, batch_request_path, { | ||
base: compact_with_empty_arrays(base.as_json), |
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.
- how about
base.as_json.except('to', 'cc', 'bcc')
? - why do you want to
compact
base json?
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.
why do you want to compact base json?
only to remove 'to', 'cc', 'bcc'
, which in case of base
has to be empty
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.
It wont be necessary once you add classes for base.
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: 2
♻️ Duplicate comments (1)
lib/mailtrap/client.rb (1)
72-75
: Apply consistent payload cleaning to request objects.Based on previous review feedback, the
requests
array should have the same empty array cleaning applied as the base object to ensure consistency and avoid sending unwanted empty fields.Apply the same
compact_with_empty_arrays
treatment to each request:perform_request(:post, api_host, batch_request_path, { base: base.as_json.except('to', 'cc', 'bcc'), - requests: + requests: requests.map { |req| compact_with_empty_arrays(req.as_json) } })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
examples/batch.rb
(1 hunks)lib/mailtrap.rb
(1 hunks)lib/mailtrap/client.rb
(4 hunks)lib/mailtrap/mail/base.rb
(1 hunks)lib/mailtrap/mail/batch/base.rb
(1 hunks)lib/mailtrap/mail/batch/from_template.rb
(1 hunks)lib/mailtrap/mail/from_template.rb
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_bulk_mode/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_sandbox_mode/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_API_errors/handles_API_errors.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_template/successfully_sends_a_batch_of_emails_with_template.yml
(1 hunks)spec/mailtrap/client_spec.rb
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- lib/mailtrap.rb
🚧 Files skipped from review as they are similar to previous changes (6)
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_template/successfully_sends_a_batch_of_emails_with_template.yml
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_API_errors/handles_API_errors.yml
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_bulk_mode/successfully_sends_a_batch_of_emails.yml
- spec/mailtrap/client_spec.rb
- examples/batch.rb
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_sandbox_mode/successfully_sends_a_batch_of_emails.yml
🧰 Additional context used
🧬 Code Graph Analysis (3)
lib/mailtrap/mail/from_template.rb (1)
lib/mailtrap/mail/base.rb (1)
to_batch
(84-96)
lib/mailtrap/mail/base.rb (1)
lib/mailtrap/mail/from_template.rb (1)
to_batch
(46-56)
lib/mailtrap/mail/batch/base.rb (3)
lib/mailtrap/mail/batch/from_template.rb (3)
attr_accessor
(13-51)initialize
(21-39)as_json
(43-50)lib/mailtrap/mail/base.rb (4)
attr_accessor
(7-97)initialize
(11-37)attachments
(64-66)as_json
(39-55)lib/mailtrap/client.rb (2)
attr_reader
(8-221)initialize
(31-52)
🔇 Additional comments (7)
lib/mailtrap/mail/base.rb (1)
81-96
: Well-implemented conversion method.The
to_batch
method correctly converts a single mail object to a batch mail object, preserving all relevant attributes while excluding recipient-specific fields that are handled separately in batch operations.lib/mailtrap/mail/from_template.rb (1)
43-56
: Consistent template-to-batch conversion.The method follows the same pattern as the base class
to_batch
method while correctly handling template-specific attributes. Good consistency across the codebase.lib/mailtrap/mail/batch/from_template.rb (1)
1-54
: Well-structured template batch class.The
FromTemplate
class properly extends the batch base functionality with template-specific attributes and maintains clean inheritance patterns. The implementation correctly handles template UUID and variables while preserving base batch behavior.lib/mailtrap/client.rb (3)
40-40
: Good refactoring of validation logic.Extracting argument validation into a dedicated method improves code organization and maintainability.
146-148
: Correct batch endpoint path construction.The batch request path correctly mirrors the send path pattern, including sandbox inbox ID when needed.
215-220
: Well-organized validation method.The extracted validation method consolidates all argument checks in a logical sequence and provides clear error messages.
lib/mailtrap/mail/batch/base.rb (1)
71-73
: Correct JSON serialization for batch base.The
as_json
method correctly excludes recipient fields (to
,cc
,bcc
) that are not relevant for batch base objects, as these are handled in individual requests.
lib/mailtrap/client.rb
Outdated
def send_batch(base, requests) | ||
unless base.is_a?(Mail::Batch::Base) | ||
raise ArgumentError, | ||
'base should be Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate object' | ||
end | ||
|
||
unless requests.all?(Mail::Base) | ||
raise ArgumentError, | ||
'requests should be an array of Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate objects' | ||
end |
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.
Fix request validation logic.
The validation on line 68 checks requests.all?(Mail::Base)
but should validate batch mail objects instead. Batch requests should be instances of Mail::Batch::Base
or its subclasses.
- unless requests.all?(Mail::Base)
+ unless requests.all?(Mail::Batch::Base)
raise ArgumentError,
'requests should be an array of Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate objects'
end
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
def send_batch(base, requests) | |
unless base.is_a?(Mail::Batch::Base) | |
raise ArgumentError, | |
'base should be Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate object' | |
end | |
unless requests.all?(Mail::Base) | |
raise ArgumentError, | |
'requests should be an array of Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate objects' | |
end | |
def send_batch(base, requests) | |
unless base.is_a?(Mail::Batch::Base) | |
raise ArgumentError, | |
'base should be Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate object' | |
end | |
unless requests.all?(Mail::Batch::Base) | |
raise ArgumentError, | |
'requests should be an array of Mailtrap::Mail::Batch::Base or Mailtrap::Mail::FromTemplate objects' | |
end | |
# ... rest of method ... | |
end |
🤖 Prompt for AI Agents
In lib/mailtrap/client.rb around lines 62 to 71, the validation for the requests
array incorrectly checks if all elements are instances of Mail::Base, but it
should verify that each element is an instance of Mail::Batch::Base or its
subclasses. Update the validation condition to check
requests.all?(Mail::Batch::Base) to correctly enforce the expected type for
batch mail objects.
lib/mailtrap/mail/batch/base.rb
Outdated
def initialize( # rubocop:disable Metrics/ParameterLists,Lint/MissingSuper | ||
from: nil, | ||
reply_to: nil, | ||
subject: nil, | ||
text: nil, | ||
html: nil, | ||
attachments: [], | ||
headers: {}, | ||
custom_variables: {}, | ||
category: nil | ||
) | ||
@from = from | ||
@reply_to = reply_to | ||
@subject = subject | ||
@text = text | ||
@html = html | ||
self.attachments = attachments | ||
@headers = headers | ||
@custom_variables = custom_variables | ||
@category = category | ||
end |
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.
🛠️ Refactor suggestion
Fix initialization to properly inherit from parent class.
The initializer disables Lint/MissingSuper
but doesn't call the parent's initialize
method. This could cause issues with inherited functionality, particularly attachment handling which relies on the parent's setter method.
- def initialize( # rubocop:disable Metrics/ParameterLists,Lint/MissingSuper
+ def initialize( # rubocop:disable Metrics/ParameterLists
from: nil,
reply_to: nil,
subject: nil,
text: nil,
html: nil,
attachments: [],
headers: {},
custom_variables: {},
category: nil
)
+ super(
+ from: from,
+ reply_to: reply_to,
+ subject: subject,
+ text: text,
+ html: html,
+ attachments: attachments,
+ headers: headers,
+ custom_variables: custom_variables,
+ category: category,
+ to: [], # Batch emails don't have direct recipients
+ cc: [],
+ bcc: []
+ )
- @from = from
- @reply_to = reply_to
- @subject = subject
- @text = text
- @html = html
- self.attachments = attachments
- @headers = headers
- @custom_variables = custom_variables
- @category = category
end
🤖 Prompt for AI Agents
In lib/mailtrap/mail/batch/base.rb lines 47 to 67, the initialize method
disables the Lint/MissingSuper cop but does not call super, which can break
inherited behavior. Fix this by adding a call to super with the appropriate
arguments at the start of the initialize method to ensure the parent class's
initialization logic, especially for attachments, is executed properly.
lib/mailtrap/mail/batch/base.rb
Outdated
# @param attachments [Array<Hash>] The attachments for the email. | ||
# @param headers [Hash] The custom headers for the email. | ||
# @param custom_variables [Hash] The custom variables for the email. | ||
class Base < Mailtrap::Mail::Base |
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 hierarchy should be reworked. I'll have to prepare a separate PR with the refactoring. Until that, this PR is on hold.
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.
@sarco3t I've merged hierarchy refactoring. There is no need to create a dedicated class for batch base. Feel free to use just Base
. No need to exclude anything from the to_json
output, simply rely on the server validations.
f93bbd3
to
7ecb29b
Compare
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: 0
♻️ Duplicate comments (2)
examples/batch.rb (2)
6-13
: Simplify configuration comments to make the example more unique.The configuration comments appear to duplicate content from other example files. Per previous feedback, these should be more concise and unique to the batch sending example.
Consider simplifying to focus on batch-specific configuration:
-# Set your API credentials as environment variables -# export MAILTRAP_API_KEY='your-api-key' -# -# client = Mailtrap::Client.new -# Bulk sending (@see https://help.mailtrap.io/article/113-sending-streams) -# client = Mailtrap::Client.new(bulk: true) -# Sandbox sending (@see https://help.mailtrap.io/article/109-getting-started-with-mailtrap-email-testing) -# client = Mailtrap::Client.new(sandbox: true, inbox_id: 12) +# For bulk or sandbox mode: +# client = Mailtrap::Client.new(bulk: true) +# client = Mailtrap::Client.new(sandbox: true, inbox_id: 12)
1-74
: Improve overall structure and formatting consistency.The example file should follow the formatting patterns of other example files to maintain consistency across the codebase. Consider adding a brief header comment and ensuring the structure aligns with existing examples.
Consider adding a header comment to explain the example:
+# frozen_string_literal: true + +# This example demonstrates batch email sending using the Mailtrap Ruby client. +# It shows two approaches: regular batch sending and template-based batch sending. + require 'mailtrap'
🧹 Nitpick comments (4)
examples/batch.rb (4)
30-32
: Update the hardcoded year to be more current.The hardcoded year 2022 in the custom variables makes the example feel outdated.
custom_variables: { - year: 2022 + year: 2024 }
35-46
: Use different email addresses to better demonstrate batch sending.Using the same email address for both recipients doesn't effectively showcase batch sending functionality. Different email addresses would provide a more realistic example.
Mailtrap::Mail::Base.new( to: [ - { email: '[email protected]', name: 'recipient1' } + { email: '[email protected]', name: 'recipient1' } ] ), Mailtrap::Mail::Base.new( to: [ - { email: '[email protected]', name: 'recipient2' } + { email: '[email protected]', name: 'recipient2' } ] )
48-48
: Make the comment more specific to differentiate from the first example.The comment is identical to line 15, which doesn't help users understand the difference between the two approaches.
-# Batch sending with Mailtrap::Mail::Base +# Batch sending with templates using Mailtrap::Mail::Base
58-73
: Improve recipient diversity and template variable clarity.Similar to the first example, using the same email address doesn't effectively demonstrate batch sending. Additionally, the template variables could be more meaningful.
Mailtrap::Mail::Base.new( to: [ - { email: '[email protected]', name: 'recipient1' } + { email: '[email protected]', name: 'recipient1' } ] ), Mailtrap::Mail::Base.new( to: [ - { email: '[email protected]', name: 'recipient2' } + { email: '[email protected]', name: 'recipient2' } ], template_variables: { - 'user_name' => 'John Doe 1', - 'user_name2' => 'John Doe 2' + 'user_name' => 'Jane Smith', + 'user_id' => '12345' } )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
examples/batch.rb
(1 hunks)lib/mailtrap/client.rb
(4 hunks)lib/mailtrap/mail/from_template.rb
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_bulk_mode/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_sandbox_mode/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_API_errors/handles_API_errors.yml
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_template/successfully_sends_a_batch_of_emails_with_template.yml
(1 hunks)spec/mailtrap/client_spec.rb
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- lib/mailtrap/mail/from_template.rb
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_bulk_mode/successfully_sends_a_batch_of_emails.yml
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_sandbox_mode/successfully_sends_a_batch_of_emails.yml
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_API_errors/handles_API_errors.yml
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/with_template/successfully_sends_a_batch_of_emails_with_template.yml
- spec/mailtrap/client_spec.rb
- lib/mailtrap/client.rb
🔇 Additional comments (1)
examples/batch.rb (1)
1-2
: Keep explicitrequire 'base64'
Our check confirmed that the Base64 module isn’t auto-loaded in Ruby, so the explicit
require 'base64'
on line 2 is necessary. No changes needed.
examples/batch.rb
Outdated
) | ||
|
||
client.send_batch(mail, [ | ||
Mailtrap::Mail::Base.new( |
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.
minor. the excessive indentation does not look pretty. how about reformatting it
client.send_batch(
mail,
[
Mailtrap::Mail::Base.new(
to: [
{ email: '[email protected]', name: 'recipient1' }
]
),
Mailtrap::Mail::Base.new(
to: [
{ email: '[email protected]', name: 'recipient2' }
]
)
]
)
Applies to other places as well.
examples/batch.rb
Outdated
# client = Mailtrap::Client.new(sandbox: true, inbox_id: 12) | ||
|
||
# Batch sending with Mailtrap::Mail::Base | ||
mail = Mailtrap::Mail::Base.new( |
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.
what do you think about creating helper methods for base similar to from_template
and from_content
:
batch_base_from_template
batch_base_from_content
def batch_base_from_content(
from: nil,
reply_to: nil,
attachments: [],
headers: {},
custom_variables: {},
subject: nil,
text: nil,
html: nil,
category: nil
)
Mailtrap::Mail::Base.new(
from:,
reply_to:,
attachments:,
headers:,
custom_variables:,
subject:,
text:,
html:,
category:
)
end
lib/mailtrap/client.rb
Outdated
def validate_args!(api_key, api_port, bulk, sandbox, inbox_id) | ||
raise ArgumentError, 'api_key is required' if api_key.nil? | ||
raise ArgumentError, 'api_port is required' if api_port.nil? | ||
raise ArgumentError, 'bulk mode is not applicable for sandbox API' if bulk && sandbox |
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.
We call it "bulk stream" in public articles.
https://help.mailtrap.io/article/113-sending-streams
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: 0
🧹 Nitpick comments (3)
lib/mailtrap/mail.rb (3)
125-131
: Fix the documentation example to reference the correct method name.The documentation example references
Mailtrap::Mail.from_template
instead ofMailtrap::Mail.batch_from_template
.Apply this diff to fix the documentation:
- # mail = Mailtrap::Mail.from_template( + # mail = Mailtrap::Mail.batch_from_template(
154-158
: Fix the documentation example to reference the correct method name.The documentation example references
Mailtrap::Mail.from_content
instead ofMailtrap::Mail.batch_from_content
.Apply this diff to fix the documentation:
- # mail = Mailtrap::Mail.from_content( + # mail = Mailtrap::Mail.batch_from_content(
132-150
: Consider refactoring to reduce code duplication.The batch methods have significant code duplication with their regular counterparts. Consider extracting the common logic into a private method or using a more DRY approach.
Here's a potential refactor approach:
def batch_from_template(**args) from_template(**args.except(:to, :cc, :bcc)) end def batch_from_content(**args) from_content(**args.except(:to, :cc, :bcc)) endOr create a private helper method:
private def build_mail_object(recipient_fields: true, **args) params = args.dup unless recipient_fields params.delete(:to) params.delete(:cc) params.delete(:bcc) end Mailtrap::Mail::Base.new(**params) endAlso applies to: 159-181
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
examples/batch.rb
(1 hunks)lib/mailtrap/client.rb
(4 hunks)lib/mailtrap/mail.rb
(1 hunks)spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_bulk_stream/successfully_sends_a_batch_of_emails.yml
(1 hunks)spec/mailtrap/client_spec.rb
(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- spec/fixtures/vcr_cassettes/Mailtrap_Client/_send_batch/when_in_bulk_stream/successfully_sends_a_batch_of_emails.yml
🚧 Files skipped from review as they are similar to previous changes (3)
- lib/mailtrap/client.rb
- examples/batch.rb
- spec/mailtrap/client_spec.rb
🧰 Additional context used
🧬 Code Graph Analysis (1)
lib/mailtrap/mail.rb (1)
lib/mailtrap/mail/base.rb (1)
attachments
(71-73)
🔇 Additional comments (1)
lib/mailtrap/mail.rb (1)
120-150
: Implementation looks correct for batch sending functionality.Both methods correctly omit recipient fields (
to
,cc
,bcc
) and pass the appropriate parameters toMailtrap::Mail::Base.new
, which aligns with the batch sending requirements described in the PR objectives.Also applies to: 152-181
…ing and error messages improvements
db29a61
to
6995844
Compare
lib/mailtrap/mail.rb
Outdated
# 'user_name' => 'John Doe' | ||
# } | ||
# ) | ||
def batch_from_template(**args) |
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 idea here is to provide argument level validation. Dont worry about the verbosity.
base
word is valuable as it better describes what you are building.
lib/mailtrap/client.rb
Outdated
# } | ||
# ) | ||
# | ||
# client.send_batch(mail, [ |
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.
- rewrite the example to use the helper methods
- change the formatting / indentation
lib/mailtrap/mail.rb
Outdated
@@ -117,6 +117,69 @@ def from_content( # rubocop:disable Metrics/ParameterLists | |||
) | |||
end | |||
|
|||
# Builds a mail object that will be sent using a pre-defined email |
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.
please update the documentation putting more emphasis on batch sending and the concept of base. Applies to the second base builder as well.
eeff166
to
fe7b7b8
Compare
Motivation
Integrate Batch Sending API to support sending multiple emails in a single request, improving efficiency and reducing API calls.
Changes
send_batch
toMailtrap::Client
How to test
or set yout api key
Summary by CodeRabbit
New Features
Bug Fixes
Tests