diff --git a/Packages/MagnumOpusCore/Sources/MailStore/Queries.swift b/Packages/MagnumOpusCore/Sources/MailStore/Queries.swift index 8c04a52..e4a002e 100644 --- a/Packages/MagnumOpusCore/Sources/MailStore/Queries.swift +++ b/Packages/MagnumOpusCore/Sources/MailStore/Queries.swift @@ -82,8 +82,29 @@ extension MailStore { ISO8601DateFormatter() }() - static func parseDate(_ iso: String) -> Date? { - isoFormatterWithFractional.date(from: iso) ?? isoFormatter.date(from: iso) + nonisolated(unsafe) private static let rfc2822Formatter: DateFormatter = { + let f = DateFormatter() + f.locale = Locale(identifier: "en_US_POSIX") + f.dateFormat = "EEE, dd MMM yyyy HH:mm:ss Z" + return f + }() + + nonisolated(unsafe) private static let rfc2822FormatterNoDow: DateFormatter = { + let f = DateFormatter() + f.locale = Locale(identifier: "en_US_POSIX") + f.dateFormat = "dd MMM yyyy HH:mm:ss Z" + return f + }() + + static func parseDate(_ dateString: String) -> Date? { + let trimmed = dateString.trimmingCharacters(in: .whitespaces) + // Try ISO 8601 first + if let d = isoFormatterWithFractional.date(from: trimmed) { return d } + if let d = isoFormatter.date(from: trimmed) { return d } + // Try RFC 2822 (IMAP envelope date format) + if let d = rfc2822Formatter.date(from: trimmed) { return d } + if let d = rfc2822FormatterNoDow.date(from: trimmed) { return d } + return nil } public static func toMessageSummary(_ record: MessageRecord) -> MessageSummary { diff --git a/Packages/MagnumOpusCore/Sources/SyncEngine/SyncCoordinator.swift b/Packages/MagnumOpusCore/Sources/SyncEngine/SyncCoordinator.swift index d1e931f..d626191 100644 --- a/Packages/MagnumOpusCore/Sources/SyncEngine/SyncCoordinator.swift +++ b/Packages/MagnumOpusCore/Sources/SyncEngine/SyncCoordinator.swift @@ -277,6 +277,9 @@ public final class SyncCoordinator { ) -> MessageRecord { let toJson = encodeAddresses(envelope.to) let ccJson = encodeAddresses(envelope.cc) + // Decode RFC 2047 encoded words in subject and sender name + let decodedSubject = envelope.subject.map { RFC2047Decoder.decode($0) } + let decodedFromName = envelope.from?.name.map { RFC2047Decoder.decode($0) } return MessageRecord( id: UUID().uuidString, accountId: accountId, @@ -285,9 +288,9 @@ public final class SyncCoordinator { messageId: envelope.messageId, inReplyTo: envelope.inReplyTo, refs: envelope.references, - subject: envelope.subject, + subject: decodedSubject, fromAddress: envelope.from?.address, - fromName: envelope.from?.name, + fromName: decodedFromName, toAddresses: toJson, ccAddresses: ccJson, date: envelope.date,