feat: replace direct MailKit in cv-search-job with IEmailApiClient Refit call

- CvSearchEmailSender now injects IEmailApiClient instead of IConfiguration+MailKit
- BuildBody updated to produce styled HTML job cards
- CvSearchJobTask passes only filename (not full path) to email sender
- IEmailApiClient registered in Program.cs with EmailApi:BaseUrl + InternalApiKey
- MailKit removed from cv-search-job.csproj

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 16:19:49 +03:00
parent 8126e7c112
commit 6fad147650
4 changed files with 63 additions and 58 deletions
+4 -9
View File
@@ -22,7 +22,6 @@ public sealed class CvSearchJobTask : IJobTask
private readonly ICvMatcherInternalApi _matcherApi;
private readonly CvSearchEmailSender _emailSender;
private readonly ILogger<CvSearchJobTask> _logger;
private readonly string _fileStoragePath;
public string TaskType => "CvSearch";
@@ -32,7 +31,6 @@ public sealed class CvSearchJobTask : IJobTask
HtmlJobSearcher searcher,
ICvMatcherInternalApi matcherApi,
CvSearchEmailSender emailSender,
IConfiguration config,
ILogger<CvSearchJobTask> logger)
{
_scopeFactory = scopeFactory;
@@ -41,9 +39,6 @@ public sealed class CvSearchJobTask : IJobTask
_matcherApi = matcherApi;
_emailSender = emailSender;
_logger = logger;
_fileStoragePath = config["FileStorage:Path"] ?? "Files";
if (!Path.IsPathRooted(_fileStoragePath))
_fileStoragePath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), _fileStoragePath));
}
public async Task ExecuteAsync(IConfiguration parametersSection, CancellationToken cancellationToken)
@@ -85,8 +80,8 @@ public sealed class CvSearchJobTask : IJobTask
pending.Status = JobSearchStatus.Done;
await db.SaveChangesAsync(cancellationToken);
var attachmentPath = BuildCvPath(pending.CvDocumentId);
await _emailSender.SendResultsAsync(pending.Email, attachmentPath, results, pending.Language, cancellationToken);
var attachmentFileName = BuildCvFileName(pending.CvDocumentId);
await _emailSender.SendResultsAsync(pending.Email, attachmentFileName, results, pending.Language, cancellationToken);
_logger.LogInformation("Session {SessionId} done. {Count} results sent.", pending.Id, results.Count);
}
catch (Exception ex)
@@ -194,10 +189,10 @@ public sealed class CvSearchJobTask : IJobTask
return Uri.TryCreate(url, UriKind.Absolute, out var uri) ? uri.Host : "unknown";
}
private string BuildCvPath(string cvDocumentId)
private static string BuildCvFileName(string cvDocumentId)
{
var safeId = string.Concat(cvDocumentId.Where(char.IsLetterOrDigit));
if (string.IsNullOrWhiteSpace(safeId)) safeId = "cv";
return Path.Combine(_fileStoragePath, $"{safeId}.pdf");
return $"{safeId}.pdf";
}
}