using MimeKit; namespace AIStudio.Tools.Mail; /// /// Reads how important the sender marked a mail. /// /// /// Three headers say so, from three different eras, and mail programs send whichever they like, /// often more than one. They are read in this order, and the first one with a value AI Studio /// understands decides: /// /// Importance (RFC 2156): low, normal or high. Outlook sends it. /// X-Priority: a number from 1 (highest) to 5 (lowest), often followed by a word such as "1 (Highest)". /// Priority (RFC 2156): non-urgent, normal or urgent. /// /// A header with a value nobody defined is skipped rather than read as normal, so that the next /// header still gets its say. /// public static class MailImportanceDetection { /// /// Reads the importance from the header block of a mail. /// /// The header block. /// The importance, NORMAL when no header says otherwise. public static MailImportance Detect(HeaderList headers) => ReadImportance(headers[HeaderId.Importance]) ?? ReadXPriority(headers[HeaderId.XPriority]) ?? ReadPriority(headers[HeaderId.Priority]) ?? MailImportance.NORMAL; private static MailImportance? ReadImportance(string? value) => value?.Trim().ToLowerInvariant() switch { "low" => MailImportance.LOW, "normal" => MailImportance.NORMAL, "high" => MailImportance.HIGH, _ => null, }; private static MailImportance? ReadXPriority(string? value) { // Only the leading digit counts, as in "2 (High)", and it has to stand alone: var trimmed = value?.TrimStart(); if (string.IsNullOrEmpty(trimmed) || (trimmed.Length > 1 && char.IsDigit(trimmed[1]))) return null; return trimmed[0] switch { '1' or '2' => MailImportance.HIGH, '3' => MailImportance.NORMAL, '4' or '5' => MailImportance.LOW, _ => null, }; } private static MailImportance? ReadPriority(string? value) => value?.Trim().ToLowerInvariant() switch { "non-urgent" => MailImportance.LOW, "normal" => MailImportance.NORMAL, "urgent" => MailImportance.HIGH, _ => null, }; }