tc-mail-scheduler
.NET 8 API and MassTransit consumers that schedule and send lifecycle customer emails (thank-you-for-booking, have-a-nice-time, welcome-home, TC-score reminders), triggered daily by an EventBridge Lambda.
Health score
0 to 100 across seven weighted factors; nothing is hidden. Green is 75 and above, amber 50 to 74, red below 50. How scoring works.
Facts
| Languages | csharp, typescript |
| Frameworks | ASP.NET Core 8, MassTransit 8, MediatR, AWS Lambda |
| Runtimes | .NET 8, nodejs 20 |
| Tests / CI | good / CI in place |
| Last commit | 2026-06-01 |
| Owner | Owner unknown (mapping to be curated) |
| Domain | Customer communications (system generated; curate in repo-owners.json to override) |
| Product area | Shared platform |
| Hosted | AWS Deployed to AWS
|
| Releases | 0 release pipeline(s): |
| Integration | rest, masstransit, sqs |
| Source | Open in Azure DevOps |
Dependencies in context
Entanglement
loose No binding mechanisms apply: this system needs no untangling work.
Migration playbooks
Generated from this repo's assessment data: what is feasible, what blocks it, and the steps in order. Ratings: green means actionable now, amber means sequence other work first, red means blocked, grey means not applicable.
ZDD adoption
No excuseNothing technical is holding this repo on the three-week release. It either already deploys without downtime (AWS) or is a modern, well-tested service the automated stealth path can carry today. Already deploys as a container to AWS, which releases without downtime today. Separating it from the three-week release is a process decision, not a technical one.
- 2 system(s) depend on this repo; during a rolling deploy they will talk to old and new versions at once, so responses must stay compatible
- Serialized state or messages in flight (Redis or queues): new code must deserialize objects written by the previous version
- Adopt the four-stage discipline from the ZDD engineering standard: pre-deployment compatibility, deployment, feature activation behind a flag, post-release cleanup.
- Make every change dual-version safe: backwards-compatible APIs (new major version for breaking wire changes), expand and contract for any schema change, and consumers tolerant of unknown fields.
- Audit serialized data: anything in Redis, queues or shared caches must deserialize cleanly across adjacent versions.
- Wrap behaviour changes in feature flags so code deploys dark and release becomes a business decision, not a deployment event.
- Use ECS rolling deployments with health checks gating traffic, and take this service off the three-week release train.
- Verify with area-scoped regression rather than the whole-platform cycle, and watch error rates after rollout with automated rollback on alert.
SQL Server exit
Not applicableNo SQL Server dependency is recorded for this repo. Nothing to migrate.
Containerisation
Already containerisedIts pipelines already build containers and deploy to AWS. Nothing to do here.
Recommended actions
No specific actions for this repo. It either needs only normal maintenance, or its work is covered by an estate-level action. See the full programme.
Assessment notes
tc-mail-scheduler
Purpose
Customer-experience (CX) mail scheduler: consumes contact, person-configuration, TC-score and transactional-email-activity events off the bus to build a MongoDB schedule of lifecycle emails per customer (thank-you-for-booking, have-a-nice-time, welcome-home, TC-score reminder — configured per company UK/IE/NL/BE/ZA/AE in appsettings), then sends batches via TC.Mail.Composer commands when a SendScheduledEmailsCommand arrives. A TypeScript Lambda (tc-mail-scheduler-send-scheduled-emails) is fired by EventBridge and publishes that command as a hand-rolled MassTransit envelope to an SNS topic.
Tech stack
C# on .NET 8 (API, Scheduler core, Abstractions, Contracts, Persistence, PublicTravelCounsellors client projects): MediatR, MassTransit 8.5 over TC.MassTransit.AmazonSQS, Mapster, FluentResults, FluentValidation, Polly, MongoDB.Driver 3.6 via TC.ConnectionBroker.Mongo, TC.Cognito.Auth.Client, Swashbuckle, Nerdbank.GitVersioning. The Lambda is TypeScript 4.9/webpack/Jest using the shared @tc/tc-aws-lambda-core package.
Deployment
No classic release pipelines (release_count 0) — deployment is YAML-only. azure-pipeline.yaml uses the shared InternalOSS/azure-pipelines-templates ci.yml (SDK 8.x), builds the TC.Mail.Scheduler.Api container (namespace cx) and deploys via Terraform tfvars into aws-cx-tc-apps ECS. build-lambdas.yaml builds/deploys the Node 20 Lambda to the tc-cx-function-artifacts bucket; deploy-mongodb.yaml runs TC.ScriptRunner.Mongo migrations. Build pipelines: tc-mail-scheduler, tc-mail-scheduler-lambdas.
Dependencies
Internal packages: TC.ConnectionBroker.* (tc-connectionbroker), TC.Mail.Composer.Contracts (tc-mail-composer, the send path), TC.Mail.Tracked.Contracts (tc-mail-tracked, transactional email activity events), Phenix.Contact.Contracts (phenix-contact-api, contact/person-configuration events), TC.Public.TravelCounsellors.Contracts plus an HTTP client to the public TC site API (tc-public-travelcounsellors, TC-score data), TC.Diagnostics.HealthChecks (tc-diagnostics-portal). External: AWS (SNS/SQS/EventBridge/Lambda/ECS), Cognito service auth.
Data stores
Owns the MailScheduler MongoDB database (scheduled emails, preferences, lease/batch state; migrations via Mongo script-runner). No SQL Server.
Integration points
Inbound REST (ScheduledEmails and ScheduledEmailPreferences controllers, Swagger); MassTransit over Amazon SQS/SNS for ten consumers (contact updated/deleted, person configuration, TC-score saved, transactional email activity, send/resend/create-custom commands); outbound send via mail-composer contracts.
Code health
Good: 208 xUnit facts/theories across API and core unit-test projects plus a shared fixtures project, coverlet coverage, analyzers (SonarAnalyzer, SecurityCodeScan, NetAnalyzers) enforced via Directory.Build.props. Jest configured for the Lambda (--passWithNoTests). Actively maintained (last commit 2026-06-01). README is untouched Azure DevOps boilerplate.
Modernisation risks
Low. Modern .NET 8 on ECS with YAML CI, tests and Mongo migrations. Residual concerns: the Lambda hand-crafts MassTransit message envelopes (mass-transit-message.ts), so envelope-format or contract-namespace drift would silently break scheduling; email-programme configuration lives in large per-environment appsettings blocks rather than data; boilerplate README.