Files
ssh-access-tui/outlook-bulk-sender/BulkArchiveMailer.Core/SendJob.cs
T
2026-07-23 12:38:13 +03:00

77 lines
3.0 KiB
C#

using System.Collections.Generic;
using System.IO;
namespace BulkArchiveMailer.Core
{
/// <summary>Status of one preview row / send attempt.</summary>
public enum SendStatus
{
/// <summary>Exactly one archive found for this login, nothing sent for it yet - safe to send.</summary>
Ready,
/// <summary>A prior log entry shows this exact archive (by SHA-256) was already sent to this address.</summary>
AlreadySent,
/// <summary>Blocking data problem (e.g. both archive kinds present for one login) - never sendable.</summary>
Error,
/// <summary>File in the folder did not match the expected naming pattern - listed for visibility, not sendable.</summary>
Skipped
}
/// <summary>
/// One row of the send preview: everything needed to either display the
/// row in the grid or hand it to MailSender.
/// </summary>
public sealed class SendJob
{
public string Login { get; set; } = "";
public string Email { get; set; } = "";
/// <summary>Null for Error rows caused by a login/kind conflict, and for Skipped (unrecognized file) rows.</summary>
public ArchiveKind? Kind { get; set; }
/// <summary>Null for conflict Error rows (see <see cref="ConflictingArchivePaths"/>) - otherwise the single archive to attach.</summary>
public string ArchivePath { get; set; }
/// <summary>Populated only for the "both kinds present" Error case: every archive path found for that login.</summary>
public IReadOnlyList<string> ConflictingArchivePaths { get; set; }
public string Subject { get; set; } = "";
public string BodyHtml { get; set; } = "";
public SendStatus Status { get; set; } = SendStatus.Ready;
/// <summary>Human-readable explanation, set for Error/Skipped rows and for AlreadySent rows (when it was sent).</summary>
public string ErrorMessage { get; set; }
/// <summary>SHA-256 of ArchivePath's current bytes, computed when a SendLogStore is available. Used for the AlreadySent dedup key.</summary>
public string FileSha256 { get; set; }
/// <summary>Whether this row is even eligible to be checked/sent in the preview grid.</summary>
public bool IsSelectable => Status == SendStatus.Ready || Status == SendStatus.AlreadySent;
public string FileName => string.IsNullOrEmpty(ArchivePath) ? "" : Path.GetFileName(ArchivePath);
public string KindDisplay
{
get
{
switch (Kind)
{
case ArchiveKind.SshAccess:
return "Новый доступ (ключ + конфиг)";
case ArchiveKind.ConfigUpdate:
return "Обновление конфига";
default:
return "-";
}
}
}
public override string ToString() => $"{Login} <{Email}> [{Status}]";
}
}