Skip to content

Add MailDev and MailKit custom integration sample - #1891

Merged
David Pine (IEvangelist) merged 5 commits into
mainfrom
dapine/add-maildev-mailkit-sample
Aug 18, 2026
Merged

Add MailDev and MailKit custom integration sample#1891
David Pine (IEvangelist) merged 5 commits into
mainfrom
dapine/add-maildev-mailkit-sample

Conversation

@IEvangelist

Copy link
Copy Markdown
Member

Summary

  • add an Aspire 13.5 custom MailDev hosting integration exported through ATS
  • add a MailKit client integration with health checks, tracing, metrics, and secure credentials
  • provide a runnable TypeScript AppHost plus a compile-validated C# equivalent
  • add a newsletter API and focused hosting/client tests

Validation

  • MailDev hosting tests: 4 passed
  • MailKit client tests: 8 passed
  • TypeScript AppHost compile and lint passed
  • end-to-end subscribe/unsubscribe flow verified against MailDev
  • vulnerable package checks found no known vulnerabilities

Copilot AI 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.

Pull request overview

Adds a new Aspire sample (samples/maildev-mailkit) demonstrating a custom MailDev hosting integration exported via the Aspire Type System (ATS) and a MailKit client integration consumed by a newsletter API, with both TypeScript and C# AppHost options.

Changes:

  • Introduces MailDev hosting integration (AddMailDev, MailDevResource) and a MailKit client integration with health checks, tracing, and metrics.
  • Adds a runnable TypeScript AppHost plus a compile-validated C# AppHost equivalent, along with sample newsletter endpoints.
  • Adds focused unit tests for the hosting/client integrations and documents setup/run/test steps.

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
samples/maildev-mailkit/tsconfig.apphost.json TypeScript compiler config for the sample AppHost build output.
samples/maildev-mailkit/ServiceDefaults/ServiceDefaults.csproj New ServiceDefaults project to share health check + OpenTelemetry wiring.
samples/maildev-mailkit/ServiceDefaults/Extensions.cs Implements ServiceDefaults extensions and endpoint mapping.
samples/maildev-mailkit/README.md Documentation for ATS exports, credentials flow, running and testing the sample.
samples/maildev-mailkit/package.json Node package scripts/deps for building and linting the TypeScript AppHost.
samples/maildev-mailkit/package-lock.json Locks Node dependencies for reproducible installs.
samples/maildev-mailkit/NewsletterService/Properties/launchSettings.json Local run profiles for the newsletter API.
samples/maildev-mailkit/NewsletterService/Program.cs Newsletter subscribe/unsubscribe endpoints sending SMTP mail via MailKit integration.
samples/maildev-mailkit/NewsletterService/NewsletterService.csproj Newsletter API project wiring (OpenAPI/Scalar + project references).
samples/maildev-mailkit/MailKit.Client/Properties/AssemblyInfo.cs Exposes internals to MailKit client tests.
samples/maildev-mailkit/MailKit.Client/MailKitHealthCheck.cs Health check that validates SMTP connectivity via the factory.
samples/maildev-mailkit/MailKit.Client/MailKitExtensions.cs Builder extensions registering MailKit factory + OTel + health checks.
samples/maildev-mailkit/MailKit.Client/MailKitClientSettings.cs Connection string parsing and configuration settings for SMTP.
samples/maildev-mailkit/MailKit.Client/MailKitClientFactory.cs Scoped SMTP client factory with connection caching per scope.
samples/maildev-mailkit/MailKit.Client/MailKit.Client.csproj MailKit client integration package references/TFM.
samples/maildev-mailkit/MailKit.Client.Tests/MailKitExtensionsTests.cs Unit tests for registration behavior (scoped/keyed/validation).
samples/maildev-mailkit/MailKit.Client.Tests/MailKitClientSettingsTests.cs Unit tests for connection string parsing behavior.
samples/maildev-mailkit/MailKit.Client.Tests/MailKit.Client.Tests.csproj Test project setup for MailKit client integration.
samples/maildev-mailkit/MailDev.Hosting/MailDevResourceBuilderExtensions.cs Adds the MailDev container resource and exports it for ATS.
samples/maildev-mailkit/MailDev.Hosting/MailDevResource.cs Defines MailDev resource model + deferred connection string expression.
samples/maildev-mailkit/MailDev.Hosting/MailDev.Hosting.csproj Hosting integration project for MailDev (Aspire.Hosting dependency).
samples/maildev-mailkit/MailDev.Hosting.Tests/MailDevResourceTests.cs Unit tests validating container config, ATS exports, and connection string expression.
samples/maildev-mailkit/MailDev.Hosting.Tests/MailDev.Hosting.Tests.csproj Test project setup for MailDev hosting integration.
samples/maildev-mailkit/eslint.config.mjs ESLint configuration for the TypeScript AppHost file.
samples/maildev-mailkit/CSharpAppHost/Program.cs C# equivalent AppHost wiring MailDev + newsletter service.
samples/maildev-mailkit/CSharpAppHost/CSharpAppHost.csproj C# AppHost project setup referencing Aspire.Hosting + MailDev.Hosting.
samples/maildev-mailkit/aspire.config.json Configures the TypeScript AppHost and ATS package export for restore.
samples/maildev-mailkit/apphost.mts Runnable TypeScript AppHost consuming ATS-generated APIs.
samples/maildev-mailkit/.gitignore Ignores .aspire/ and build outputs for the sample.
README.md Adds the new sample entry to the repository’s samples table.
Files not reviewed (1)
  • samples/maildev-mailkit/package-lock.json: Generated file

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread samples/maildev-mailkit/ServiceDefaults/Extensions.cs
Comment thread samples/maildev-mailkit/package-lock.json
Comment thread samples/maildev-mailkit/MailKit.Client/MailKitExtensions.cs Outdated
@IEvangelist
David Pine (IEvangelist) force-pushed the dapine/add-maildev-mailkit-sample branch from 6a6bbcd to ad93e11 Compare August 14, 2026 16:48
@IEvangelist
David Pine (IEvangelist) force-pushed the dapine/add-maildev-mailkit-sample branch from ad93e11 to f42053e Compare August 14, 2026 16:56
Comment thread samples/maildev-mailkit/MailKit.Client/MailKitExtensions.cs
Comment thread samples/maildev-mailkit/NewsletterService/Program.cs Outdated
Comment thread samples/maildev-mailkit/MailDev.Hosting/MailDevResource.cs Outdated
Comment thread samples/maildev-mailkit/MailDev.Hosting/MailDev.Hosting.csproj

@adamint Adam Ratzman (adamint) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed pinned head 7ff86d2d6fd5ba479889cfa5a789f641ba434596. The overall shape is sound and these are fixable in place, so I am approving. I think the must-fix items are keeping MailDev run-only, adding real readiness, making repo CI compile/test the .NET projects, and returning Unhealthy instead of an unhandled 500 for missing MailKit configuration. I also left comments on request validation, connection properties, and ATS docs.

The PR head advanced while this review ran; this decision is intentionally attached to the requested pinned commit.

@adamint Adam Ratzman (adamint) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental review of f42053e: the MailKit naming fix is incomplete, so I reopened that thread with a failing focused test. Ubuntu is failing in the unrelated Angular sample (typescript@7.0.2 vs @angular-devkit/build-angular requiring <6.1), which #1866 already fixed on main. This head is still conflicting with main and red, so I’m leaving a comment rather than approving. Please merge main, address the MailKit thread, and rerun CI.

@adamint Adam Ratzman (adamint) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving this as the remaining issue is fixable in place. The health-check thread is still must-fix before merge, and this branch needs updating from main to clear the unrelated Angular failure and workflow conflict.

…ilkit-sample

# Conflicts:
#	.github/workflows/ci.yml
- MailDev.Hosting: exclude the resource from the manifest, add an HTTP
  readiness health check (/healthz), and implement GetConnectionProperties
  (Host, Port, Username, Password, Uri) for structured/polyglot consumers
- MailDev.Hosting: enable GenerateDocumentationFile so XML docs flow into the
  generated ATS SDK JSDoc; document the primary constructor parameters
- MailKit.Client: bind each health check to its own connection settings so
  multiple registrations probe distinct endpoints, and construct the factory
  without throwing so a missing endpoint reports Unhealthy instead of a 500
- NewsletterService: validate the recipient with MailboxAddress.TryParse and
  return 400 for missing/invalid email instead of an unhandled 500
- ServiceDefaults: only map health endpoints in Development, with a note on the
  security implications, matching the repo convention
- Add MailDevMailKit.slnx so CI compiles and tests all sample projects
- Add tests for manifest exclusion, the readiness health check, structured
  connection properties, per-connection health-check binding, and the
  Unhealthy-on-missing-endpoint path

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist

Copy link
Copy Markdown
Member Author

Thanks for the detailed review Adam Ratzman (@adamint)! Pushed 7d13c4e addressing everything, and resolved each thread with specifics. High-level:

  • MailDev.Hosting.ExcludeFromManifest(), an HTTP readiness health check on /healthz, and GetConnectionProperties() (Host/Port/Username/Password/Uri). Enabled GenerateDocumentationFile; verified the generated aspire.mts now carries JSDoc (summary/@param/@returns) on addMailDev and the MailDevResource type.
  • MailKit.Client — each health check binds to its own connection (distinct endpoints), and constructs without throwing so a missing endpoint reports Unhealthy instead of a 500.
  • NewsletterServiceMailboxAddress.TryParse400 for missing/malformed email.
  • ServiceDefaults — health endpoints mapped in Development only, matching the repo convention.
  • MailDevMailKit.slnx — all seven projects so CI compiles/tests them. Full solution builds clean under TreatWarningsAsErrors (18 tests pass); TS AppHost aspire:build + aspire:lint are clean.

On the Copilot package-lock note: the internal ms-feed/visualstudio.com URLs are already gone (the committed lockfile has no resolved URLs) and npm ci restores cleanly against the public registry. The integrity hashes are still sha1 — an artifact of the feed it was generated against. If you'd prefer sha512, I'm happy to regenerate against public npm; it just needs an environment with public-registry access. Let me know your preference.

The repo CI pins the Aspire CLI to 13.4.6, but the sample pinned the
Aspire SDK to 13.5.0 (staging), causing `aspire restore` to fail with a
version mismatch on every CI run. Downgrade the sample to the stable
13.4.0 release so it restores and builds under CI:

- aspire.config.json: SDK 13.5.0 -> 13.4.0; drop the staging channel.
- CSharpAppHost / MailDev.Hosting: Aspire.Hosting 13.5.0 -> 13.4.0.
- MailDev.Hosting: opt in to ASPIREATS001; the Aspire Type System export
  attribute is an evaluation feature in 13.4.x.
- Remove the sample-local NuGet.Config; the staging feed is no longer
  needed and the repo-root NuGet.Config (nuget.org) suffices.

Verified: solution builds clean, 18/18 tests pass, `aspire restore`
regenerates the ATS bindings (JSDoc intact), tsc + eslint clean.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist

Copy link
Copy Markdown
Member Author

CI is green now ✅

The pipeline was red on every run because the sample pinned the Aspire SDK to 13.5.0 (staging) while the repo CI installs the Aspire CLI at 13.4.6aspire restore failed with a version mismatch (Method not found: set_CertificateBundleEnvironmentVariable) in both the Ubuntu Validate JavaScript packages step and the Windows build.

Rather than bump CI, I aligned the sample with the stable release the repo already targets:

  • aspire.config.json: SDK 13.5.013.4.0, dropped the staging channel.
  • CSharpAppHost / MailDev.Hosting: Aspire.Hosting 13.5.013.4.0.
  • MailDev.Hosting: opt in to ASPIREATS001 — the Aspire Type System export attribute is an evaluation feature in 13.4.x (it's un-gated in 13.5.0).
  • Removed the sample-local NuGet.Config; the staging feed is no longer needed and the repo-root NuGet.Config (nuget.org) covers it.

Verified locally and in CI: solution builds clean, 18/18 tests pass, aspire restore regenerates the ATS bindings with the XML-doc JSDoc intact (addMailDev summary/@param/@returns), and tsc + eslint are clean.

@IEvangelist
David Pine (IEvangelist) merged commit 7da636b into main Aug 18, 2026
4 checks passed
@IEvangelist
David Pine (IEvangelist) deleted the dapine/add-maildev-mailkit-sample branch August 18, 2026 14:16
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.

4 participants