mirror of
https://github.com/BZmHackTeam/BezpiecznaZywnosc
synced 2024-12-22 22:46:59 +01:00
Minimum Viable Mailsender
This commit is contained in:
parent
f6f6c17555
commit
b77acdb322
6 changed files with 147 additions and 11 deletions
15
src/Nyanlabs.SFood.Api/Controllers/ApiController.cs
Normal file
15
src/Nyanlabs.SFood.Api/Controllers/ApiController.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Nyanlabs.SFood.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("/api")]
|
||||||
|
public class ApiController : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet("version")]
|
||||||
|
public string Version() => "1.0.0E";
|
||||||
|
}
|
39
src/Nyanlabs.SFood.Api/Controllers/IncidentController.cs
Normal file
39
src/Nyanlabs.SFood.Api/Controllers/IncidentController.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Mail;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Nyanlabs.SFood.Api.Models;
|
||||||
|
using Nyanlabs.SFood.Api.Services;
|
||||||
|
|
||||||
|
namespace Nyanlabs.SFood.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/incident")]
|
||||||
|
public class IncidentController : ControllerBase
|
||||||
|
{
|
||||||
|
public IncidentController(EmailClient mail)
|
||||||
|
{
|
||||||
|
_mail = mail;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly EmailClient _mail;
|
||||||
|
|
||||||
|
[HttpPost("submit")]
|
||||||
|
public async Task<IActionResult> SubmitIncident([FromForm] IncidentSubmission incident)
|
||||||
|
{
|
||||||
|
string body = $@"<p>Dziękujemy za zgłoszenie incydentu.<p>
|
||||||
|
<p>Dane zgłoszenia:<br/>
|
||||||
|
<b>Identyfikator zgłoszenia:</b> {Random.Shared.NextInt64()}<br/>
|
||||||
|
<b>Produkt:</b> {incident.ProductName}<br/>
|
||||||
|
<b>Producent:</b> {incident.Producer}<br/>
|
||||||
|
<b>Opis incydentu:</b> {incident.Description}<br/>
|
||||||
|
<b>Miejsce zdarzenia:</b> {incident.Location}<br/>
|
||||||
|
<b>Data zgłoszenia:</b> {incident.Submitted.ToLongDateString()}
|
||||||
|
</p>";
|
||||||
|
|
||||||
|
return (await _mail.SendRawAsync(incident.SubmitterAddress, body)) ? NoContent() : BadRequest();
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,13 +10,11 @@ namespace Nyanlabs.SFood.Api.Models;
|
||||||
public class IncidentSubmission
|
public class IncidentSubmission
|
||||||
{
|
{
|
||||||
//TODO: Validation
|
//TODO: Validation
|
||||||
[Key]
|
|
||||||
public long Id { get; set; }
|
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
public DateTime Submitted { get; set; }
|
public DateTime Submitted { get; set; } = DateTime.Now;
|
||||||
[EmailAddress]
|
[EmailAddress]
|
||||||
public string? SubmitterAddress { get; set; }
|
public required string SubmitterAddress { get; set; }
|
||||||
public required string ProductName { get; set; }
|
public required string ProductName { get; set; }
|
||||||
public required string Producer { get; set; }
|
public required string Producer { get; set; }
|
||||||
public required string Description { get; set; }
|
public required string Description { get; set; }
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MailKit" Version="4.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.12" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.12" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.12">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.12">
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Nyanlabs.SFood.Api;
|
using Nyanlabs.SFood.Api;
|
||||||
|
using Nyanlabs.SFood.Api.Services;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.Configure<EmailClientOptions>(o => builder.Configuration.GetSection("EmailClient").Bind(o));
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
builder.Services.AddScoped<EmailClient>();
|
||||||
|
|
||||||
builder.Services.AddDbContext<DataContext>(o =>
|
// builder.Services.AddDbContext<DataContext>(o =>
|
||||||
{
|
// {
|
||||||
if (builder.Environment.IsDevelopment())
|
// if (builder.Environment.IsDevelopment())
|
||||||
{
|
// {
|
||||||
o.UseSqlite("Data Source=/data/store.db;");
|
// o.UseSqlite("Data Source=/data/store.db;");
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
79
src/Nyanlabs.SFood.Api/Services/EmailClient.cs
Normal file
79
src/Nyanlabs.SFood.Api/Services/EmailClient.cs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MailKit.Net.Smtp;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace Nyanlabs.SFood.Api.Services;
|
||||||
|
|
||||||
|
public class EmailClient : IDisposable
|
||||||
|
{
|
||||||
|
public EmailClient(IOptions<EmailClientOptions> opts)
|
||||||
|
{
|
||||||
|
_opts = opts.Value;
|
||||||
|
_cli = new();
|
||||||
|
_cli.Connect(_opts.Host, _opts.Port, true);
|
||||||
|
|
||||||
|
if (!_cli.IsConnected)
|
||||||
|
{
|
||||||
|
throw new DataException($"Cannot connect to {_opts.Host}:{_opts.Port}...");
|
||||||
|
}
|
||||||
|
|
||||||
|
var credentials = new NetworkCredential(_opts.User, _opts.Password);
|
||||||
|
_cli.Authenticate(credentials);
|
||||||
|
if (!_cli.IsAuthenticated)
|
||||||
|
{
|
||||||
|
throw new DataException($"{_opts.Host}:{_opts.Port}: Cannot authenticate user {_opts.User}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly EmailClientOptions _opts;
|
||||||
|
private readonly SmtpClient _cli;
|
||||||
|
|
||||||
|
public async Task<bool> SendAsync([EmailAddress] string addr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<bool> SendRawAsync([EmailAddress] string addr, string html)
|
||||||
|
{
|
||||||
|
MimeMessage msg = new();
|
||||||
|
msg.From.Add(new MailboxAddress(_opts.FromName, _opts.FromAddr));
|
||||||
|
|
||||||
|
var recipient = new MailboxAddress(addr, addr);
|
||||||
|
|
||||||
|
if (recipient is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.To.Add(recipient);
|
||||||
|
|
||||||
|
msg.Subject = "Zgłoszenie przyjęte";
|
||||||
|
msg.Body = new TextPart("html", html);
|
||||||
|
|
||||||
|
string result = await _cli.SendAsync(msg);
|
||||||
|
return result.StartsWith("2.") && result.Contains("ok", StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_cli.Disconnect(true);
|
||||||
|
_cli.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record EmailClientOptions
|
||||||
|
{
|
||||||
|
public required string Host { get; set; }
|
||||||
|
public required string User { get; set; }
|
||||||
|
public required string Password { get; set; }
|
||||||
|
public required string FromName { get; set; }
|
||||||
|
public required string FromAddr { get; set; }
|
||||||
|
public int Port { get; set; } = 465;
|
||||||
|
};
|
Loading…
Reference in a new issue