Swift implementation of RFC 5321: Simple Mail Transfer Protocol (SMTP) - email address validation and formatting standard.
RFC 5321 defines the SMTP protocol and email address format used for electronic mail transmission. This package provides a pure Swift implementation of RFC 5321-compliant email address validation, parsing, and formatting, supporting both simple addresses and addresses with display names.
The package handles email address components including local-parts (before @), domains (after @), and optional display names, with full validation according to RFC 5321 specifications including length limits and character restrictions.
- RFC 5321 Compliant: Full validation of email addresses per SMTP specification
- Display Name Support: Parse and format addresses like "John Doe [email protected]"
- Local Part Validation: Support for both dot-atom and quoted-string formats
- Domain Integration: Built on RFC 1123 domain validation
- Length Validation: Enforces RFC 5321 length limits (64 chars for local-part, 254 total)
- Type-Safe API: Structured components with compile-time safety
- Codable Support: Seamless JSON encoding/decoding
Add swift-rfc-5321 to your package dependencies:
dependencies: [
.package(url: "https://github.com/swift-standards/swift-rfc-5321.git", from: "0.1.0")
]Then add it to your target:
.target(
name: "YourTarget",
dependencies: [
.product(name: "RFC_5321", package: "swift-rfc-5321")
]
)import RFC_5321
// Parse simple email address
let email = try EmailAddress("[email protected]")
print(email.localPart.stringValue) // "user"
print(email.domain.name) // "example.com"
// Parse with display name
let namedEmail = try EmailAddress("John Doe <[email protected]>")
print(namedEmail.displayName) // "John Doe"
print(namedEmail.addressValue) // "[email protected]"
// Parse with quoted display name
let quotedEmail = try EmailAddress("\"Doe, John\" <[email protected]>")
print(quotedEmail.displayName) // "Doe, John"// Create from components
let localPart = try EmailAddress.LocalPart("support")
let domain = try Domain("example.com")
let email = EmailAddress(
displayName: "Support Team",
localPart: localPart,
domain: domain
)
print(email.stringValue) // "Support Team <[email protected]>"
print(email.addressValue) // "[email protected]"// Valid addresses
let valid1 = try EmailAddress("[email protected]")
let valid2 = try EmailAddress("[email protected]")
let valid3 = try EmailAddress("\"user name\"@example.com")
// Invalid addresses throw errors
do {
let invalid = try EmailAddress("no-at-sign")
} catch EmailAddress.ValidationError.missingAtSign {
print("Missing @ symbol")
}
do {
let tooLong = try EmailAddress("verylonglocalpartthatexceedssixtyfourcharactersshouldnotbeallowed@example.com")
} catch EmailAddress.ValidationError.localPartTooLong(let length) {
print("Local part too long: \(length) characters")
}The core EmailAddress type provides structured access to email components:
public struct EmailAddress: Hashable, Sendable {
public let displayName: String?
public let localPart: LocalPart
public let domain: Domain
public init(displayName: String?, localPart: LocalPart, domain: Domain)
public init(_ string: String) throws
public var stringValue: String // Full format with display name
public var addressValue: String // Just the email address part
}The local-part (before @) supports both dot-atom and quoted formats:
public struct LocalPart: Hashable, Sendable {
public init(_ string: String) throws
public var stringValue: String
}Valid local-part formats:
- Dot-atom:
user,user.name,first.last - Quoted:
"user name","user@name","special!chars"
Uses RFC 1123 domain validation (re-exported from swift-rfc-1123):
let domain = try Domain("mail.example.com")public enum ValidationError: Error {
case missingAtSign
case invalidDotAtom
case invalidQuotedString
case localPartTooLong(Int)
case totalLengthExceeded(Int)
}- swift-rfc-1123 - Domain name validation per RFC 1123
- swift-rfc-5322 - Extended email address format (Internet Message Format)
- swift-rfc-6531 - Internationalized email addresses (SMTPUTF8)
- Swift 6.0+
- macOS 13.0+ / iOS 16.0+
This library is released under the Apache License 2.0. See LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request.