165 lines
4.3 KiB
Swift
165 lines
4.3 KiB
Swift
import Testing
|
|
@testable import IMailSync
|
|
|
|
@Suite("MIMEParser")
|
|
struct MIMEParserTests {
|
|
|
|
// MARK: - Header parsing
|
|
|
|
@Test("Parses Message-ID stripping angle brackets")
|
|
func messageId() {
|
|
let raw = """
|
|
Message-ID: <abc123@mail.example.com>
|
|
Subject: Hello
|
|
|
|
Body
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.messageId == "abc123@mail.example.com")
|
|
}
|
|
|
|
@Test("Parses basic text/plain message")
|
|
func plainTextBody() {
|
|
let raw = """
|
|
Content-Type: text/plain; charset=utf-8
|
|
Subject: Test
|
|
|
|
Hello, world!
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "Hello, world!")
|
|
#expect(msg.html == nil)
|
|
}
|
|
|
|
@Test("Parses From header into address and name")
|
|
func fromHeader() {
|
|
let raw = """
|
|
From: Quinn Test <quinn@example.com>
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.from?.address == "quinn@example.com")
|
|
#expect(msg.from?.name == "Quinn Test")
|
|
}
|
|
|
|
@Test("Parses bare email address in From")
|
|
func fromHeaderBare() {
|
|
let raw = """
|
|
From: quinn@example.com
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.from?.address == "quinn@example.com")
|
|
#expect(msg.from?.name == nil)
|
|
}
|
|
|
|
@Test("Parses multiple To recipients")
|
|
func toRecipients() {
|
|
let raw = """
|
|
To: Alice <alice@example.com>, bob@example.com
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.to.count == 2)
|
|
#expect(msg.to[0].address == "alice@example.com")
|
|
#expect(msg.to[0].name == "Alice")
|
|
#expect(msg.to[1].address == "bob@example.com")
|
|
#expect(msg.to[1].name == nil)
|
|
}
|
|
|
|
// MARK: - Multipart
|
|
|
|
@Test("Extracts text and html from multipart/alternative")
|
|
func multipartAlternative() {
|
|
let boundary = "----=_Part_1"
|
|
let raw = """
|
|
Content-Type: multipart/alternative; boundary="\(boundary)"
|
|
|
|
--\(boundary)
|
|
Content-Type: text/plain; charset=utf-8
|
|
|
|
Plain text body
|
|
|
|
--\(boundary)
|
|
Content-Type: text/html; charset=utf-8
|
|
|
|
<html><body>HTML body</body></html>
|
|
|
|
--\(boundary)--
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.text?.contains("Plain text body") == true)
|
|
#expect(msg.html?.contains("HTML body") == true)
|
|
}
|
|
|
|
@Test("Detects attachments in multipart/mixed")
|
|
func multipartMixedAttachment() {
|
|
let boundary = "----=_Part_2"
|
|
let raw = """
|
|
Content-Type: multipart/mixed; boundary="\(boundary)"
|
|
|
|
--\(boundary)
|
|
Content-Type: text/plain
|
|
|
|
Message body
|
|
|
|
--\(boundary)
|
|
Content-Type: application/pdf
|
|
Content-Disposition: attachment; filename="file.pdf"
|
|
|
|
<binary>
|
|
|
|
--\(boundary)--
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.hasAttachments == true)
|
|
}
|
|
|
|
// MARK: - RFC 2047
|
|
|
|
@Test("Decodes Base64-encoded RFC 2047 subject")
|
|
func rfc2047Base64() {
|
|
// =?UTF-8?B?SGVsbG8gV29ybGQ=?= decodes to "Hello World"
|
|
let raw = """
|
|
Subject: =?UTF-8?B?SGVsbG8gV29ybGQ=?=
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.subject == "Hello World")
|
|
}
|
|
|
|
@Test("Decodes Q-encoded RFC 2047 subject")
|
|
func rfc2047QEncoded() {
|
|
// =?iso-8859-1?Q?Caf=E9?= decodes to "Café"
|
|
let raw = """
|
|
Subject: =?iso-8859-1?Q?Caf=E9?=
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.subject?.hasPrefix("Caf") == true)
|
|
}
|
|
|
|
// MARK: - References
|
|
|
|
@Test("Parses References header into array")
|
|
func referencesHeader() {
|
|
let raw = """
|
|
References: <ref1@example.com> <ref2@example.com>
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.references.count == 2)
|
|
#expect(msg.references[0] == "ref1@example.com")
|
|
#expect(msg.references[1] == "ref2@example.com")
|
|
}
|
|
|
|
@Test("Parses In-Reply-To stripping angle brackets")
|
|
func inReplyTo() {
|
|
let raw = """
|
|
In-Reply-To: <parent@example.com>
|
|
|
|
"""
|
|
let msg = MIMEParser.parse(raw)
|
|
#expect(msg.inReplyTo == "parent@example.com")
|
|
}
|
|
}
|