Skip to content

Add Sending domains API#81

Merged
DagonWat merged 14 commits intomainfrom
MT-19854-sending-domains
Feb 3, 2026
Merged

Add Sending domains API#81
DagonWat merged 14 commits intomainfrom
MT-19854-sending-domains

Conversation

@DagonWat
Copy link
Contributor

@DagonWat DagonWat commented Jan 4, 2026

Motivation

Adding Sending Domains API for Ruby SDK

Changes

  • Adding full API scope

Summary by CodeRabbit

  • New Features

    • Added Sending Domains management: create, list, retrieve, delete, and send DNS setup instructions.
  • Documentation

    • Added Sending Domains API example and Ruby usage example to the README; minor formatting tweaks to Email API examples.
  • Tests

    • Added RSpec tests and VCR fixtures covering success and error scenarios for Sending Domains.
  • Chores

    • Updated CI configuration to ensure consistent dependency installation.

@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

📝 Walkthrough

Walkthrough

Adds Sending Domains feature: new SendingDomain struct, Mailtrap::SendingDomainsAPI (list/get/create/delete/send_setup_instructions), example script, require registration in lib/mailtrap.rb, RSpec tests, VCR fixtures, README and CHANGELOG updates, and a CI environment variable tweak.

Changes

Cohort / File(s) Summary
Core API & Model
lib/mailtrap/sending_domain.rb, lib/mailtrap/sending_domains_api.rb
Adds SendingDomain struct and Mailtrap::SendingDomainsAPI with response_class, supported_options, and methods: list, get, create, delete, send_setup_instructions.
Library integration & Docs
lib/mailtrap.rb, README.md, CHANGELOG.md
Requires the new SendingDomains API in lib/mailtrap.rb; updates README headings and adds Sending Domains example reference; prepends CHANGELOG entry "Add Sending Domains API".
Example
examples/sending_domains_api.rb
New example demonstrating create -> list -> get -> send_setup_instructions -> delete (no error handling).
Tests (spec)
spec/mailtrap/sending_domain_spec.rb, spec/mailtrap/sending_domains_api_spec.rb
Adds specs for SendingDomain and comprehensive tests for SendingDomainsAPI covering success and error cases (authorization, validation, not found).
VCR Fixtures
spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/*
Adds recorded HTTP fixtures for create (ok/error), list (ok/auth error), get (ok/not found), delete (ok/not found), send_setup_instructions (ok/not found).
CI Workflow
.github/workflows/main.yml
Sets BUNDLE_PATH: vendor/bundle in the GitHub Actions build job environment.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant API as Mailtrap::SendingDomainsAPI
  participant Server as mailtrap.io API

  Client->>API: create(sending_domain)
  API->>Server: POST /api/accounts/{account_id}/sending_domains
  Server-->>API: 200 OK (sending_domain JSON)
  API-->>Client: SendingDomain

  Client->>API: list()
  API->>Server: GET /api/accounts/{account_id}/sending_domains
  Server-->>API: 200 OK [sending_domain...]
  API-->>Client: [SendingDomain]

  Client->>API: get(id)
  API->>Server: GET /api/accounts/{account_id}/sending_domains/{id}
  Server-->>API: 200 OK (sending_domain JSON)
  API-->>Client: SendingDomain

  Client->>API: send_setup_instructions(id, email)
  API->>Server: POST /api/accounts/{account_id}/sending_domains/{id}/send_setup_instructions
  Server-->>API: 204 No Content
  API-->>Client: nil

  Client->>API: delete(id)
  API->>Server: DELETE /api/accounts/{account_id}/sending_domains/{id}
  Server-->>API: 204 No Content
  API-->>Client: nil
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • IgorDobryn
  • mklocek

Poem

🐰 I hopped through lines to add a domain so fine,
Structs and endpoints placed in tidy design,
Fixtures hum and tests replay each sign,
An example shows the create-to-delete line,
Rabbit nods — DNS ready, all set to shine.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description provides motivation and lists changes, but lacks critical details such as how to test and omits the images/GIFs section that is part of the template. Expand the 'Changes' section with specific implementation details, and add a 'How to test' section with testing instructions to align with the template structure.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarizes the main change: adding a Sending Domains API to the Ruby SDK, which aligns with the primary objective and all file changes in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch MT-19854-sending-domains

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

# @return nil
# @!macro api_errors
def send_setup_instructions(domain_id, email)
client.post("#{base_path}/#{domain_id}/send_setup_instructions", { email: email })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle the response

# @param email [String] The email for instructions
# @return nil
# @!macro api_errors
def send_setup_instructions(domain_id, email)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets use kwargs for email for consistency. see list(email: nil) in suppressions api

@i7an i7an marked this pull request as draft January 7, 2026 16:36
Base automatically changed from add-projects-api to main January 13, 2026 12:35
@DagonWat DagonWat marked this pull request as ready for review January 27, 2026 12:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@examples/sending_domains_api.rb`:
- Around line 23-25: The example calls the wrong method: replace the call to
sending_domains.clean with sending_domains.send_setup_instructions so it matches
the API spec; update the invocation that currently passes sending_domain.id and
'jonathan@mail.com' to call send_setup_instructions(sending_domain.id,
'jonathan@mail.com') and ensure the example comment remains accurate.
- Line 5: The example instantiates the wrong API class: replace the
instantiation of Mailtrap::InboxesAPI with Mailtrap::SendingDomainsAPI for the
sending_domains variable so it uses the correct client; update the line that
creates sending_domains (currently referencing Mailtrap::InboxesAPI) to use
Mailtrap::SendingDomainsAPI while keeping the account_id and client arguments
unchanged.

In
`@spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/returns_nil.yml`:
- Around line 6-8: The cassette contains a real developer email in the recorded
request body; replace the literal string "yahor.vaitsiakhouski@railsware.com" in
the fixture content
(spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/returns_nil.yml
— the body.string value) with an anonymized test address like "test@example.com"
to remove PII while preserving the fixture structure.

In
`@spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/when_sending_domain_does_not_exist/raises_not_found_error.yml`:
- Around line 6-8: The fixture contains a real email in the VCR cassette
body.string; update the value '{"email":"yahor.vaitsiakhouski@railsware.com"}'
to use a placeholder/test address (e.g. test@example.com) so the body.string
entry in the Mailtrap_SendingDomainsAPI cassette no longer exposes a real
developer email.
🧹 Nitpick comments (4)
lib/mailtrap/sending_domains_api.rb (1)

53-55: Consider validating the email parameter.

The email parameter is sent directly without validation. While the server will reject invalid input, adding client-side validation would provide a better developer experience with immediate feedback.

♻️ Optional: Add email presence validation
 def send_setup_instructions(domain_id, email)
+  raise ArgumentError, 'email is required' if email.nil? || email.to_s.strip.empty?
+
   client.post("#{base_path}/#{domain_id}/send_setup_instructions", { email: email })
 end
spec/mailtrap/sending_domain_spec.rb (2)

33-42: Remove unused project variable.

The project variable is defined but never used in the test. The actual test uses sending_domain defined in the context block. This appears to be leftover code, possibly from copy-paste.

🧹 Proposed fix to remove dead code
   describe '#to_h' do
     subject(:hash) { sending_domain.to_h }
 
-    let(:project) do
-      described_class.new(
-        id: '123456',
-        domain_name: 'My Sending Domain',
-        dns_verified: false,
-        compliance_status: 'pending',
-        created_at: '2024-01-01T00:00:00Z',
-        updated_at: '2024-01-02T00:00:00Z'
-      )
-    end
-
     context 'when some attributes are nil' do

44-64: Consider adding test coverage for to_h when all attributes are present.

The #to_h tests only cover the case when some attributes are nil. Consider adding a test case verifying that all attributes are included in the hash when none are nil.

💡 Suggested additional test case
context 'when all attributes are present' do
  let(:sending_domain) do
    described_class.new(
      id: '123456',
      domain_name: 'My Sending Domain',
      dns_verified: false,
      compliance_status: 'pending',
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-02T00:00:00Z'
    )
  end

  it 'returns a hash with all attributes' do
    expect(hash).to eq(
      id: '123456',
      domain_name: 'My Sending Domain',
      dns_verified: false,
      compliance_status: 'pending',
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-02T00:00:00Z'
    )
  end
end
spec/mailtrap/sending_domains_api_spec.rb (1)

125-127: Test description doesn't match the expectation.

The test is named 'returns deleted sending domain data' but it expects nil. Consider renaming to accurately describe the behavior, such as 'returns nil on successful deletion'.

📝 Proposed fix
-    it 'returns deleted sending domain data' do
+    it 'returns nil on successful deletion' do
       expect(delete).to be_nil
     end

Comment on lines 6 to 8
body:
encoding: UTF-8
string: '{"email":"yahor.vaitsiakhouski@railsware.com"}'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Same privacy concern: consider anonymizing the email address.

As noted in the other cassette, replace the developer email with a test email like test@example.com.

🤖 Prompt for AI Agents
In
`@spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/returns_nil.yml`
around lines 6 - 8, The cassette contains a real developer email in the recorded
request body; replace the literal string "yahor.vaitsiakhouski@railsware.com" in
the fixture content
(spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/returns_nil.yml
— the body.string value) with an anonymized test address like "test@example.com"
to remove PII while preserving the fixture structure.

Comment on lines 6 to 8
body:
encoding: UTF-8
string: '{"email":"yahor.vaitsiakhouski@railsware.com"}'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider anonymizing the email address in test fixtures.

The request body contains what appears to be a real developer email address. For privacy and to avoid potential spam, consider replacing it with a test/placeholder email like test@example.com.

🤖 Prompt for AI Agents
In
`@spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_send_setup_instructions/when_sending_domain_does_not_exist/raises_not_found_error.yml`
around lines 6 - 8, The fixture contains a real email in the VCR cassette
body.string; update the value '{"email":"yahor.vaitsiakhouski@railsware.com"}'
to use a placeholder/test address (e.g. test@example.com) so the body.string
entry in the Mailtrap_SendingDomainsAPI cassette no longer exposes a real
developer email.

@DagonWat DagonWat force-pushed the MT-19854-sending-domains branch from c5248e9 to 465d4f4 Compare January 27, 2026 17:03
@DagonWat DagonWat changed the base branch from main to coderabbit-config January 27, 2026 17:04
@DagonWat
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@DagonWat DagonWat requested review from IgorDobryn and i7an January 27, 2026 17:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@examples/sending_domains_api.rb`:
- Around line 23-25: Replace the real-looking example email passed to
sending_domains.send_setup_instructions (call site uses sending_domain.id and
'jonathan@mail.com') with a non-real placeholder such as 'user@example.com' or
'user@example.test' so the example stays safe and generic; update the argument
to the send_setup_instructions call accordingly.
- Around line 15-17: Add a public update wrapper to SendingDomainsAPI so
examples calling sending_domains.update(...) don't raise NoMethodError:
implement a method named update in the SendingDomainsAPI class that accepts
domain_id and options and delegates to the existing base_update(domain_id,
options), matching other API operation wrappers.

In `@lib/mailtrap/sending_domain.rb`:
- Around line 4-25: The SendingDomain DTO (Struct named SendingDomain) omits API
fields and silently drops data; add :dns_records, :dns_verified_at, and
:permissions to the Struct.new(...) declaration (keeping keyword_init: true) so
incoming API responses map fully to the DTO, and ensure the existing to_h method
continues to return the compacted hash of all attributes.

In
`@spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_get/when_sending_domain_does_not_exist/raises_not_found_error.yml`:
- Around line 5-70: The cassette contains sensitive account and trace/request
IDs (e.g. account "1111111" in the URI and X-Request-Id / X-Cloud-Trace-Context
/ Cf-Ray headers) — update your VCR configuration (e.g. in your VCR.configure
block in spec helper or spec/support/vcr.rb) to scrub these before recording:
add VCR.filter_sensitive_data('<ACCOUNT_ID>') { '1111111' } or a regex-based
replacement for account IDs in request URIs, and add filters or a before_record
hook to replace header values like X-Request-Id, X-Cloud-Trace-Context and
Cf-Ray with placeholders (e.g. '<X_REQUEST_ID>', '<TRACE_CONTEXT>', '<CF_RAY>');
re-run tests to regenerate the cassette with redacted values and commit the
updated fixture
(spec/fixtures/vcr_cassettes/Mailtrap_SendingDomainsAPI/_get/when_sending_domain_does_not_exist/raises_not_found_error.yml).
🧹 Nitpick comments (1)
spec/mailtrap/sending_domains_api_spec.rb (1)

9-27: Consider asserting additional mapped fields.

Once the DTO includes dns_records and permissions, it would be valuable to assert these in the list mapping so regressions are caught early.

@DagonWat DagonWat mentioned this pull request Jan 28, 2026
@i7an i7an force-pushed the coderabbit-config branch from 3b328ba to aae72b7 Compare January 28, 2026 14:40
Base automatically changed from coderabbit-config to main January 28, 2026 14:49
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@examples/sending_domains_api.rb`:
- Around line 15-17: Update the stale example comment after the call to
sending_domains.get so it reflects the actual created domain; replace
domain_name="proper.com" with domain_name="example.com" (or remove the example
output line) to match the created resource and avoid confusion—look for the
sending_domain variable and the sending_domains.get(sending_domain.id) call to
locate the line to change.

@DagonWat DagonWat force-pushed the MT-19854-sending-domains branch from 7c9b7b8 to eb251ad Compare February 3, 2026 16:53
@DagonWat DagonWat merged commit e15d638 into main Feb 3, 2026
4 checks passed
@DagonWat DagonWat deleted the MT-19854-sending-domains branch February 3, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants