mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-04-06 02:19:05 +00:00
Add user registration emails + email infrastructure (#150)
* Add email functionality * Add email template project and rendering service * Update email template dir structure * Add email header and footer components for user registration template * update example env * Refactor email templates namespace and components * Format email dir
This commit is contained in:
@@ -20,7 +20,12 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Domain.Entities\Domain.Entities.csproj" />
|
||||
<ProjectReference Include="..\..\Domain.Exceptions\Domain.Exceptions.csproj" />
|
||||
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Repository\Infrastructure.Repository.csproj" />
|
||||
<ProjectReference
|
||||
Include="..\..\Infrastructure\Infrastructure.Email\Infrastructure.Email.csproj" />
|
||||
<ProjectReference
|
||||
Include="..\..\Infrastructure\Infrastructure.Email.Templates\Infrastructure.Email.Templates.csproj" />
|
||||
<ProjectReference
|
||||
Include="..\..\Infrastructure\Infrastructure.Repository\Infrastructure.Repository.csproj" />
|
||||
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Jwt\Infrastructure.Jwt.csproj" />
|
||||
<ProjectReference Include="..\..\Service\Service.Auth\Service.Auth.csproj" />
|
||||
<ProjectReference Include="..\..\Service\Service.UserManagement\Service.UserManagement.csproj" />
|
||||
|
||||
@@ -14,6 +14,7 @@ COPY ["Domain.Exceptions/Domain.Exceptions.csproj", "Domain.Exceptions/"]
|
||||
COPY ["Infrastructure/Infrastructure.Repository/Infrastructure.Repository.csproj", "Infrastructure/Infrastructure.Repository/"]
|
||||
COPY ["Infrastructure/Infrastructure.Jwt/Infrastructure.Jwt.csproj", "Infrastructure/Infrastructure.Jwt/"]
|
||||
COPY ["Infrastructure/Infrastructure.PasswordHashing/Infrastructure.PasswordHashing.csproj", "Infrastructure/Infrastructure.PasswordHashing/"]
|
||||
COPY ["Infrastructure/Infrastructure.Email/Infrastructure.Email.csproj", "Infrastructure/Infrastructure.Email/"]
|
||||
COPY ["Service/Service.Auth/Service.Auth.csproj", "Service/Service.Auth/"]
|
||||
COPY ["Service/Service.UserManagement/Service.UserManagement.csproj", "Service/Service.UserManagement/"]
|
||||
RUN dotnet restore "API/API.Core/API.Core.csproj"
|
||||
|
||||
@@ -12,6 +12,9 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Service.Auth.Auth;
|
||||
using Service.UserManagement.User;
|
||||
using API.Core.Contracts.Common;
|
||||
using Infrastructure.Email;
|
||||
using Infrastructure.Email.Templates;
|
||||
using Infrastructure.Email.Templates.Rendering;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -53,6 +56,8 @@ builder.Services.AddScoped<IRegisterService, RegisterService>();
|
||||
|
||||
builder.Services.AddScoped<ITokenInfrastructure, JwtInfrastructure>();
|
||||
builder.Services.AddScoped<IPasswordInfrastructure, Argon2Infrastructure>();
|
||||
builder.Services.AddScoped<IEmailProvider, SmtpEmailProvider>();
|
||||
builder.Services.AddScoped<IEmailTemplateProvider, EmailTemplateProvider>();
|
||||
|
||||
// Register the exception filter
|
||||
builder.Services.AddScoped<GlobalExceptionFilter>();
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
<!-- Reqnroll core, xUnit adapter and code-behind generator -->
|
||||
<PackageReference Include="Reqnroll" Version="3.3.3" />
|
||||
<PackageReference Include="Reqnroll.xUnit" Version="3.3.3" />
|
||||
<PackageReference Include="Reqnroll.Tools.MsBuild.Generation" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Reqnroll.Tools.MsBuild.Generation" Version="3.3.3"
|
||||
PrivateAssets="all" />
|
||||
|
||||
<!-- ASP.NET Core integration testing -->
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.1" />
|
||||
@@ -34,5 +35,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\API.Core\API.Core.csproj" />
|
||||
<ProjectReference
|
||||
Include="..\..\Infrastructure\Infrastructure.Email\Infrastructure.Email.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -8,6 +8,7 @@ COPY ["Domain.Exceptions/Domain.Exceptions.csproj", "Domain.Exceptions/"]
|
||||
COPY ["Infrastructure/Infrastructure.Repository/Infrastructure.Repository.csproj", "Infrastructure/Infrastructure.Repository/"]
|
||||
COPY ["Infrastructure/Infrastructure.Jwt/Infrastructure.Jwt.csproj", "Infrastructure/Infrastructure.Jwt/"]
|
||||
COPY ["Infrastructure/Infrastructure.PasswordHashing/Infrastructure.PasswordHashing.csproj", "Infrastructure/Infrastructure.PasswordHashing/"]
|
||||
COPY ["Infrastructure/Infrastructure.Email/Infrastructure.Email.csproj", "Infrastructure/Infrastructure.Email/"]
|
||||
COPY ["Service/Service.Auth/Service.Auth.csproj", "Service/Service.Auth/"]
|
||||
COPY ["Service/Service.UserManagement/Service.UserManagement.csproj", "Service/Service.UserManagement/"]
|
||||
RUN dotnet restore "API/API.Specs/API.Specs.csproj"
|
||||
|
||||
54
src/Core/API/API.Specs/Mocks/MockEmailService.cs
Normal file
54
src/Core/API/API.Specs/Mocks/MockEmailService.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using Infrastructure.Email;
|
||||
|
||||
namespace API.Specs.Mocks;
|
||||
|
||||
/// <summary>
|
||||
/// Mock email service for testing that doesn't actually send emails.
|
||||
/// Tracks sent emails for verification in tests if needed.
|
||||
/// </summary>
|
||||
public class MockEmailProvider : IEmailProvider
|
||||
{
|
||||
public List<SentEmail> SentEmails { get; } = new();
|
||||
|
||||
public Task SendAsync(string to, string subject, string body, bool isHtml = true)
|
||||
{
|
||||
SentEmails.Add(new SentEmail
|
||||
{
|
||||
To = [to],
|
||||
Subject = subject,
|
||||
Body = body,
|
||||
IsHtml = isHtml,
|
||||
SentAt = DateTime.UtcNow
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SendAsync(IEnumerable<string> to, string subject, string body, bool isHtml = true)
|
||||
{
|
||||
SentEmails.Add(new SentEmail
|
||||
{
|
||||
To = to.ToList(),
|
||||
Subject = subject,
|
||||
Body = body,
|
||||
IsHtml = isHtml,
|
||||
SentAt = DateTime.UtcNow
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SentEmails.Clear();
|
||||
}
|
||||
|
||||
public class SentEmail
|
||||
{
|
||||
public List<string> To { get; init; } = new();
|
||||
public string Subject { get; init; } = string.Empty;
|
||||
public string Body { get; init; } = string.Empty;
|
||||
public bool IsHtml { get; init; }
|
||||
public DateTime SentAt { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using API.Specs.Mocks;
|
||||
using Infrastructure.Email;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace API.Specs
|
||||
{
|
||||
@@ -10,6 +13,20 @@ namespace API.Specs
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
builder.UseEnvironment("Testing");
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
// Replace the real email service with mock for testing
|
||||
var descriptor = services.SingleOrDefault(
|
||||
d => d.ServiceType == typeof(IEmailProvider));
|
||||
|
||||
if (descriptor != null)
|
||||
{
|
||||
services.Remove(descriptor);
|
||||
}
|
||||
|
||||
services.AddScoped<IEmailProvider, MockEmailProvider>();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user