mirror of
https://github.com/Cocoanetics/SwiftMail.git
synced 2026-03-17 20:02:25 +00:00
Replace ID command dictionary with Identification struct
This commit is contained in:
@@ -4,17 +4,17 @@ import OrderedCollections
|
||||
|
||||
/// Command for IMAP ID.
|
||||
struct IDCommand: IMAPCommand {
|
||||
typealias ResultType = IDResponse
|
||||
typealias ResultType = Identification
|
||||
typealias HandlerType = IDHandler
|
||||
|
||||
/// Client identification parameters.
|
||||
let parameters: OrderedDictionary<String, String?>
|
||||
let identification: Identification
|
||||
|
||||
init(parameters: OrderedDictionary<String, String?> = [:]) {
|
||||
self.parameters = parameters
|
||||
init(identification: Identification = Identification()) {
|
||||
self.identification = identification
|
||||
}
|
||||
|
||||
func toTaggedCommand(tag: String) -> TaggedCommand {
|
||||
TaggedCommand(tag: tag, command: .id(parameters))
|
||||
TaggedCommand(tag: tag, command: .id(identification.nioParameters))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import NIOConcurrencyHelpers
|
||||
import OrderedCollections
|
||||
|
||||
/// Handler for the IMAP ID command.
|
||||
final class IDHandler: BaseIMAPCommandHandler<IDResponse>, IMAPCommandHandler, @unchecked Sendable {
|
||||
final class IDHandler: BaseIMAPCommandHandler<Identification>, IMAPCommandHandler, @unchecked Sendable {
|
||||
private var responseParams: OrderedDictionary<String, String?> = [:]
|
||||
|
||||
override func handleUntaggedResponse(_ response: Response) -> Bool {
|
||||
@@ -19,7 +19,7 @@ final class IDHandler: BaseIMAPCommandHandler<IDResponse>, IMAPCommandHandler, @
|
||||
|
||||
override func handleTaggedOKResponse(_ response: TaggedResponse) {
|
||||
let params = lock.withLock { responseParams }
|
||||
succeedWithResult(IDResponse(parameters: params))
|
||||
succeedWithResult(Identification(parameters: params))
|
||||
}
|
||||
|
||||
override func handleTaggedErrorResponse(_ response: TaggedResponse) {
|
||||
|
||||
@@ -212,19 +212,15 @@ public actor IMAPServer {
|
||||
}
|
||||
|
||||
/// Identify the client to the server using the `ID` command.
|
||||
/// - Parameter parameters: Key/value pairs describing the client. Pass an empty dictionary to send no information.
|
||||
/// - Parameter identification: Information describing the client. Pass the default value to send no information.
|
||||
/// - Returns: Information returned by the server.
|
||||
/// - Throws: ``IMAPError.commandNotSupported`` if the server does not support the command or ``IMAPError.commandFailed`` on failure.
|
||||
public func id(parameters: [String: String?] = [:]) async throws -> IDResponse {
|
||||
public func id(_ identification: Identification = Identification()) async throws -> Identification {
|
||||
guard capabilities.contains(.id) else {
|
||||
throw IMAPError.commandNotSupported("ID command not supported by server")
|
||||
}
|
||||
|
||||
var ordered = OrderedDictionary<String, String?>()
|
||||
for (key, value) in parameters {
|
||||
ordered[key] = value
|
||||
}
|
||||
let command = IDCommand(parameters: ordered)
|
||||
let command = IDCommand(identification: identification)
|
||||
return try await executeCommand(command)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import Foundation
|
||||
import OrderedCollections
|
||||
|
||||
/// Information returned by the IMAP `ID` command.
|
||||
///
|
||||
/// The server may return any key/value pairs describing its
|
||||
/// implementation. Values may be `nil` if the server omits them.
|
||||
public struct IDResponse: Sendable {
|
||||
/// Raw key/value pairs returned by the server.
|
||||
public var parameters: OrderedDictionary<String, String?>
|
||||
|
||||
/// Create a new response with the provided parameters.
|
||||
public init(parameters: OrderedDictionary<String, String?> = [:]) {
|
||||
self.parameters = parameters
|
||||
}
|
||||
|
||||
/// Access a value by key.
|
||||
public subscript(key: String) -> String? {
|
||||
parameters[key] ?? nil
|
||||
}
|
||||
|
||||
/// Commonly used name field of the server.
|
||||
public var name: String? { self["name"] }
|
||||
|
||||
/// Server version string if provided.
|
||||
public var version: String? { self["version"] }
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import Foundation
|
||||
import OrderedCollections
|
||||
|
||||
/// Client or server identification information used with the IMAP `ID` command.
|
||||
///
|
||||
/// The most common fields defined by RFC 2971 are provided as stored
|
||||
/// properties. Additional parameters that do not match these fields can
|
||||
/// be accessed via the subscript operator.
|
||||
public struct Identification: Sendable {
|
||||
/// Product name of the client or server.
|
||||
public var name: String?
|
||||
/// Product version string.
|
||||
public var version: String?
|
||||
/// Operating system name.
|
||||
public var os: String?
|
||||
/// Operating system version string.
|
||||
public var osVersion: String?
|
||||
/// Name of the vendor.
|
||||
public var vendor: String?
|
||||
/// Support contact URL.
|
||||
public var supportURL: String?
|
||||
|
||||
/// Any additional parameters returned by the server.
|
||||
public var additional: [String: String?]
|
||||
|
||||
/// Create a new identification value.
|
||||
public init(
|
||||
name: String? = nil,
|
||||
version: String? = nil,
|
||||
os: String? = nil,
|
||||
osVersion: String? = nil,
|
||||
vendor: String? = nil,
|
||||
supportURL: String? = nil,
|
||||
additional: [String: String?] = [:]
|
||||
) {
|
||||
self.name = name
|
||||
self.version = version
|
||||
self.os = os
|
||||
self.osVersion = osVersion
|
||||
self.vendor = vendor
|
||||
self.supportURL = supportURL
|
||||
self.additional = additional
|
||||
}
|
||||
|
||||
/// Create an Identification from raw parameters received from NIOIMAP.
|
||||
internal init(parameters: OrderedDictionary<String, String?>) {
|
||||
self.name = parameters["name"] ?? nil
|
||||
self.version = parameters["version"] ?? nil
|
||||
self.os = parameters["os"] ?? nil
|
||||
self.osVersion = parameters["os-version"] ?? nil
|
||||
self.vendor = parameters["vendor"] ?? nil
|
||||
self.supportURL = parameters["support-url"] ?? nil
|
||||
var other: [String: String?] = [:]
|
||||
for (key, value) in parameters where !Self.knownKeys.contains(key) {
|
||||
other[key] = value
|
||||
}
|
||||
self.additional = other
|
||||
}
|
||||
|
||||
/// Access a parameter by key.
|
||||
public subscript(key: String) -> String? {
|
||||
switch key {
|
||||
case "name": return name
|
||||
case "version": return version
|
||||
case "os": return os
|
||||
case "os-version": return osVersion
|
||||
case "vendor": return vendor
|
||||
case "support-url": return supportURL
|
||||
default: return additional[key] ?? nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert this Identification into the ordered dictionary format expected by NIOIMAP.
|
||||
internal var nioParameters: OrderedDictionary<String, String?> {
|
||||
var params: OrderedDictionary<String, String?> = [:]
|
||||
params["name"] = name
|
||||
params["version"] = version
|
||||
params["os"] = os
|
||||
params["os-version"] = osVersion
|
||||
params["vendor"] = vendor
|
||||
params["support-url"] = supportURL
|
||||
for (k, v) in additional {
|
||||
params[k] = v
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
/// Keys that map directly to stored properties.
|
||||
private static let knownKeys: Set<String> = [
|
||||
"name", "version", "os", "os-version", "vendor", "support-url"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user