using MimeKit; using MimeKit.Utils; namespace AIStudio.Tools.Mail; /// /// Reads the header fields of a mail which carry addresses, Message-IDs and the date. /// /// /// One place for all readers of a header block, the text of a mail as well as what the index /// keeps about it, so that both name the same people and the same date. /// public static class MailHeaders { /// /// Reads the addresses of all headers of one kind, e.g. both To lines of a mail which has two. /// /// /// Parsed from the raw header rather than from its decoded text: a display name may carry an /// encoded comma, as in "=?utf-8?q?Doe=2C_John?=", which decoded first would split one person /// into two. The members of a group are read as addresses of their own. /// /// The header block. /// The header, e.g. To. /// The addresses in their order, empty when there is no such header or none can be read. public static IReadOnlyList ReadMailboxes(HeaderList headers, HeaderId headerId) { var mailboxes = new List(); foreach (var header in headers.Where(header => header.Id == headerId)) { if (InternetAddressList.TryParse(ParserOptions.Default, header.RawValue, out var list)) mailboxes.AddRange(list.Mailboxes); } return mailboxes; } /// /// Reads the Message-IDs of a header, without their angle brackets. /// /// The header block. /// The header, e.g. References. /// The Message-IDs in their order, empty when there is no such header. public static IReadOnlyList ReadMessageIds(HeaderList headers, HeaderId headerId) { var value = headers[headerId]; return string.IsNullOrWhiteSpace(value) ? [] : MimeUtils.EnumerateReferences(value).ToList(); } /// /// Reads when the sender says the mail was written. /// /// The header block. /// The Date header, or null when there is none or it cannot be read. public static DateTimeOffset? ReadDate(HeaderList headers) => DateUtils.TryParse(headers[HeaderId.Date] ?? string.Empty, out var date) ? date : null; }