Files
SwiftMail/Sources/SwiftIMAP/IMAP/Handler/FetchPartHandler.swift

83 lines
2.9 KiB
Swift

// FetchPartHandler.swift
// A specialized handler for IMAP fetch part operations
import Foundation
@preconcurrency import NIOIMAP
import NIOIMAPCore
import NIO
import NIOConcurrencyHelpers
/// Handler for IMAP FETCH PART command
public final class FetchPartHandler: BaseIMAPCommandHandler<Data>, IMAPCommandHandler, @unchecked Sendable {
/// Collected message part data
private var partData: Data = Data()
/// Expected byte count for the streaming data
private var expectedByteCount: Int?
/// Handle a tagged OK response by succeeding the promise with the collected data
/// - Parameter response: The tagged response
override public func handleTaggedOKResponse(_ response: TaggedResponse) {
// Succeed with the collected data
succeedWithResult(lock.withLock { self.partData })
}
/// Handle a tagged error response
/// - Parameter response: The tagged response
override public func handleTaggedErrorResponse(_ response: TaggedResponse) {
failWithError(IMAPError.fetchFailed(String(describing: response.state)))
}
/// Process an incoming response
/// - Parameter response: The response to process
/// - Returns: Whether the response was handled by this handler
override public func processResponse(_ response: Response) -> Bool {
// Call the base class implementation to buffer the response
let handled = super.processResponse(response)
// Process fetch responses
if case .fetch(let fetchResponse) = response {
processFetchResponse(fetchResponse)
}
// Return the result from the base class
return handled
}
/// Process a fetch response
/// - Parameter fetchResponse: The fetch response to process
private func processFetchResponse(_ fetchResponse: FetchResponse) {
switch fetchResponse {
case .simpleAttribute(let attribute):
// Process simple attributes
processMessageAttribute(attribute)
case .streamingBegin(_, let byteCount):
// Store the expected byte count
expectedByteCount = byteCount
case .streamingBytes(let data):
// Collect the streaming body data
lock.withLock {
self.partData.append(Data(data.readableBytesView))
}
default:
break
}
}
/// Process a message attribute
/// - Parameter attribute: The attribute to process
private func processMessageAttribute(_ attribute: MessageAttribute) {
switch attribute {
case .body(_, _):
// We're primarily interested in the body data which comes through streaming
break
default:
break
}
}
}