/bin/bash: ligne 1: q : commande introuvable

This commit is contained in:
Paul Schneider 2026-08-29 15:36:36 +01:00
commit c27091051b
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
4 changed files with 82 additions and 32 deletions

View file

@ -7,7 +7,5 @@
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.9" /> <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.9" /> <PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.9" /> <PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.9" />
<PackageVersion Include="xunit.v3.common" Version="3.2.2" />
<PackageVersion Include="xunit.v3.extensibility.core" Version="3.2.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -55,5 +55,6 @@ namespace Yavsc.Org.Tests
client.Calls.Select(c => c.Kind).ToArray()); client.Calls.Select(c => c.Kind).ToArray());
Assert.Equal(_serverFixture.SiteSettings.Owner.EMail, client.LastSentMessage?.To.Mailboxes.First().Address); Assert.Equal(_serverFixture.SiteSettings.Owner.EMail, client.LastSentMessage?.To.Mailboxes.First().Address);
} }
} }
} }

View file

@ -20,6 +20,5 @@
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.9" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.9" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.2.2" /> <PackageVersion Include="Swashbuckle.AspNetCore" Version="10.2.2" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="10.0.9" /> <PackageVersion Include="System.Security.Cryptography.Pkcs" Version="10.0.9" />
<PackageVersion Include="YamlDotNet" Version="18.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -9,6 +9,7 @@ using Yavsc.Settings;
using Yavsc.Models; using Yavsc.Models;
using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Text.RegularExpressions;
using System.Web; using System.Web;
namespace Yavsc.Services namespace Yavsc.Services
@ -56,13 +57,53 @@ namespace Yavsc.Services
return SendEmailAsync(null, email, subject, htmlMessage); return SendEmailAsync(null, email, subject, htmlMessage);
} }
internal static MailboxAddress BuildMailboxAddress(string? displayName, string? rawAddress)
{
if (string.IsNullOrWhiteSpace(rawAddress))
{
throw new FormatException("Email address is empty.");
}
var candidate = rawAddress.Trim();
if (candidate.Contains('<') || candidate.Contains('>'))
{
var emailMatch = Regex.Match(candidate,
@"[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}",
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
if (emailMatch.Success)
{
candidate = emailMatch.Value;
}
else
{
candidate = candidate.Trim('<', '>', '"', '\'');
}
}
candidate = candidate.Trim('"', '\'', '<', '>', ' ');
candidate = candidate.Replace(" ", string.Empty);
if (!MailboxAddress.TryParse(candidate, out var parsedAddress))
{
throw new FormatException($"Invalid email address '{rawAddress}'.");
}
var safeName = string.IsNullOrWhiteSpace(displayName)
? parsedAddress.Name
: displayName.Trim();
return new MailboxAddress(safeName ?? string.Empty, parsedAddress.Address);
}
public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage) public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage)
{
try
{ {
logger.LogInformation($"SendEmail for {email} : {subject}"); logger.LogInformation($"SendEmail for {email} : {subject}");
MimeMessage msg = new(); MimeMessage msg = new();
msg.From.Add(new MailboxAddress(siteSettings.Owner.Name, msg.From.Add(BuildMailboxAddress(siteSettings.Owner.Name, siteSettings.Owner.EMail));
siteSettings.Owner.EMail)); msg.To.Add(BuildMailboxAddress(name, email));
msg.To.Add(new MailboxAddress(name, email));
TextPart text; TextPart text;
msg.Body = text = new TextPart("html") msg.Body = text = new TextPart("html")
{ {
@ -93,6 +134,17 @@ namespace Yavsc.Services
} }
return msg.MessageId; return msg.MessageId;
} }
catch (FormatException ex)
{
logger.LogError(ex, "Refusing to send email because the recipient or sender address is malformed. To={To}, From={From}", email, siteSettings.Owner.EMail);
return string.Empty;
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to send email. To={To}, Subject={Subject}", email, subject);
throw;
}
}
public void SendEmailFromCriteria(string Criteria) public void SendEmailFromCriteria(string Criteria)
{ {