MT-22401: Add Email Campaigns API - #250
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
💤 Files with no reviewable changes (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR adds email campaign contracts, models, validation, REST resources, lifecycle operations, statistics retrieval, integration and unit tests, and a runnable console example. ChangesEmail campaigns API
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Application
participant MailtrapClient
participant EmailCampaignResource
participant MailtrapAPI
Application->>MailtrapClient: resolve email campaign resource
MailtrapClient-->>Application: return resource
Application->>EmailCampaignResource: execute campaign operation
EmailCampaignResource->>MailtrapAPI: send REST request
MailtrapAPI-->>EmailCampaignResource: return campaign or statistics data
EmailCampaignResource-->>Application: return mapped result
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignCollectionResourceTests.cs (1)
19-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover collection operations, not only construction.
Add tests for
GetAllwithtoken,per_page, andsearch, plusCreaterequest/response mapping. These are the main behaviors introduced byEmailCampaignCollectionResourceand are currently untested.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignCollectionResourceTests.cs` around lines 19 - 58, The EmailCampaignCollectionResource tests currently cover only construction and URI behavior; add coverage for its collection operations. Extend the test fixture around CreateResource to verify GetAll passes token, per_page, and search parameters correctly, and verify Create maps the request to the command and maps the response back to the expected resource model.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/Mailtrap.Example.EmailCampaigns/EmailCampaigns.cs`:
- Around line 100-115: Change the EmailCampaigns example so
campaignResource.Start is not executed by default; place it behind an explicit
opt-in snippet or command. When opted in and a campaign is started, call
campaignResource.Terminate before cleanup, while preserving stats behavior as
appropriate. Verify the equivalent Mailtrap app example still accurately
reflects this public lifecycle and update it if needed.
- Around line 107-111: Update the GetStats call in the campaign example to use a
statistics window derived from the current execution time, covering the campaign
actions created during that run, instead of fixed May 2026 dates. Keep the
existing stats logging unchanged.
---
Nitpick comments:
In
`@tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignCollectionResourceTests.cs`:
- Around line 19-58: The EmailCampaignCollectionResource tests currently cover
only construction and URI behavior; add coverage for its collection operations.
Extend the test fixture around CreateResource to verify GetAll passes token,
per_page, and search parameters correctly, and verify Create maps the request to
the command and maps the response back to the expected resource model.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e005b093-9047-44b0-9f09-14a1c4114666
📒 Files selected for processing (61)
Mailtrap.slnREADME.mdexamples/Mailtrap.Example.EmailCampaigns/EmailCampaigns.csexamples/Mailtrap.Example.EmailCampaigns/Mailtrap.Example.EmailCampaigns.csprojexamples/Mailtrap.Example.EmailCampaigns/Properties/launchSettings.jsonexamples/Mailtrap.Example.EmailCampaigns/appsettings.jsonsrc/Mailtrap.Abstractions/Accounts/IAccountResource.cssrc/Mailtrap.Abstractions/EmailCampaigns/IEmailCampaignCollectionResource.cssrc/Mailtrap.Abstractions/EmailCampaigns/IEmailCampaignResource.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/CampaignState.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/DeliveryMode.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaign.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignDeliveryOptions.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignList.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignListFilter.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStateError.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStateMetadata.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStats.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStatsFilter.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignTemplate.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignType.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignsPagination.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/ReplyTo.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/CreateEmailCampaignRequest.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/EmailCampaignTemplateAttributes.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/ScheduleEmailCampaignRequest.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/UpdateEmailCampaignRequest.cssrc/Mailtrap.Abstractions/EmailCampaigns/Validators/CreateEmailCampaignRequestValidator.cssrc/Mailtrap.Abstractions/EmailCampaigns/Validators/ScheduleEmailCampaignRequestValidator.cssrc/Mailtrap.Abstractions/EmailCampaigns/Validators/UpdateEmailCampaignRequestValidator.cssrc/Mailtrap.Abstractions/GlobalSuppressions.cssrc/Mailtrap.Abstractions/GlobalUsings.cssrc/Mailtrap/Accounts/AccountResource.cssrc/Mailtrap/Core/Constants/UrlSegments.cssrc/Mailtrap/EmailCampaigns/EmailCampaignCollectionResource.cssrc/Mailtrap/EmailCampaigns/EmailCampaignResource.cssrc/Mailtrap/EmailCampaigns/Responses/EmailCampaignListResponseDto.cssrc/Mailtrap/EmailCampaigns/Responses/EmailCampaignResponseDto.cssrc/Mailtrap/EmailCampaigns/Responses/EmailCampaignStatsResponseDto.cssrc/Mailtrap/GlobalUsings.cstests/Mailtrap.IntegrationTests/EmailCampaigns/Create_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Create_Unprocessable.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/EmailCampaignIntegrationTests.cstests/Mailtrap.IntegrationTests/EmailCampaigns/GetAll_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/GetDetails_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/GetStats_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Schedule_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Start_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Start_Unprocessable.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Terminate_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Update_Success.jsontests/Mailtrap.IntegrationTests/GlobalUsings.cstests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cstests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignCollectionResourceTests.cstests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignRequestValidatorTests.cstests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignResourceTests.cstests/Mailtrap.UnitTests/EmailCampaigns/Requests/CreateEmailCampaignRequestTests.cstests/Mailtrap.UnitTests/EmailCampaigns/Requests/ScheduleEmailCampaignRequestTests.cstests/Mailtrap.UnitTests/EmailCampaigns/Requests/UpdateEmailCampaignRequestTests.cstests/Mailtrap.UnitTests/GlobalUsings.cstests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs
|
Addressed CodeRabbit review feedback in 8fc13fc:
Verified: |
8fc13fc to
711af62
Compare
Decisions: - Request bodies are flat per the current OpenAPI contract: the Create/Update request DTO envelopes and their ToDto() extensions are deleted; the public requests are posted directly. - Single-object and stats responses unwrap the data envelope via internal EmailCampaignResponseDto/EmailCampaignStatsResponseDto (Webhooks precedent). - Delete returns Task via RestResource.DeleteWithStatusCodeResult() to match the API's 204 No Content. - Five lifecycle endpoints (start/schedule/cancel/terminate/reset) POST to sub-segments via RestResourceCommandFactory.CreatePost; ScheduleEmailCampaignRequest carries a DateTimeOffset validated as future and at most 1 month ahead. - DomainId is a positive int64 sending domain ID (as returned by the Sending Domains endpoints) validated with NotNull + GreaterThan(0); a TemplateAttributes.Subject required-on-create rule replaces the dropped Scheduled/ScheduledFor rules.
Decisions: - Gate Start() behind MAILTRAP_START_CAMPAIGN=true so the example does not send real emails by default; Terminate() the campaign before cleanup when opted in - Derive the GetStats window from the current run time (last 7 days) instead of hardcoded May 2026 dates - Keep the date formatter in a partial Program member to stay under the CA1506 coupling limit for the top-level statements
711af62 to
027e001
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignRequestValidatorTests.cs (1)
158-164: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest the one-month boundary.
This test only rejects a date two months ahead. A validator that accepts dates more than one month ahead, but less than two months ahead, will still pass.
Add a case such as
DateTimeOffset.UtcNow.AddMonths(1).AddDays(1). Assert that it fails validation.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignRequestValidatorTests.cs` around lines 158 - 164, Update Schedule_WithDatetimeMoreThanOneMonthAhead_ShouldFail to use a date just beyond the one-month limit, such as DateTimeOffset.UtcNow.AddMonths(1).AddDays(1), and retain the assertion that the Datetime field has a validation error. This must verify the one-month boundary rather than only rejecting dates two months ahead.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignRequestValidatorTests.cs`:
- Around line 158-164: Update
Schedule_WithDatetimeMoreThanOneMonthAhead_ShouldFail to use a date just beyond
the one-month limit, such as DateTimeOffset.UtcNow.AddMonths(1).AddDays(1), and
retain the assertion that the Datetime field has a validation error. This must
verify the one-month boundary rather than only rejecting dates two months ahead.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f175993c-5cca-4fc9-8a56-ef627601e810
📒 Files selected for processing (60)
Mailtrap.slnREADME.mdexamples/Mailtrap.Example.EmailCampaigns/EmailCampaigns.csexamples/Mailtrap.Example.EmailCampaigns/Mailtrap.Example.EmailCampaigns.csprojexamples/Mailtrap.Example.EmailCampaigns/Properties/launchSettings.jsonexamples/Mailtrap.Example.EmailCampaigns/appsettings.jsonsrc/Mailtrap.Abstractions/Accounts/IAccountResource.cssrc/Mailtrap.Abstractions/EmailCampaigns/IEmailCampaignCollectionResource.cssrc/Mailtrap.Abstractions/EmailCampaigns/IEmailCampaignResource.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/CampaignState.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/DeliveryMode.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaign.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignDeliveryOptions.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignList.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignListFilter.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStateError.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStateMetadata.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStats.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStatsFilter.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignTemplate.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignsPagination.cssrc/Mailtrap.Abstractions/EmailCampaigns/Models/ReplyTo.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/CreateEmailCampaignRequest.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/EmailCampaignTemplateAttributes.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/ScheduleEmailCampaignRequest.cssrc/Mailtrap.Abstractions/EmailCampaigns/Requests/UpdateEmailCampaignRequest.cssrc/Mailtrap.Abstractions/EmailCampaigns/Validators/CreateEmailCampaignRequestValidator.cssrc/Mailtrap.Abstractions/EmailCampaigns/Validators/ScheduleEmailCampaignRequestValidator.cssrc/Mailtrap.Abstractions/EmailCampaigns/Validators/UpdateEmailCampaignRequestValidator.cssrc/Mailtrap.Abstractions/GlobalSuppressions.cssrc/Mailtrap.Abstractions/GlobalUsings.cssrc/Mailtrap/Accounts/AccountResource.cssrc/Mailtrap/Core/Constants/UrlSegments.cssrc/Mailtrap/EmailCampaigns/EmailCampaignCollectionResource.cssrc/Mailtrap/EmailCampaigns/EmailCampaignResource.cssrc/Mailtrap/EmailCampaigns/Responses/EmailCampaignListResponseDto.cssrc/Mailtrap/EmailCampaigns/Responses/EmailCampaignResponseDto.cssrc/Mailtrap/EmailCampaigns/Responses/EmailCampaignStatsResponseDto.cssrc/Mailtrap/GlobalUsings.cstests/Mailtrap.IntegrationTests/EmailCampaigns/Create_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Create_Unprocessable.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/EmailCampaignIntegrationTests.cstests/Mailtrap.IntegrationTests/EmailCampaigns/GetAll_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/GetDetails_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/GetStats_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Schedule_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Start_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Start_Unprocessable.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Terminate_Success.jsontests/Mailtrap.IntegrationTests/EmailCampaigns/Update_Success.jsontests/Mailtrap.IntegrationTests/GlobalUsings.cstests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cstests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignCollectionResourceTests.cstests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignRequestValidatorTests.cstests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignResourceTests.cstests/Mailtrap.UnitTests/EmailCampaigns/Requests/CreateEmailCampaignRequestTests.cstests/Mailtrap.UnitTests/EmailCampaigns/Requests/ScheduleEmailCampaignRequestTests.cstests/Mailtrap.UnitTests/EmailCampaigns/Requests/UpdateEmailCampaignRequestTests.cstests/Mailtrap.UnitTests/GlobalUsings.cstests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs
🚧 Files skipped from review as they are similar to previous changes (53)
- examples/Mailtrap.Example.EmailCampaigns/Mailtrap.Example.EmailCampaigns.csproj
- src/Mailtrap/GlobalUsings.cs
- README.md
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Terminate_Success.json
- src/Mailtrap.Abstractions/EmailCampaigns/Models/DeliveryMode.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStatsFilter.cs
- tests/Mailtrap.UnitTests/GlobalUsings.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignDeliveryOptions.cs
- src/Mailtrap/EmailCampaigns/Responses/EmailCampaignListResponseDto.cs
- src/Mailtrap/EmailCampaigns/Responses/EmailCampaignStatsResponseDto.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Schedule_Success.json
- src/Mailtrap.Abstractions/EmailCampaigns/Validators/ScheduleEmailCampaignRequestValidator.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Create_Success.json
- tests/Mailtrap.IntegrationTests/EmailCampaigns/GetStats_Success.json
- tests/Mailtrap.IntegrationTests/GlobalUsings.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Start_Unprocessable.json
- examples/Mailtrap.Example.EmailCampaigns/appsettings.json
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStateError.cs
- src/Mailtrap.Abstractions/Accounts/IAccountResource.cs
- src/Mailtrap.Abstractions/EmailCampaigns/IEmailCampaignCollectionResource.cs
- examples/Mailtrap.Example.EmailCampaigns/Properties/launchSettings.json
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignList.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Start_Success.json
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignsPagination.cs
- src/Mailtrap.Abstractions/EmailCampaigns/IEmailCampaignResource.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/GetAll_Success.json
- src/Mailtrap.Abstractions/EmailCampaigns/Requests/UpdateEmailCampaignRequest.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/GetDetails_Success.json
- tests/Mailtrap.UnitTests/EmailCampaigns/Requests/CreateEmailCampaignRequestTests.cs
- src/Mailtrap/EmailCampaigns/Responses/EmailCampaignResponseDto.cs
- tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Create_Unprocessable.json
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignTemplate.cs
- tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignCollectionResourceTests.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/ReplyTo.cs
- tests/Mailtrap.UnitTests/EmailCampaigns/EmailCampaignResourceTests.cs
- tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs
- examples/Mailtrap.Example.EmailCampaigns/EmailCampaigns.cs
- src/Mailtrap/Core/Constants/UrlSegments.cs
- tests/Mailtrap.UnitTests/EmailCampaigns/Requests/ScheduleEmailCampaignRequestTests.cs
- Mailtrap.sln
- src/Mailtrap.Abstractions/EmailCampaigns/Requests/EmailCampaignTemplateAttributes.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/CampaignState.cs
- src/Mailtrap.Abstractions/GlobalUsings.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStats.cs
- src/Mailtrap/Accounts/AccountResource.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignListFilter.cs
- src/Mailtrap/EmailCampaigns/EmailCampaignCollectionResource.cs
- src/Mailtrap.Abstractions/GlobalSuppressions.cs
- src/Mailtrap.Abstractions/EmailCampaigns/Models/EmailCampaignStateMetadata.cs
- tests/Mailtrap.IntegrationTests/EmailCampaigns/Update_Success.json
- tests/Mailtrap.IntegrationTests/EmailCampaigns/EmailCampaignIntegrationTests.cs
- src/Mailtrap/EmailCampaigns/EmailCampaignResource.cs
Decisions: - Nothing in the payload is campaign-specific, so move it to Core/Models as Pagination for the next paginated resource to reuse - Core.Models is already a global using, so no call site needs a new import
piobeny
left a comment
There was a problem hiding this comment.
We should make decision on the scoping, other then that LGTM
Decisions: - Account(1).EmailCampaigns() and Account(2).EmailCampaigns() hit the same token-scoped path and returned identical results, which is misleading - Follow the Inbound precedent: token-scoped resources hang off IMailtrapClient - Drop assertions and comments about the account-scoped campaigns path; it does not exist, so there is nothing to guard against
Decisions: - The backend allows deleting only a campaign in the draft state (EmailCampaign#validate_soft_delete), not merely a non-sending one - Examples deleted a campaign after start/terminate, which would 422; a started campaign can never return to draft, so they now delete a fresh draft
Decisions: - Campaigns are an Email Marketing feature, not contact management or Email API/SMTP, so they were filed under the wrong heading
…-shaped errors Decisions: - Campaign rates were float while the existing SendingStats uses double; one numeric type per concept avoids surprising precision differences - The lifecycle 422 body is oneOf string or array of strings per the spec, but only the string branch was covered
Motivation
MT-22401
Port the Email Campaigns public API (MT-21113) to the .NET SDK.
Changes
client.Account(id).EmailCampaigns()/.EmailCampaign(id)covering the full contract: list (token/per_page/search filter), get, create, update, delete (204 →Task), the five lifecycle actions (Start,Schedule,Cancel,Terminate,Reset), andGetStatswith an optional date windowdata-envelope response DTOs (Webhooks precedent), int64DomainId/DomainNamematching the Sending Domains endpoints,Rapid/Gradualdelivery modes, 10-valueCampaignState, audience id lists, template attributes withBodyHtml/BodyText/MergeTags, per-recipient state-metadata errorsTemplateAttributes.SubjectandFromLocalPartrequired on create;Scheduledatetime must be in the future and ≤1 month aheadHow to test
Mailtrap.Example.EmailCampaignswith a real API token and a verified sending domain — create a draft, update design/audience, schedule + cancel, fetch stats, deleteCancelon a draft) surfaces the API error messageNote: the endpoint is token-scoped; the resource hangs off
Account(...)for API-shape consistency but the URI is/api/email_campaigns(asserted by tests).Summary by CodeRabbit