The types related to the bodystructure are essential to code trying do things such as
decide which parts of messages to download (as opposed to downloading the complete message including attachments)
display message previews and/or display message without MIME parsing
The body structure is very complex and recursive. Here’s an attempt at making it a bit more approachable.
Note: I’m being a bit lax about the use of String vs. NString here — need to revise that.
Structure
As noted in #75 the top level structure should be something like
public indirect enum BodyStructure: Equatable {
case singlePart(BodyStructure.SinglePart)
case multiPart(BodyStructure.MultiPart)
}
Then, generally, nest body structure related types inside BodyStructure.
Single Part
A single part would look like this:
extension BodyStructure {
public struct SinglePart: Equatable {
public var bodyFields: Fields
public var kind: Kind
public var extension: BodyStructure.SinglePart.ExtensionData?
public var mediaType: MediaType { get } // derived from `kind`
public enum Kind: Equatable {
/// A RFC 822 message, i.e. `"MESSAGE" "RFC822"`
case rfc822Message(BodyStructure .RFC822Message)
/// A message that is text, i.e. `"TEXT" "<subtype>"`
case text(BodyStructure.Text)
/// A message that is not an RFC 822 message, i.e. `"<type>" "<subtype>"`
/// where `<subtype>` is not `RFC822`.
case basic(BodyStructure.MediaType)
}
}
}
#### Single Part — Additional Types
This one is similar to existing`Body.Fields`:
```swift
extension BodyStructure {
public struct Fields: Equatable {
public var parameters: [FieldParameterPair]
public var identifier: NString
public var description: NString
public var encoding: Encoding
public var byteCount: UInt32
}
}
with
extension BodyStructure {
public struct FieldParameterPair: Equatable {
public var field: String
public var value: String
}
}
See Body.FieldEncoding:
extension BodyStructure {
public enum Encoding: Equatable {
case sevenBit
case eightBit
case binary
case base64
case quotedPrintable
case other(EncodedString)
}
}
extension BodyStructure {
public struct RFC822Message: Equatable {
public var envelope: Envelope
public var body: BodyStructure
public var lineCount: Int
public var mediaType: MediaType { get }
}
}
extension BodyStructure {
public struct TextMessage: Equatable {
public var mediaSubtype: NString
public var lineCount: Int
public var mediaType: MediaType { get }
}
}
public enum MediaType: Equatable {
case text(subtype: EncodedString)
case rfc822Message
case application(subtype: EncodedString)
case audio(subtype: EncodedString)
case image(subtype: EncodedString)
case message(subtype: EncodedString)
case video(subtype: EncodedString)
case other(type: EncodedString, subtype: EncodedString)
}
Note: This may have to be a struct for API stability.
extension BodyStructure.SinglePart {
/// Extension data for a single part message.
///
/// This is never returned with the `BODY` fetch,
/// but can be returned with a `BODYSTRUCTURE` fetch.
struct ExtensionData {
/// MD5 of the body
public var bodyDigest: EncodedString?
/// RFC 2183 style content disposition
public var disposition: MessageData.Disposition?
/// A string or parenthesized list giving the body language
/// value as defined in RFC 3066
public var language: MessageData.LanguageIdentifier?
/// A string list giving the body content URI as defined in RFC 2557
public var location: MessageData.ContentLocation?
public var extension: BodyStructure.Extension?
}
}
The BodyStructure.Extension needs to represent body-extension — which is a string / number / (nested) array of string or number. I don’t know if this is actually used by anyone.
Multi Part
extension BodyStructure {
public struct MultiPart: Equatable {
public var parts: [BodyStructure]
public var mediaSubtype: MediaSubtype
}
}
extension BodyStructure.MultiPart {
public enum MediaSubtype: Equatable {
case alternative
case related
case mixed
case other(String)
}
}
extension BodyStructure.MultiPart {
/// Extension data for a single part message.
///
/// This is never returned with the `BODY` fetch,
/// but can be returned with a `BODYSTRUCTURE` fetch.
struct ExtensionData {
public var parameters: [FieldParameterPair]
/// RFC 2183 style content disposition
public var disposition: MessageData.Disposition?
/// A string or parenthesized list giving the body language
/// value as defined in RFC 3066
public var language: MessageData.LanguageIdentifier?
/// A string list giving the body content URI as defined in RFC 2557
public var location: MessageData.ContentLocation?
public var extension: BodyStructure.Extension?
}
}
The types related to the bodystructure are essential to code trying do things such as
The body structure is very complex and recursive. Here’s an attempt at making it a bit more approachable.
Note: I’m being a bit lax about the use of
String
vs.NString
here — need to revise that.Structure
As noted in #75 the top level structure should be something like
Then, generally, nest body structure related types inside
BodyStructure
.Single Part
A single part would look like this:
with
See
Body.FieldEncoding
:Note: This may have to be a
struct
for API stability.The
BodyStructure.Extension
needs to representbody-extension
— which is a string / number / (nested) array of string or number. I don’t know if this is actually used by anyone.Multi Part