feat(email): export send attempt metadata
CI and Deploy / test (pull_request) Failing after 4m32s
CI and Deploy / deploy (pull_request) Has been skipped

Add content-free provider delivery history to encrypted and daily owner exports, exclude payload hashes, and lock in tenant-safe hard-delete cascades.
This commit is contained in:
cesnimda
2026-08-10 00:48:32 +02:00
parent 14f8d4e928
commit aff34cc645
6 changed files with 120 additions and 2 deletions
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using JobTrackerApi.Data;
using JobTrackerApi.Models;
namespace JobTrackerApi.Controllers
{
@@ -73,6 +74,21 @@ namespace JobTrackerApi.Controllers
.Where(e => jobIds.Contains(e.JobApplicationId))
.OrderBy(e => e.At)
.ToListAsync(cancellationToken);
var emailSendAttempts = await _db.EmailSendAttempts.AsNoTracking()
.Where(attempt => jobIds.Contains(attempt.JobApplicationId))
.OrderBy(attempt => attempt.CreatedAtUtc)
.Select(attempt => new EmailSendAttemptExport(
attempt.Id,
attempt.JobApplicationId,
attempt.Provider,
attempt.ClientRequestId,
attempt.Status,
attempt.ProviderMessageId,
attempt.FailureCategory,
attempt.CreatedAtUtc,
attempt.StartedAtUtc,
attempt.CompletedAtUtc))
.ToListAsync(cancellationToken);
var rules = await _db.RuleSettings.AsNoTracking().FirstOrDefaultAsync(cancellationToken);
return new
@@ -82,6 +98,7 @@ namespace JobTrackerApi.Controllers
Correspondence = correspondence,
Attachments = attachments,
Events = events,
EmailSendAttempts = emailSendAttempts,
Rules = rules
};
}
+12
View File
@@ -25,3 +25,15 @@ public sealed class EmailSendAttempt
public DateTime? StartedAtUtc { get; set; }
public DateTime? CompletedAtUtc { get; set; }
}
public sealed record EmailSendAttemptExport(
Guid Id,
int JobApplicationId,
string Provider,
string ClientRequestId,
string Status,
string? ProviderMessageId,
string? FailureCategory,
DateTime CreatedAtUtc,
DateTime? StartedAtUtc,
DateTime? CompletedAtUtc);
@@ -2,6 +2,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using JobTrackerApi.Data;
using JobTrackerApi.Models;
using Microsoft.EntityFrameworkCore;
namespace JobTrackerApi.Services;
@@ -61,6 +62,21 @@ public sealed class DailyExportHostedService(
Correspondence = await db.Correspondences.AsNoTracking().Where(message => jobIds.Contains(message.JobApplicationId)).OrderBy(message => message.Date).ToListAsync(cancellationToken),
Attachments = await db.Attachments.AsNoTracking().Where(attachment => jobIds.Contains(attachment.JobApplicationId)).OrderBy(attachment => attachment.UploadDate).ToListAsync(cancellationToken),
Events = await db.JobEvents.AsNoTracking().Where(jobEvent => jobIds.Contains(jobEvent.JobApplicationId)).OrderBy(jobEvent => jobEvent.At).ToListAsync(cancellationToken),
EmailSendAttempts = await db.EmailSendAttempts.AsNoTracking()
.Where(attempt => jobIds.Contains(attempt.JobApplicationId))
.OrderBy(attempt => attempt.CreatedAtUtc)
.Select(attempt => new EmailSendAttemptExport(
attempt.Id,
attempt.JobApplicationId,
attempt.Provider,
attempt.ClientRequestId,
attempt.Status,
attempt.ProviderMessageId,
attempt.FailureCategory,
attempt.CreatedAtUtc,
attempt.StartedAtUtc,
attempt.CompletedAtUtc))
.ToListAsync(cancellationToken),
Rules = await RulesEngine.GetSettings(db, cancellationToken),
};