send email from swift osx application

后端 未结 3 2129
广开言路
广开言路 2021-02-13 15:45

I am facing problem on sending mail from my osx swift application. To send mail i used the below code

import Foundation
import Cocoa


class sendemail : NSObject         


        
相关标签:
3条回答
  • 2021-02-13 16:13

    Swift 4.2:

    class SendEmail: NSObject {
        static func send() {
            let service = NSSharingService(named: NSSharingService.Name.composeEmail)!
            service.recipients = ["email@yourEmail.eu"]
            service.subject = "Email Subject"
    
            service.perform(withItems: ["Email Content"])
        }
    }
    

    Usage: SendEmail.send()

    0 讨论(0)
  • 2021-02-13 16:15

    This works for me:

    import Cocoa
    
    class SendEmail: NSObject {
        static func send() {
            let service = NSSharingService(named: NSSharingServiceNameComposeEmail)!
            service.recipients = ["abc@dom.com"]
            service.subject = "Vea software"
            
            service.performWithItems(["This is an email for auto testing through code."])
        }
    }
    

    Usage:

    SendEmail.send()
    
    0 讨论(0)
  • We solved this "the hard way" by not using the shared services, but the postfix utility. Note that postfix must be running and correctly configured before the following code can take effect.

    Why do this the hard way? well, it is a slightly more 'universal' solution that should work (or can be modified easily) on other platforms than macOS. Also, it does not depend on 'mail'.

    Note that this also uses our Log facility, but you should be able to easily extract the code you need.

    /// This queue/thread will be used to transfer the mails.
    
    fileprivate let mailQueue = DispatchQueue.global(qos: .background)
    
    
    /// Sends an email using the postfix unix utility.
    ///
    /// - Note: Ths function only works if postfix is running (and set up correctly)
    ///
    /// - Parameters:
    ///   - mail: The email to be transmitted. It should -as a minimum- contain the To, From and Subject fields.
    ///   - domainName: The domain this email is sent from, used for logging purposes only.
    
    public func sendEmail(_ mail: String, domainName: String) {
    
    
        // Do this on a seperate queue in the background so this operation is non-blocking.
    
        mailQueue.async { [mail, domainName] in
    
            // Ensure the mail is ok
    
            guard let utf8mail = mail.data(using: .utf8), utf8mail.count > 0 else {
                Log.atDebug?.log("No mail present")
                return
            }
    
            let options: Array<String> = ["-t"] // This option tells sendmail to read the from/to/subject from the email string itself.
    
            let errpipe = Pipe() // should remain empty
            let outpipe = Pipe() // should remain empty (but if you use other options you may get some text)
            let inpipe = Pipe()  // will be used to transfer the mail to sendmail
    
    
            // Setup the process that will send the mail
    
            let process = Process()
            if #available(OSX 10.13, *) {
                process.executableURL = URL(fileURLWithPath: "/usr/sbin/sendmail")
            } else {
                process.launchPath = "/usr/sbin/sendmail"
            }
            process.arguments = options
            process.standardError = errpipe
            process.standardOutput = outpipe
            process.standardInput = inpipe
    
    
            // Start the sendmail process
    
            let data: Data
            do {
    
                Log.atDebug?.log("\n\(mail)")
    
    
                // Setup the data to be sent
    
                inpipe.fileHandleForWriting.write(utf8mail)
    
    
                // Start the sendmail process
    
                if #available(OSX 10.13, *) {
                    try process.run()
                } else {
                    process.launch()
                }
    
    
                // Data transfer complete
    
                inpipe.fileHandleForWriting.closeFile()
    
    
                // Set a timeout. 10 seconds should be more than enough.
    
                let timeoutAfter = DispatchTime(uptimeNanoseconds: DispatchTime.now().uptimeNanoseconds + UInt64(10000) * 1000000)
    
    
                // Setup the process timeout on another queue
    
                DispatchQueue.global().asyncAfter(deadline: timeoutAfter) {
                    [weak process] in
                    Log.atDebug?.log("Sendmail Timeout expired, process \(process != nil ? "is still running" : "has exited already")")
                    process?.terminate()
                }
    
    
                // Wait for sendmail to complete
    
                process.waitUntilExit()
    
                Log.atDebug?.log("Sendmail terminated")
    
    
                // Check termination reason & status
    
                if (process.terminationReason == .exit) && (process.terminationStatus == 0) {
    
                    // Exited OK, return data
    
                    data = outpipe.fileHandleForReading.readDataToEndOfFile()
    
                    if data.count > 0 {
                        Log.atDebug?.log("Unexpectedly read \(data.count) bytes from sendmail, content: \(String(data: data, encoding: .utf8) ?? "")")
                    } else {
                        Log.atDebug?.log("Sendmail completed without error")
                    }
    
                } else {
    
                    // An error of some kind happened
    
                    Log.atError?.log("Sendmail process terminations status = \(process.terminationStatus), reason = \(process.terminationReason.rawValue )")
    
                    let now = dateFormatter.string(from: Date())
    
                    Log.atError?.log("Sendmail process failure, check domain (\(domainName)) logging directory for an error entry with timestamp \(now)")
    
    
                    // Error, grab all possible output and create a file with all error info
    
                    let e = errpipe.fileHandleForReading.readDataToEndOfFile()
                    let d = outpipe.fileHandleForReading.readDataToEndOfFile()
    
                    let dump =
                    """
                    Process Termination Reason: \(process.terminationReason.rawValue)
                    Sendmail exit status: \(process.terminationStatus)
                    Details:
                    - Sendmail Executable  : /usr/sbin/sendmail
                    - Sendmail Options     : -t
                    - Sendmail Timeout     : 10,000 mSec
                    - Sendmail Error output: \(e.count) bytes
                    - Sendmail Output      : \(d.count) bytes
                    Below the output of sendmail is given in the following block format:
                    (----- Email input -----)
                    ...
                    (----- Standard Error -----)
                    ...
                    (----- Standard Out -----)
                    ...
                    (----- End of output -----)
    
                    (----- Email input -----)
                    \(mail)
                    (----- Standard Error -----)
                    \(String(bytes: e, encoding: .utf8) ?? "")
                    (----- Standard Out -----)
                    \(String(bytes: d, encoding: .utf8) ?? "")
                    (----- End of output -----)
                    """
    
                    let errorFileName = "sendmail-error-log-" + now
                    if
                        let errorFileUrl = Urls.domainLoggingDir(for: domainName)?.appendingPathComponent(errorFileName).appendingPathExtension("txt"),
                        let dumpData = dump.data(using: .utf8),
                        ((try? dumpData.write(to: errorFileUrl)) != nil) {
                    } else {
                        Log.atError?.log("Cannot create sendmail error file, content is: \n\(dump)\n")
                    }
                }
    
            } catch let error {
    
                Log.atError?.log("Exception occured during sendmail execution, message = \(error.localizedDescription)")
            }
        }
    }
    
    

    This routine should be called with a string formatted like:

        let email: String =
        """
        To: \(emailAddress)
        From: \(fromAddress)
        Content-Type: text/html;
        Subject: Confirm Account Creation at \(domain.name)\n
        \(message)
        """
    
    0 讨论(0)
提交回复
热议问题