Skip to content

[PM-40167] feat: Update billing domain email copy - #8203

Open
cyprain-okeke wants to merge 3 commits into
mainfrom
billing/pm-40167/server-emails-billing-domain-license-subscription-seats-sponsorship-billing
Open

[PM-40167] feat: Update billing domain email copy#8203
cyprain-okeke wants to merge 3 commits into
mainfrom
billing/pm-40167/server-emails-billing-domain-license-subscription-seats-sponsorship-billing

Conversation

@cyprain-okeke

Copy link
Copy Markdown
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-40167

📔 Objective

Refreshes subject lines and body copy for nine billing-domain emails (HTML + text variants) per the PM-38898 terminology epic:

  • LicenseExpired — subject only ("License expired")
  • OrganizationSeatsMaxReached / OrganizationSmSeatsMaxReached / OrganizationSmServiceAccountsMaxReached — lowercased subjects; body now leads with the organization name (added OrganizationName to the view models via CoreHelpers.SanitizeForEmail)
  • Provider/ProviderUpdatePaymentMethod — "Your Bitwarden organization…" copy and Admin Console navigation wording
  • FamiliesForEnterprise offer (new + existing account), sponsorship reverting, and removed-from-family emails — "Sponsored Families Plan" terminology, updated subjects and body copy

Additional changes riding along:

  • Removed the now-unused offerAcceptanceDate parameter from SendFamiliesForEnterpriseRemoveSponsorshipsEmailAsync (interface, both implementations, caller, tests)
  • Sponsor org name in offer emails now passes through CoreHelpers.SanitizeForEmail, matching the sibling sponsorship-removal email
  • Fixed the sponsorship-reverting text template referencing a nonexistent {{Date}} property (previously rendered a blank date); both variants now use {{date ExpirationDate 'MMMM dd, yyyy'}}
  • Unit tests added for all changed emails, rendering the real embedded templates and asserting subjects, body copy (HTML + text), retained CTA links/disclaimers, and date formatting

Notes for reviewers:

  • The ticket description still says the copy is gated behind the vfo1-foundation flag as duplicate V2 templates — that's stale. Nick Krantz confirmed the copy ships in-place with no flag; the ticket AC predates that decision.
  • The removed-sponsorship email keeps the "Or click the following link: {subscription URL}" line per the ticket's copy spec. In the HTML variant this renders the raw URL as visible link text (previously anchored behind "Subscription page") and the "Or" no longer has an antecedent — flagged to product as a copy-deck question rather than deviating from the specified copy here.

Refreshes subject lines and body copy for nine billing emails
(license, seat limits, provider payment method, and Families for
Enterprise sponsorship) per the PM-38898 terminology epic. Copy
ships in-place with no feature flag per product decision.

Also removes the unused offerAcceptanceDate parameter from
SendFamiliesForEnterpriseRemoveSponsorshipsEmailAsync, sanitizes
the sponsor org name in offer emails, and fixes the sponsorship
reverting text template referencing a nonexistent {{Date}} property.
@cyprain-okeke cyprain-okeke added the ai-review Request a Claude code review label Aug 13, 2026
@github-actions github-actions Bot added the platform-community Touches a Platform-stewarded area with limited team familiarity label Aug 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

ℹ️ Limited Platform familiarity

This PR touches a platform-community area. The Platform team owns this code but does not actively develop it, so a Platform review here may be less authoritative than usual.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed copy updates across nine billing-domain email templates (HTML + text), the OrganizationName additions to the seat/machine-account view models, subject line changes in HandlebarsMailService, and the removal of the offerAcceptanceDate parameter from SendFamiliesForEnterpriseRemoveSponsorshipsEmailAsync. Verified the signature change is propagated to both IMailService implementations and the sole caller, that all three OrganizationSeatsMaxReached*/OrganizationServiceAccountsMaxReached* view model construction sites now populate OrganizationName, and that no stale references to OfferAcceptanceDate, {{Date}}, or the old subject strings remain anywhere in the repo. Confirmed {{date ExpirationDate 'MMMM dd, yyyy'}} and {{{link SubscriptionUrl true}}} match the registered Handlebars helper signatures, and that new view model values pass through CoreHelpers.SanitizeForEmail and render via escaping stashes, consistent with sibling templates. No security, correctness, or breaking-change issues were identified.

Code Review Details

No findings at or above the reporting threshold.

Notes considered and intentionally not raised as findings:

  • The dangling "Or click the following link:" line in FamiliesForEnterpriseRemovedFromFamilyUser (both variants) is already documented in the PR description as an open copy-deck question with product.
  • FreeFamiliesForEnterprisePolicyEventHandler passes OrganizationSponsorship.FriendlyName into the email parameter, and SanitizeForEmail is applied to a nullable organization?.Name — both are pre-existing behaviors that this PR does not introduce or worsen.
  • Removing org.ValidUntil!.Value from the handler eliminates a potential InvalidOperationException on sponsorships with a null ValidUntil; no other logic depended on it.

…n-license-subscription-seats-sponsorship-billing
@cyprain-okeke cyprain-okeke added the t:feature Change Type - Feature Development label Aug 13, 2026
@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.33%. Comparing base (5358a2f) to head (e60cf96).

Additional details and impacted files
@@            Coverage Diff            @@
##           main    #8203       +/-   ##
=========================================
+ Coverage      0   63.33%   +63.33%     
=========================================
  Files         0     2381     +2381     
  Lines         0   103759   +103759     
  Branches      0     9385     +9385     
=========================================
+ Hits          0    65717    +65717     
- Misses        0    35810    +35810     
- Partials      0     2232     +2232     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cyprain-okeke
cyprain-okeke marked this pull request as ready for review August 14, 2026 07:54
@cyprain-okeke
cyprain-okeke requested review from a team as code owners August 14, 2026 07:54
…n-license-subscription-seats-sponsorship-billing

@djsmith85 djsmith85 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving for platform

@djsmith85
djsmith85 removed the request for review from dani-garcia August 14, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review platform-community Touches a Platform-stewarded area with limited team familiarity t:feature Change Type - Feature Development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants