Skip to content

Commit 75addc0

Browse files
Merge pull request #9 from pierrick-fonquerne/FRO-45-Service-d-email-centralise
Fro 45 service d email centralise
2 parents 9b8c749 + f6609ac commit 75addc0

File tree

16 files changed

+1104
-2
lines changed

16 files changed

+1104
-2
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444

4545
- name: Test
4646
if: steps.check.outputs.exists == 'true'
47-
run: dotnet test --no-build --configuration Release --verbosity normal
47+
run: dotnet test --no-build --configuration Release --verbosity normal --filter "Category!=Email"
4848

4949
- name: Skip (no backend yet)
5050
if: steps.check.outputs.exists == 'false'

src/backend/src/FantasyRealm.Api/FantasyRealm.Api.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
<Project Sdk="Microsoft.NET.Sdk.Web">
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
7+
<UserSecretsId>007759ae-ee7a-4987-a1c3-cc316e317846</UserSecretsId>
78
</PropertyGroup>
89

910
<ItemGroup>

src/backend/src/FantasyRealm.Api/appsettings.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,14 @@
1212
},
1313
"MongoDB": {
1414
"DatabaseName": "fantasyrealm"
15+
},
16+
"Email": {
17+
"Host": "ssl0.ovh.net",
18+
"Port": 587,
19+
"UseSsl": true,
20+
"Username": "noreply@fantasy-realm.com",
21+
"Password": "",
22+
"FromAddress": "noreply@fantasy-realm.com",
23+
"FromName": "FantasyRealm"
1524
}
1625
}

src/backend/src/FantasyRealm.Application/Interfaces/.gitkeep

Whitespace-only changes.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
namespace FantasyRealm.Application.Interfaces
2+
{
3+
/// <summary>
4+
/// Defines the contract for email sending operations.
5+
/// </summary>
6+
public interface IEmailService
7+
{
8+
/// <summary>
9+
/// Sends a welcome email to a newly registered user.
10+
/// </summary>
11+
/// <param name="toEmail">The recipient's email address.</param>
12+
/// <param name="pseudo">The user's display name.</param>
13+
/// <param name="cancellationToken">A cancellation token.</param>
14+
/// <returns>A task representing the asynchronous operation.</returns>
15+
Task SendWelcomeEmailAsync(string toEmail, string pseudo, CancellationToken cancellationToken = default);
16+
17+
/// <summary>
18+
/// Sends a password reset email with a reset link.
19+
/// </summary>
20+
/// <param name="toEmail">The recipient's email address.</param>
21+
/// <param name="pseudo">The user's display name.</param>
22+
/// <param name="resetToken">The password reset token.</param>
23+
/// <param name="cancellationToken">A cancellation token.</param>
24+
/// <returns>A task representing the asynchronous operation.</returns>
25+
Task SendPasswordResetEmailAsync(string toEmail, string pseudo, string resetToken, CancellationToken cancellationToken = default);
26+
27+
/// <summary>
28+
/// Sends a notification when a character has been approved by an employee.
29+
/// </summary>
30+
/// <param name="toEmail">The recipient's email address.</param>
31+
/// <param name="pseudo">The user's display name.</param>
32+
/// <param name="characterName">The name of the approved character.</param>
33+
/// <param name="cancellationToken">A cancellation token.</param>
34+
/// <returns>A task representing the asynchronous operation.</returns>
35+
Task SendCharacterApprovedEmailAsync(string toEmail, string pseudo, string characterName, CancellationToken cancellationToken = default);
36+
37+
/// <summary>
38+
/// Sends a notification when a character has been rejected by an employee.
39+
/// </summary>
40+
/// <param name="toEmail">The recipient's email address.</param>
41+
/// <param name="pseudo">The user's display name.</param>
42+
/// <param name="characterName">The name of the rejected character.</param>
43+
/// <param name="reason">The reason for rejection.</param>
44+
/// <param name="cancellationToken">A cancellation token.</param>
45+
/// <returns>A task representing the asynchronous operation.</returns>
46+
Task SendCharacterRejectedEmailAsync(string toEmail, string pseudo, string characterName, string reason, CancellationToken cancellationToken = default);
47+
48+
/// <summary>
49+
/// Sends a notification when a comment has been approved.
50+
/// </summary>
51+
/// <param name="toEmail">The recipient's email address.</param>
52+
/// <param name="pseudo">The user's display name.</param>
53+
/// <param name="characterName">The name of the character that was commented on.</param>
54+
/// <param name="cancellationToken">A cancellation token.</param>
55+
/// <returns>A task representing the asynchronous operation.</returns>
56+
Task SendCommentApprovedEmailAsync(string toEmail, string pseudo, string characterName, CancellationToken cancellationToken = default);
57+
58+
/// <summary>
59+
/// Sends a notification when a comment has been rejected.
60+
/// </summary>
61+
/// <param name="toEmail">The recipient's email address.</param>
62+
/// <param name="pseudo">The user's display name.</param>
63+
/// <param name="characterName">The name of the character that was commented on.</param>
64+
/// <param name="reason">The reason for rejection.</param>
65+
/// <param name="cancellationToken">A cancellation token.</param>
66+
/// <returns>A task representing the asynchronous operation.</returns>
67+
Task SendCommentRejectedEmailAsync(string toEmail, string pseudo, string characterName, string reason, CancellationToken cancellationToken = default);
68+
69+
/// <summary>
70+
/// Sends a notification when the user's account has been suspended.
71+
/// </summary>
72+
/// <param name="toEmail">The recipient's email address.</param>
73+
/// <param name="pseudo">The user's display name.</param>
74+
/// <param name="reason">The reason for suspension.</param>
75+
/// <param name="cancellationToken">A cancellation token.</param>
76+
/// <returns>A task representing the asynchronous operation.</returns>
77+
Task SendAccountSuspendedEmailAsync(string toEmail, string pseudo, string reason, CancellationToken cancellationToken = default);
78+
}
79+
}

src/backend/src/FantasyRealm.Infrastructure/DependencyInjection.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using FantasyRealm.Application.Interfaces;
2+
using FantasyRealm.Infrastructure.Email;
13
using FantasyRealm.Infrastructure.Persistence;
24
using Microsoft.EntityFrameworkCore;
35
using Microsoft.Extensions.Configuration;
@@ -39,6 +41,10 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi
3941
});
4042
}
4143

44+
services.Configure<EmailSettings>(configuration.GetSection(EmailSettings.SectionName));
45+
services.AddSingleton<ISmtpClientFactory, SmtpClientFactory>();
46+
services.AddScoped<IEmailService, SmtpEmailService>();
47+
4248
return services;
4349
}
4450
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace FantasyRealm.Infrastructure.Email
2+
{
3+
/// <summary>
4+
/// Configuration settings for the SMTP email service.
5+
/// </summary>
6+
public class EmailSettings
7+
{
8+
/// <summary>
9+
/// The configuration section name in appsettings.json.
10+
/// </summary>
11+
public const string SectionName = "Email";
12+
13+
/// <summary>
14+
/// Gets or sets the SMTP server hostname.
15+
/// </summary>
16+
public string Host { get; set; } = string.Empty;
17+
18+
/// <summary>
19+
/// Gets or sets the SMTP server port.
20+
/// </summary>
21+
public int Port { get; set; } = 587;
22+
23+
/// <summary>
24+
/// Gets or sets whether to use SSL/TLS for the connection.
25+
/// </summary>
26+
public bool UseSsl { get; set; } = true;
27+
28+
/// <summary>
29+
/// Gets or sets the SMTP authentication username.
30+
/// </summary>
31+
public string Username { get; set; } = string.Empty;
32+
33+
/// <summary>
34+
/// Gets or sets the SMTP authentication password.
35+
/// </summary>
36+
public string Password { get; set; } = string.Empty;
37+
38+
/// <summary>
39+
/// Gets or sets the sender email address.
40+
/// </summary>
41+
public string FromAddress { get; set; } = string.Empty;
42+
43+
/// <summary>
44+
/// Gets or sets the sender display name.
45+
/// </summary>
46+
public string FromName { get; set; } = string.Empty;
47+
}
48+
}

0 commit comments

Comments
 (0)