Skip to content

Commit 112ba14

Browse files
committed
fix(attachment:filename): fix the mime filename header
the bug happens only for filenames that contain non ascii characters like latin or german umlauts now the content-type name and content-disposition filename behaves correctly according to the rfc2231 and rfc2047
1 parent 4937eca commit 112ba14

1 file changed

Lines changed: 33 additions & 2 deletions

File tree

Sources/PerfectSMTP/PerfectSMTP.swift

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,45 @@ public class EMail {
248248
print("\(data.utf8.count) bytes attached")
249249
}
250250
// pack it up to an MIME part
251-
return "--\(boundary)\r\nContent-Type: \(mimeType); name=\"\(file)\"\r\n"
251+
let filename = paramterRfc2231(something: file)
252+
let name = contentTypefilenameParameter(something: file)
253+
return "--\(boundary)\r\n"
254+
+ "Content-Disposition: \(disposition);\r\n"
255+
+ " filename*=\(filename)\r\n"
256+
+ "Content-Type: \(mimeType);\r\n"
257+
+ " name=\"\(name)\"\r\n"
252258
+ "Content-Transfer-Encoding: base64\r\n"
253-
+ "Content-Disposition: \(disposition); filename=\"\(file)\"\r\n\r\n\(data)\r\n"
259+
+ "\r\n\(data)\r\n"
254260
} catch {
255261
return ""
256262
}
257263
}
258264

265+
/// https://www.ietf.org/rfc/rfc2047.txt
266+
/// encode a string to url encode conform string
267+
/// - parameters:
268+
/// - something: a string to be encoded
269+
/// - returns:
270+
/// base64 but rfc2047 conform string
271+
private func contentTypefilenameParameter(something: String) -> String {
272+
let something = something.base64Encoded()!
273+
// from rfc2047 encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
274+
// Q is "Quoted-Printable" content-transfer-encoding defined in RFC 2045
275+
// B is Base64
276+
return "=?utf-8?B?\(something)?="
277+
}
278+
279+
/// https://tools.ietf.org/html/rfc2231
280+
/// encode a string to url encode conform string
281+
/// - parameters:
282+
/// - something: a string to be encoded
283+
/// - returns:
284+
/// url encoded string
285+
private func paramterRfc2231(something: String) -> String {
286+
let something = something.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
287+
return "utf-8''\(something)"
288+
}
289+
259290
/// encode a file by base64 method
260291
/// - parameters:
261292
/// - path: full path of the file to encode

0 commit comments

Comments
 (0)