【问题标题】:send email from swift osx application从 swift osx 应用程序发送电子邮件
【发布时间】:2016-10-18 02:01:14
【问题描述】:

我在从我的 osx swift 应用程序发送邮件时遇到问题。要发送邮件,我使用了以下代码

import Foundation
import Cocoa


class sendemail : NSObject, NSSharingServiceDelegate{

func sendEmail()  throws
{
    print("enter email sending")
    let body = "This is an email for auto testing throug code."
    let shareItems = [body] as NSArray

    let service = NSSharingService(named: NSSharingServiceNameComposeEmail)

    service?.delegate = self
    service?.recipients = ["abc@dom.com"]

    let subject = "Vea Software"
    service?.subject = subject

    service?.performWithItems(shareItems as [AnyObject])
}

}

我从这个链接中找到了源代码:https://www.veasoftware.com/posts/send-email-in-swift-xcode-62-os-x-1010-tutorial

但它不起作用。

我也尝试按照以下说明从终端发送邮件:

http://www.developerfiles.com/how-to-send-emails-from-localhost-mac-os-x-el-capitan/

上面写着:

postfix/postfix-script: fatal: the Postfix mail system is not running

请帮帮我。

我可以从我配置的 mac 邮件应用程序手动发送邮件。

我正在使用

xcode 7.3, osx el captain and swift 2.2

【问题讨论】:

    标签: xcode swift macos swift2 postfix-mta


    【解决方案1】:

    这对我有用:

    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."])
        }
    }
    

    用法:

    SendEmail.send()
    

    【讨论】:

    • 非常感谢您的帮助。但它在这里不起作用... :( .... 是否有必要设置像 postmail 这样的东西才能成功运行它?
    • 为我工作,无需额外设置。谢谢
    • 我遇到了同样的问题。需要的是,Apple 的 Mail 是您选择的电子邮件客户端。
    【解决方案2】:

    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"])
        }
    }
    

    用法:SendEmail.send()

    【讨论】:

      【解决方案3】:

      我们通过不使用共享服务,而是使用 postfix 实用程序解决了这个“困难的方法”。请注意,postfix 必须运行并正确配置才能使以下代码生效。

      为什么要这样做?好吧,这是一个稍微“通用”的解决方案,应该可以在 macOS 以外的其他平台上工作(或可以轻松修改)。此外,它不依赖于“邮件”。

      请注意,这也使用了我们的日志工具,但您应该能够轻松提取所需的代码。

      /// 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)")
              }
          }
      }
      
      

      应该使用格式如下的字符串调用此例程:

          let email: String =
          """
          To: \(emailAddress)
          From: \(fromAddress)
          Content-Type: text/html;
          Subject: Confirm Account Creation at \(domain.name)\n
          \(message)
          """
      

      【讨论】:

        猜你喜欢
        • 2017-08-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-08
        • 2020-05-24
        • 2011-05-08
        • 2011-08-06
        • 2011-02-03
        • 1970-01-01
        相关资源
        最近更新 更多