62 lines
3.7 KiB
Swift
62 lines
3.7 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import MikeMail
|
|
|
|
@MainActor
|
|
struct MailActionTests {
|
|
@Test func ccAndBccStaySeparateFromEnvelope() throws {
|
|
let raw = try MIME.compose(from: "sender@example.com", to: ["to@example.com"],
|
|
cc: ["copy@example.com"], bcc: ["hidden@example.com"], subject: "CC BCC", body: "Hello", attachments: [])
|
|
let headers = MIME.split(raw).0
|
|
#expect(headers["cc"] == "copy@example.com")
|
|
#expect(headers["bcc"] == nil)
|
|
#expect(!String(decoding: raw, as: UTF8.self).contains("hidden@example.com"))
|
|
#expect(MIME.parse(raw, id: "1").cc == "copy@example.com")
|
|
#expect(throws: (any Error).self) {
|
|
try MIME.compose(from: "sender@example.com", to: [], bcc: ["bad\r\nBcc: evil@example.com"],
|
|
subject: "No injection", body: "", attachments: [])
|
|
}
|
|
let blindOnly = try MIME.compose(from: "sender@example.com", to: [], bcc: ["hidden@example.com"],
|
|
subject: "Blind only", body: "", attachments: [])
|
|
#expect(MIME.split(blindOnly).0["bcc"] == nil)
|
|
}
|
|
|
|
@Test func replyUsesReplyToAndForwardIncludesAttachments() {
|
|
let attachment = MailAttachment(name: "sample.txt", mimeType: "text/plain", data: Data("abc".utf8))
|
|
let mail = MailMessage(id: "id", sender: "Sender <from@example.com>", recipient: "to@example.com",
|
|
subject: "Question", date: Date(), body: "Original", attachments: [attachment], replyTo: "Reply <reply@example.com>")
|
|
let account = UUID()
|
|
let reply = ComposeDraft.from(mail, accountID: account, forwarding: false)
|
|
#expect(reply.recipient == "reply@example.com")
|
|
#expect(reply.accountID == account)
|
|
#expect(reply.body.contains("> Original"))
|
|
#expect(reply.attachments.isEmpty)
|
|
let forward = ComposeDraft.from(mail, accountID: account, forwarding: true)
|
|
#expect(forward.recipient.isEmpty)
|
|
#expect(forward.attachments.first?.data == attachment.data)
|
|
}
|
|
|
|
@Test func newAccountRequiresValidationAndFlagsDriveCounts() throws {
|
|
let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString)
|
|
defer { try? FileManager.default.removeItem(at: root) }
|
|
let archive = try MailArchive(root: root)
|
|
try archive.saveConfiguration(ArchiveConfiguration(accounts: [], folders: [:], recipients: []))
|
|
let store = MailStore(archive: archive)
|
|
let account = MailAccount(name: "New", email: "new@example.com", username: "new", host: "example.com")
|
|
#expect(throws: (any Error).self) { try store.save(account: account, password: "unused") }
|
|
#expect(store.accounts.isEmpty)
|
|
let folder = MailFolder(accountID: account.id, path: "INBOX", name: "Inbox")
|
|
let raw = Data("Subject: Flags\r\nMessage-ID: <fixture@example.com>\r\n\r\nBody".utf8)
|
|
try archive.store(raw: raw, folderID: folder.id, validity: "1", uid: "1", flags: [])
|
|
#expect(try archive.unreadCounts()[folder.id] == 1)
|
|
try archive.reconcile(folderID: folder.id, inventory: MailboxInventory(validity: "1", flags: [1: ["\\Seen"]]))
|
|
#expect(try archive.unreadCounts()[folder.id] == nil)
|
|
try archive.store(raw: raw, folderID: account.id.uuidString + ":__local_outgoing__",
|
|
validity: "local", uid: "outgoing", flags: ["\\Seen", "SentCopyPending"])
|
|
#expect(try archive.pendingSent(accountID: account.id).count == 1)
|
|
try archive.store(raw: raw, folderID: account.id.uuidString + ":__local_outgoing__",
|
|
validity: "local", uid: "outgoing", flags: ["\\Seen", "SentCopied"], visible: false)
|
|
#expect(try archive.pendingSent(accountID: account.id).isEmpty)
|
|
}
|
|
}
|