Skip to content

Commit

Permalink
Merge pull request #37 from IBM-Swift/issue_26
Browse files Browse the repository at this point in the history
Ignore certain additionalHeaders
  • Loading branch information
quanvo87 committed Jul 17, 2017
2 parents 2cafbdc + de20450 commit 2d1eabc
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 40 deletions.
15 changes: 11 additions & 4 deletions Sources/Attachment.swift
Expand Up @@ -32,9 +32,11 @@ public struct Attachment {
/// - inline: Indicates if attachment is inline. To embed the attachment
/// in mail content, set to `true`. To send as standalone
/// attachment, set to `false`. Defaults to `false`.
/// - additionalHeaders: Additional headers for the attachment. Header
/// keys are capitalized and duplicate keys will
/// replace each other. Defaults to none.
/// - additionalHeaders: Additional headers for the `Mail`. Header keys
/// are capitalized and duplicate keys will
/// overwrite each other. Defaults to none. The
/// following will be ignored: CONTENT-TYPE,
/// CONTENT-DISPOSITION, CONTENT-TRANSFER-ENCODING.
/// - related: Related `Attachment`s of this attachment. Defaults to
/// none.
public init(data: Data,
Expand Down Expand Up @@ -153,7 +155,12 @@ extension Attachment {
dictionary["CONTENT-TRANSFER-ENCODING"] = "BASE64"

for (key, value) in additionalHeaders {
dictionary[key.uppercased()] = value
let keyUppercased = key.uppercased()
if keyUppercased != "CONTENT-TYPE" &&
keyUppercased != "CONTENT-DISPOSITION" &&
keyUppercased != "CONTENT-TRANSFER-ENCODING" {
dictionary[keyUppercased] = value
}
}

return dictionary
Expand Down
55 changes: 22 additions & 33 deletions Sources/DataSender.swift
Expand Up @@ -41,7 +41,7 @@ struct DataSender {
if mail.hasAttachment {
try sendMixed(mail)
} else {
try sendText(mail.text, headersDictionary: mail.headersDictionary)
try sendText(mail.text)
}
}
}
Expand All @@ -53,36 +53,14 @@ extension DataSender {
}

// Add custom/default headers to a `Mail`'s text and write it to the socket.
func sendText(_ text: String, headersDictionary: [String: String]) throws {
var embeddedText = ""

if let contentType = headersDictionary["CONTENT-TYPE"] {
embeddedText += "CONTENT-TYPE: \(contentType)\(CRLF)"
} else {
embeddedText += "CONTENT-TYPE: text/html; charset=utf-8\(CRLF)"
}

if let contentTransferEncoding = headersDictionary["CONTENT-TRANSFER-ENCODING"] {
embeddedText += "CONTENT-TRANSFER-ENCODING: \(contentTransferEncoding)\(CRLF)"
} else {
embeddedText += "CONTENT-TRANSFER-ENCODING: 7bit\(CRLF)"
}

if let contentDisposition = headersDictionary["CONTENT-DISPOSITION"] {
embeddedText += "CONTENT-DISPOSITION: \(contentDisposition)\(CRLF)"
} else {
embeddedText += "CONTENT-DISPOSITION: inline\(CRLF)"
}

embeddedText += "\(CRLF)\(text)\(CRLF)"

try send(embeddedText)
func sendText(_ text: String) throws {
try send(text.embedded)
}

// Send `mail`'s content that is more than just plain text
mutating func sendMixed(_ mail: Mail) throws {
let boundary = String.makeBoundary()
let mixedHeader = String.mixedHeader(boundary: boundary)
let mixedHeader = String.makeMixedHeader(boundary: boundary)

try send(mixedHeader)
try send(boundary.startLine)
Expand All @@ -98,11 +76,11 @@ extension DataSender {
mutating func sendAlternative(for mail: Mail) throws {
if let alternative = mail.alternative {
let boundary = String.makeBoundary()
let alternativeHeader = String.alternativeHeader(boundary: boundary)
let alternativeHeader = String.makeAlternativeHeader(boundary: boundary)
try send(alternativeHeader)

try send(boundary.startLine)
try sendText(mail.text, headersDictionary: mail.headersDictionary)
try sendText(mail.text)

try send(boundary.startLine)
try sendAttachment(alternative)
Expand All @@ -111,7 +89,7 @@ extension DataSender {
return
}

try sendText(mail.text, headersDictionary: mail.headersDictionary)
try sendText(mail.text)
}

// Sends the attachments of a `Mail`.
Expand All @@ -129,7 +107,7 @@ extension DataSender {

if attachment.hasRelated {
relatedBoundary = String.makeBoundary()
let relatedHeader = String.relatedHeader(boundary: relatedBoundary)
let relatedHeader = String.makeRelatedHeader(boundary: relatedBoundary)
try send(relatedHeader)
try send(relatedBoundary.startLine)
}
Expand Down Expand Up @@ -240,26 +218,37 @@ private extension DataSender {
}

private extension String {
// Embed plain text content of emails with the proper headers so that it is
// rendered correctly.
var embedded: String {
var embeddedText = ""
embeddedText += "CONTENT-TYPE: text/html; charset=utf-8\(CRLF)"
embeddedText += "CONTENT-TRANSFER-ENCODING: 7bit\(CRLF)"
embeddedText += "CONTENT-DISPOSITION: inline\(CRLF)"
embeddedText += "\(CRLF)\(self)\(CRLF)"
return embeddedText
}

// The SMTP protocol requires unique boundaries between sections of an
// email.
static func makeBoundary() -> String {
return UUID().uuidString.replacingOccurrences(of: "-", with: "")
}

// Header for a mixed type email.
static func mixedHeader(boundary: String) -> String {
static func makeMixedHeader(boundary: String) -> String {
return "CONTENT-TYPE: multipart/mixed; boundary=\"\(boundary)\"\(CRLF)"
}

// Header for an alternative email.
static func alternativeHeader(boundary: String) -> String {
static func makeAlternativeHeader(boundary: String) -> String {
return "CONTENT-TYPE: multipart/alternative; boundary=\"\(boundary)\"\(CRLF)"
}

// Header for an attachment that is related to another attachment.
// (Such as an image attachment that can be referenced by a related HTML
// attachment)
static func relatedHeader(boundary: String) -> String {
static func makeRelatedHeader(boundary: String) -> String {
return "CONTENT-TYPE: multipart/related; boundary=\"\(boundary)\"\(CRLF)"
}

Expand Down
11 changes: 9 additions & 2 deletions Sources/Mail.swift
Expand Up @@ -47,7 +47,9 @@ public struct Mail {
/// sent). Defaults to none.
/// - additionalHeaders: Additional headers for the `Mail`. Header keys
/// are capitalized and duplicate keys will
/// overwrite each other. Defaults to none.
/// overwrite each other. Defaults to none. The
/// following will be ignored: CONTENT-TYPE,
/// CONTENT-DISPOSITION, CONTENT-TRANSFER-ENCODING.
public init(from: User,
to: [User],
cc: [User] = [],
Expand Down Expand Up @@ -96,7 +98,12 @@ extension Mail {
dictionary["MIME-VERSION"] = "1.0 (Swift-SMTP)"

for (key, value) in additionalHeaders {
dictionary[key.uppercased()] = value
let keyUppercased = key.uppercased()
if keyUppercased != "CONTENT-TYPE" &&
keyUppercased != "CONTENT-DISPOSITION" &&
keyUppercased != "CONTENT-TRANSFER-ENCODING" {
dictionary[keyUppercased] = value
}
}

return dictionary
Expand Down
2 changes: 1 addition & 1 deletion Sources/SSL.swift
Expand Up @@ -70,7 +70,7 @@ public struct SSL {
///
/// - Parameters:
/// - chainFilePath: Path to the certificate chain file (optional). *(see note above)*
/// - password: Password for the chain file (optional).
/// - password: Password for the chain file (optional). If using self-signed certs, a password is required.
/// - selfSigned: True if certs are `self-signed`, false otherwise. Defaults to true.
/// - clientAllowsSelfSignedCertificates: True if, as a client, connections to self-signed servers are allowed
/// - cipherSuite: Optional String containing the cipher suite to use.
Expand Down

0 comments on commit 2d1eabc

Please sign in to comment.