mirror of
https://github.com/Stefan-5422/-T5-Elektrifikatsiya.git
synced 2026-09-04 00:45:58 +02:00
Email Inferstructure
This commit is contained in:
@@ -42,7 +42,9 @@
|
|||||||
<PackageReference Include="Blazorise.Icons.Material" Version="1.2.0" />
|
<PackageReference Include="Blazorise.Icons.Material" Version="1.2.0" />
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="FluentResults" Version="3.15.2" />
|
<PackageReference Include="FluentResults" Version="3.15.2" />
|
||||||
|
<PackageReference Include="Handlebars.Net" Version="2.1.4" />
|
||||||
<PackageReference Include="HiveMQtt" Version="0.1.10" />
|
<PackageReference Include="HiveMQtt" Version="0.1.10" />
|
||||||
|
<PackageReference Include="MailKit" Version="4.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.4">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.4">
|
||||||
@@ -50,6 +52,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
|
||||||
|
<PackageReference Include="Mjml.Net" Version="1.22.0" />
|
||||||
<PackageReference Include="Tmds.MDns" Version="0.7.1" />
|
<PackageReference Include="Tmds.MDns" Version="0.7.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -7,17 +7,22 @@ using Elektrifikatsiya.Database;
|
|||||||
using Elektrifikatsiya.Models;
|
using Elektrifikatsiya.Models;
|
||||||
using Elektrifikatsiya.Services;
|
using Elektrifikatsiya.Services;
|
||||||
using Elektrifikatsiya.Services.Implementations;
|
using Elektrifikatsiya.Services.Implementations;
|
||||||
|
using Elektrifikatsiya.Utilities;
|
||||||
using HiveMQtt.Client;
|
using HiveMQtt.Client;
|
||||||
using HiveMQtt.Client.Options;
|
using HiveMQtt.Client.Options;
|
||||||
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Read configuration
|
||||||
|
builder.Services.Configure<EmailSettings>(builder.Configuration.GetRequiredSection("EmailSettings"));
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
builder.Services.AddServerSideBlazor();
|
builder.Services.AddServerSideBlazor();
|
||||||
|
builder.Services.AddOptions();
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
builder.Services.AddHostedService<UpdateService>();
|
builder.Services.AddHostedService<UpdateService>();
|
||||||
builder.Services.AddSingleton<IDeviceStatusService, DeviceStatusService>();
|
builder.Services.AddSingleton<IDeviceStatusService, DeviceStatusService>();
|
||||||
@@ -38,6 +43,7 @@ builder.Services.AddTransient<IDeviceManagmentService, DeviceManagmentService>()
|
|||||||
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
|
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||||
builder.Services.AddScoped<IAuthorizationService, AuthorizationService>();
|
builder.Services.AddScoped<IAuthorizationService, AuthorizationService>();
|
||||||
builder.Services.AddScoped<ICookieService, CookieService>();
|
builder.Services.AddScoped<ICookieService, CookieService>();
|
||||||
|
builder.Services.AddScoped<IEmailService, EmailService>();
|
||||||
builder.Services.AddDbContext<MainDatabaseContext>(options => options.UseSqlite("Data Source=./MainDatabase.sqlite"));
|
builder.Services.AddDbContext<MainDatabaseContext>(options => options.UseSqlite("Data Source=./MainDatabase.sqlite"));
|
||||||
builder.Services.AddBootstrapProviders();
|
builder.Services.AddBootstrapProviders();
|
||||||
builder.Services.AddHttpClient<IDeviceManagmentService, DeviceManagmentService>();
|
builder.Services.AddHttpClient<IDeviceManagmentService, DeviceManagmentService>();
|
||||||
@@ -46,6 +52,7 @@ builder.Services.AddBlazorise(options =>
|
|||||||
options.Immediate = true;
|
options.Immediate = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
AddBlazorise(builder.Services);
|
AddBlazorise(builder.Services);
|
||||||
|
|
||||||
WebApplication app = builder.Build();
|
WebApplication app = builder.Build();
|
||||||
@@ -67,6 +74,8 @@ app.MapBlazorHub();
|
|||||||
app.MapFallbackToPage("/_Host");
|
app.MapFallbackToPage("/_Host");
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Services.GetRequiredService<IOptions<EmailSettings>>().Value.CompileTemplates();
|
||||||
|
|
||||||
IServiceScope serviceScope = app.Services.GetRequiredService<IServiceScopeFactory>().CreateScope();
|
IServiceScope serviceScope = app.Services.GetRequiredService<IServiceScopeFactory>().CreateScope();
|
||||||
|
|
||||||
MainDatabaseContext mainDatabase = serviceScope.ServiceProvider.GetRequiredService<MainDatabaseContext>();
|
MainDatabaseContext mainDatabase = serviceScope.ServiceProvider.GetRequiredService<MainDatabaseContext>();
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Elektrifikatsiya.Services;
|
||||||
|
|
||||||
|
public interface IEmailService
|
||||||
|
{
|
||||||
|
Task SendAsync(string to, string subject, string html, string? from = null);
|
||||||
|
|
||||||
|
Task SendWithTemeplateAsync(string to, string subject, string templateKey, string? from = null, Dictionary<string, string>? templateParameters = null);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using Elektrifikatsiya.Utilities;
|
||||||
|
using HandlebarsDotNet;
|
||||||
|
using MailKit.Net.Smtp;
|
||||||
|
using MailKit.Security;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MimeKit;
|
||||||
|
using MimeKit.Text;
|
||||||
|
|
||||||
|
namespace Elektrifikatsiya.Services.Implementations
|
||||||
|
{
|
||||||
|
public class EmailService : IEmailService
|
||||||
|
{
|
||||||
|
private readonly EmailSettings emailSettings;
|
||||||
|
|
||||||
|
public EmailService(IOptions<EmailSettings> emailSettings)
|
||||||
|
{
|
||||||
|
this.emailSettings = emailSettings.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendAsync(string to, string subject, string html, string? from = null)
|
||||||
|
{
|
||||||
|
from ??= emailSettings.DefaultEmail;
|
||||||
|
|
||||||
|
MimeMessage message = new MimeMessage();
|
||||||
|
message.From.Add(MailboxAddress.Parse(from));
|
||||||
|
message.To.Add(MailboxAddress.Parse(to));
|
||||||
|
message.Subject = subject;
|
||||||
|
message.Body = new TextPart(TextFormat.Html) { Text = html };
|
||||||
|
|
||||||
|
using SmtpClient smtp = new SmtpClient();
|
||||||
|
await smtp.ConnectAsync(emailSettings.SmtpServer, emailSettings.SmtpPort, SecureSocketOptions.StartTls);
|
||||||
|
await smtp.AuthenticateAsync(emailSettings.User, emailSettings.Key);
|
||||||
|
await smtp.SendAsync(message);
|
||||||
|
await smtp.DisconnectAsync(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SendWithTemeplateAsync(string to, string subject, string templateKey, string? from = null, Dictionary<string, string>? templateParameters = null)
|
||||||
|
{
|
||||||
|
string content = emailSettings.CompiledTemplates[templateKey](templateParameters ?? new());
|
||||||
|
return SendAsync(to, subject, content, from);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using HandlebarsDotNet;
|
||||||
|
|
||||||
|
namespace Elektrifikatsiya.Utilities;
|
||||||
|
|
||||||
|
public class EmailSettings
|
||||||
|
{
|
||||||
|
public string User { get; set; }
|
||||||
|
public string DefaultEmail { get; set; }
|
||||||
|
public string Key { get; set; }
|
||||||
|
public Dictionary<string, string> Templates { get; set; }
|
||||||
|
public string SmtpServer { get; set; }
|
||||||
|
public int SmtpPort { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, HandlebarsTemplate<object, object>> CompiledTemplates = new();
|
||||||
|
|
||||||
|
public void CompileTemplates()
|
||||||
|
{
|
||||||
|
foreach ((string templateName, string templatePath) in Templates)
|
||||||
|
{
|
||||||
|
CompiledTemplates.Add(templateName, Handlebars.Compile(File.ReadAllText(templatePath)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,19 @@
|
|||||||
{
|
{
|
||||||
"DetailedErrors": true,
|
"DetailedErrors": true,
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EmailSettings": {
|
||||||
|
"User": "",
|
||||||
|
"DefaultEmail": "",
|
||||||
|
"Key": "",
|
||||||
|
"Templates": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"SmtpServer": "",
|
||||||
|
"SmtpPort": 0
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,49 @@
|
|||||||
|
<mjml>
|
||||||
|
<mj-head>
|
||||||
|
<mj-attributes>
|
||||||
|
<mj-class name="primary" background-color="#1a237e"/>
|
||||||
|
</mj-attributes>
|
||||||
|
<mj-style>
|
||||||
|
@font-face {
|
||||||
|
font-family: Nunito;
|
||||||
|
src: url(https://fonts.gstatic.com/s/nunito/v16/XRXV3I6Li01BKofINeaB.woff2)
|
||||||
|
format('truetype');
|
||||||
|
}
|
||||||
|
</mj-style>
|
||||||
|
</mj-head>
|
||||||
|
<mj-body background-color="white">
|
||||||
|
<mj-wrapper padding-right="20px" padding-left="20px" padding-top="7%" >
|
||||||
|
<mj-section border-right="2px solid #B0B0B0" border-top="2px solid #B0B0B0" border-left="2px solid #B0B0B0" border-radius="33px">
|
||||||
|
</mj-section>
|
||||||
|
<mj-section padding-bottom="0px" padding-top="0px" border-left="2px solid #B0B0B0" border-right="2px solid #B0B0B0">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text align="center" font-family="Nunito, Sans-Serif" font-weight="bold" font-size="30px">
|
||||||
|
Daily Notification
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
<mj-section padding-bottom="0px" border-left="2px solid #B0B0B0" border-right="2px solid #B0B0B0">
|
||||||
|
<mj-column padding-left="5%" padding-right="5%">
|
||||||
|
<mj-text font-family="Nunito, Sans-Serif" align="center" font-size="18px">
|
||||||
|
Energy Consumption yesterday: {{yesterday}}
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text font-family="Nunito, Sans-Serif" algin="center" font-size="18px">
|
||||||
|
Energy Consumption since the start of the year: {{yearly}}
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
<mj-section padding-top="0px" border-right="2px solid #B0B0B0" border-left="2px solid #B0B0B0" border-bottom="2px solid #B0B0B0" border-radius="33px">
|
||||||
|
<mj-column>
|
||||||
|
<mj-button font-size="16px" mj-class="primary" font-weight="bold" font-family="Nunito, Sans-Serif">
|
||||||
|
<mj-text>
|
||||||
|
<a href="{{link}}" target="_blank" style="color:white; text-decoration:none;">Goto Dashboard</a>
|
||||||
|
</mj-text>
|
||||||
|
</mj-button>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</mj-wrapper>
|
||||||
|
|
||||||
|
</mj-body>
|
||||||
|
</mjml>
|
||||||
Reference in New Issue
Block a user