Skip to content

Commit

Permalink
fix(attachments:sandbox): fix the empty attachment bug on macos
Browse files Browse the repository at this point in the history
when having a sandboxed app, and using NSOpenPanel for letting users the selecting a file, the attachments did contain sizeof file times zero bytes.

Using the FileManager to access the file contents did solve the problem.

Also the base64 and cutting off after n characters is now simplified
  • Loading branch information
sassman committed Apr 24, 2020
1 parent 4937eca commit 961b2b1
Showing 1 changed file with 28 additions and 50 deletions.
78 changes: 28 additions & 50 deletions Sources/PerfectSMTP/PerfectSMTP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public enum SMTPError:Error {
case INVALID_PROTOCOL
/// base64 failed
case INVALID_ENCRYPTION

case general(Int, String)
}

Expand Down Expand Up @@ -90,7 +90,7 @@ extension String {
}
return nil
}

/// get RFC 5322-compliant date for email
static var rfc5322Date: String {
let dateFormatter = DateFormatter()
Expand All @@ -99,7 +99,7 @@ extension String {
let compliantDate = dateFormatter.string(from: Date())
return compliantDate
}

/// convert a recipient to standard email format: "Full Name"<[email protected]>
/// - parameters:
/// - recipient: the email receiver name / address structure
Expand All @@ -115,14 +115,14 @@ extension String {
}
}
}

/// convert a group of recipients into an address list, joined by comma
/// - parameters:
/// - recipients: array of recipient
init(recipients: [Recipient]) {
self = recipients.map{String(recipient: $0)}.joined(separator: ", ")
}

/// MIME mail header: To/Cc/Bcc + recipients
/// - parameters:
/// - prefix: To / Cc or Bcc
Expand All @@ -131,7 +131,7 @@ extension String {
let r = String(recipients: recipients)
self = "\(prefix): \(r)\r\n"
}

/// get the address info from a recipient, i.e, someone@somewhere -> @somewhere
var emailSuffix: String {
get {
Expand All @@ -145,15 +145,15 @@ extension String {
#endif
}
}

/// extract file name from a full path
var fileNameWithoutPath: String {
get {
let segments = self.split(separator: "/")
return String(segments[segments.count - 1])
}
}

/// extract file suffix from a file name
var suffix: String {
get {
Expand All @@ -167,11 +167,11 @@ private struct EmailBodyGen: CURLRequestBodyGenerator {
let bytes: [UInt8]
var offset = 0
var contentLength: Int? { return bytes.count }

init(_ string: String) {
bytes = Array(string.utf8)
}

mutating func next(byteCount: Int) -> [UInt8]? {
let count = bytes.count
let remaining = count - offset
Expand Down Expand Up @@ -215,16 +215,16 @@ public class EMail {
public var connectTimeoutSeconds: Int = 15
/// for debugging purposes
public var debug = false

var progress = 0

/// constructor
/// - parameters:
/// - client: SMTP client for login info
public init(client: SMTPClient) {
self.client = client
}

/// transform an attachment into an MIME part
/// - parameters:
/// - path: local full path
Expand Down Expand Up @@ -255,41 +255,19 @@ public class EMail {
return ""
}
}

/// encode a file by base64 method
/// - parameters:
/// - path: full path of the file to encode
/// - returns:
/// base64 encoded text WITH A TRAILING NEWLINE
@discardableResult
private func encode(path: String) throws -> String? {
let fd = File(path)
try fd.open(.read)
guard let buffer = try fd.readSomeBytes(count: fd.size).encode(.base64) else {
fd.close()
throw SMTPError.INVALID_ENCRYPTION
}
if self.debug {
print("encode \(fd.size) -> \(buffer.count)")
}
var wraped = [UInt8]()
let szline = 76
var cursor = 0
let newline:[UInt8] = [13, 10]
while cursor < buffer.count {
var mark = cursor + szline
if mark >= buffer.count {
mark = buffer.count
}
wraped.append(contentsOf: buffer[cursor ..< mark])
wraped.append(contentsOf: newline)
cursor += szline

/// encode a file by base64 method
/// - parameters:
/// - path: full path of the file to encode
/// - returns:
/// base64 encoded text WITH A TRAILING NEWLINE
@discardableResult
private func encode(path: String) throws -> String? {
return FileManager.default.contents(atPath: path)?
.base64EncodedString(options:
.init(arrayLiteral: [.endLineWithCarriageReturn, .endLineWithLineFeed, .lineLength76Characters]))
}
fd.close()
wraped.append(0)
return String(validatingUTF8: wraped)
}


private func makeBody() throws -> (String, String) {
// !FIX! quoted printable?
var body = "Date: \(String.rfc5322Date)\r\n"
Expand Down Expand Up @@ -320,7 +298,7 @@ public class EMail {
body += "In-Reply-To: \(reference)\r\n"
body += "References: \(reference)\r\n"
}

// add the email title
if subject.isEmpty {
throw SMTPError.INVALID_SUBJECT
Expand Down Expand Up @@ -358,7 +336,7 @@ public class EMail {
body += "--\(boundary)--\r\n"
return (body, uuid)
}

private func getResponse(_ body : String) throws -> CURLResponse {
let recipients = to + cc + bcc
guard recipients.count > 0 else {
Expand All @@ -376,7 +354,7 @@ public class EMail {
let request = CURLRequest(client.url, options: options)
return try request.perform()
}

/// send an email with the current settings
/// - parameters:
/// - completion: once sent, callback to the main thread with curl code, header & body string
Expand Down

0 comments on commit 961b2b1

Please sign in to comment.