MailCore is a production-ready backend service for an email application. Built with .NET 8 following Clean Architecture and CQRS patterns.
- Email Management: Send, receive, forward, reply, search, and organize emails.
- Drafts & Threads: Save drafts with recipient fields, group related emails into conversational threads.
- Labels: Tag emails with custom labels for organization.
- Attachments: Upload files via local storage provider.
- Full-Text Search: Search across subject, body, sender, and recipient emails with cursor-paginated results.
- Delivery Tracking: Track send status (Pending / Sent / Failed) with retry logic (3 attempts).
- SMTP Outbound: Background dispatch via MailKit (polling every 5s), configured for any SMTP provider (SendGrid, Resend, Mailgun, etc.).
- Real-Time Push: SignalR hub pushes new email notifications to recipient groups.
- Authentication: JWT-based with rate-limited auth endpoints (10 req/min).
- API Versioning: URL segment + header-based versioning.
- Validation: FluentValidation pipeline via MediatR behaviors.
- Swagger: Full OpenAPI docs with XML comments, response schemas, and example values (enabled in all environments).
- Dev Seeding: Auto-seeds demo data (2 users, labels, threads, emails, drafts) in Development.
flowchart TD
Client(["Client / Frontend"]) -->|HTTP / REST| API
Client -->|SignalR| WS(["WebSocket /hubs/mail"])
subgraph core ["MailCore"]
API("API Layer<br/><small>Controllers, Auth, Swagger, SignalR Hub</small>")
APP("Application Layer<br/><small>CQRS, MediatR, Validation, Notifications</small>")
DOMAIN("Domain Layer<br/><small>Entities, Enums, Interfaces</small>")
INFRA("Infrastructure Layer<br/><small>EF Core, Repositories, SMTP, File Storage</small>")
API -->|Commands & Queries| APP
APP -->|Business Models| DOMAIN
INFRA -->|Implements Interfaces| APP
INFRA -->|Persists Models| DOMAIN
API -.->|DI Container Config| INFRA
end
INFRA -->|Reads / Writes| DB[("SQL Server")]
INFRA -->|File I/O| FS["Local File Storage"]
INFRA -->|SMTP| SMTP["SMTP Server<br/><small>SendGrid / Resend / Mailgun</small>"]
WS -.->|NewEmail event| Client
- API Layer — Entry point. Controllers, JWT auth, rate limiting, CORS, Swagger, SignalR hub, Web Deploy publishing.
- Application Layer — Use cases as MediatR Commands/Queries. DTOs, mappers, validators, pipeline behaviors (logging, validation, transactions), MediatR notifications for cross-cutting concerns.
- Domain Layer — Core entities (
Email,User,Thread,Label,Draft,Attachment,MailRecipient), enums (EmailDeliveryStatus,RecipientType), repository interfaces, custom exceptions. - Infrastructure Layer — EF Core DbContext + Migrations, repository implementations, Unit of Work,
SmtpEmailSender(MailKit),EmailDispatchService(BackgroundService), JWT token generator,IdentityPasswordHasher, local file storage.
- Framework: .NET 8 / C#
- Database: SQL Server via Entity Framework Core
- SMTP: MailKit (Resend / SendGrid / any SMTP)
- Real-Time: SignalR
- CQRS/Mediation: MediatR
- Validation: FluentValidation
- Testing: xUnit + Moq + Testcontainers (SQL Server)
- Docs: Swagger / Swashbuckle
- Auth: JWT Bearer
- Containerization: Docker Compose (SQL Server 2022 + MailHog + API)
- .NET 8 SDK
- SQL Server (or Docker for containerized DB)
docker compose upThis starts SQL Server 2022, MailHog (SMTP capture at localhost:8025), and the API at localhost:5237.
-
Clone:
git clone https://github.com/Se3do/MailCore-API.git cd MailCore-API -
Configure
MailCore.API/appsettings.Development.json:"ConnectionStrings": { "DefaultConnection": "Server=.;Database=MailService;TrustServerCertificate=True;MultipleActiveResultSets=true;Integrated Security=SSPI;" }, "Jwt": { "Secret": "Your-Very-Secret-Key-Here-Make-It-Long-At-Least-32-Chars", "Issuer": "MailCore", "Audience": "MailCore", "ExpiryMinutes": 60 }
-
Apply migrations:
dotnet ef database update --project MailCore.Infrastructure --startup-project MailCore.API
-
Run:
dotnet run --project MailCore.API
-
Swagger UI: Navigate to
https://localhost:<port>/swagger. -
Seed Data: Set
"SeedOnStartup": trueinappsettings.Development.jsonto auto-seed demo users, labels, and sample emails.
# Unit tests
dotnet test MailCore.Application.Tests
dotnet test MailCore.Infrastructure.Tests
# Integration tests (requires Docker Desktop for SQL Server container)
dotnet test MailCore.IntegrationTestsMailCore/
├── MailCore.API/ # API entry point, controllers, SignalR hub
├── MailCore.Application/ # CQRS commands/queries, DTOs, validators
├── MailCore.Application.Tests/ # Unit tests for Application layer
├── MailCore.Domain/ # Entities, enums, repository interfaces
├── MailCore.Infrastructure/ # EF Core, repositories, SMTP sender, file storage
├── MailCore.Infrastructure.Tests/ # Unit tests for Infrastructure layer
├── MailCore.IntegrationTests/ # Integration tests with Testcontainers
├── .github/workflows/ # CI + CD (both master branch) pipelines
├── Dockerfile # Container image for the API
├── docker-compose.yml # SQL Server + MailHog + API
└── MailCore.sln # Solution file
CI/CD configured via GitHub Actions:
- CI runs on
masterpushes — build + unit tests - CD runs on
masterpushes — build → test → publish → deploy to MonsterASP via Web Deploy (rasmusbuchholdt/simply-web-deploy)
Set these GitHub secrets for deployment:
MONSTERASP_MSDEPLOY_URL,MONSTERASP_USERNAME,MONSTERASP_PASSWORDWEBSITE_NAME,SERVER_COMPUTER_NAME,SERVER_USERNAME,SERVER_PASSWORDCONNECTIONSTRINGS__DEFAULTCONNECTIONJWT__SECRET,JWT__ISSUER,JWT__AUDIENCESMTP__HOST,SMTP__USERNAME,SMTP__PASSWORD,SMTP__FROMADDRESS,SMTP__FROMNAMEFILESTORAGE__ROOTPATH
MIT