如何在 swift 中使用 Gmail api 发送电子邮件

How send Email using Gmail api in swift

Gmail Api has no clear documentation on how to do this, I have been trying with this但是有很多事情是悬而未决的。

我已经寻求外部资源。 Source 1 and Source 2。第一个好像是用了api的势,用的是函数queryForUsersMessagesSendWithUploadParameters.

而第二个大约多一点。虽然这在 Objective-C 中不是问题,但 GTMMIMEDocument 对象除外,它不知道从哪里或是否从库中获取。

我的问题是,是否有人有更清晰和/或更易于理解的代码,或者更好的发送电子邮件指南

如果您的目标是发送电子邮件,我建议使用 iOS 的 MailCore 库。 在文档中有 Objective-c 中的示例,但它与 Swift

兼容

这是如何使用 MailCore 和 Swift 发送电子邮件的示例:

var smtpSession = MCOSMTPSession()
smtpSession.hostname = "smtp.gmail.com"
smtpSession.username = "matt@gmail.com"
smtpSession.password = "xxxxxxxxxxxxxxxx"
smtpSession.port = 465
smtpSession.authType = MCOAuthType.SASLPlain
smtpSession.connectionType = MCOConnectionType.TLS
smtpSession.connectionLogger = {(connectionID, type, data) in
    if data != nil {
        if let string = NSString(data: data, encoding: NSUTF8StringEncoding){
            NSLog("Connectionlogger: \(string)")
        }
    }
}

var builder = MCOMessageBuilder()
builder.header.to = [MCOAddress(displayName: "Rool", mailbox: "itsrool@gmail.com")]
builder.header.from = MCOAddress(displayName: "Matt R", mailbox: "matt@gmail.com")
builder.header.subject = "My message"
builder.htmlBody = "Yo Rool, this is a test message!"

let rfc822Data = builder.data()
let sendOperation = smtpSession.sendOperationWithData(rfc822Data)
sendOperation.start { (error) -> Void in
    if (error != nil) {
        NSLog("Error sending email: \(error)")
    } else {
        NSLog("Successfully sent email!")
    }
} 

我找到了解决方案

class func sendEmail() {

        var gtlMessage = GTLGmailMessage()
        gtlMessage.raw = self.generateRawString()

        let appd = UIApplication.sharedApplication().delegate as! AppDelegate
        let query = GTLQueryGmail.queryForUsersMessagesSendWithUploadParameters(nil)
        query.message = gtlMessage

        appd.service.executeQuery(query, completionHandler: { (ticket, response, error) -> Void in
            println("ticket \(ticket)")
            println("response \(response)")
            println("error \(error)")
        })
    }

    class func generateRawString() -> String {

        var dateFormatter:NSDateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss Z"; //RFC2822-Format
        var todayString:String = dateFormatter.stringFromDate(NSDate())

        var rawMessage = "" +
            "Date: \(todayString)\r\n" +
            "From: <mail>\r\n" +
            "To: username <mail>\r\n" +
            "Subject: Test send email\r\n\r\n" +
            "Test body"

        println("message \(rawMessage)")

        return GTLEncodeWebSafeBase64(rawMessage.dataUsingEncoding(NSUTF8StringEncoding))
    }

根据Google API文档(https://developers.google.com/gmail/api/guides/sending),我们可以知道有两种方法可以帮助您成功发送消息(draft.send, message.send).毫无疑问,两者使用 api 是不同的,但结果是一样的。 由于您给出了上述方法之一,因此我们将其称为message.send。另一种方式是draft.send,所以我们应该上传"UploadParameters"到Gmail草稿,上传成功后,我们可以得到一些关于gmail草稿的信息。最后,我们要发送邮件内容,发送成功后,草稿邮件会自动删除。代码如下:

func postEmailMessageRequest(model: MEMailMessageModel, request: CompletionRequest) {

        let uploadParameters = GTLUploadParameters()
        uploadParameters.data = model.snippet.dataUsingEncoding(NSUTF8StringEncoding)
        uploadParameters.MIMEType = model.mimeType!

        let query = GTLQueryGmail.queryForUsersDraftsCreateWithUploadParameters(uploadParameters) as! GTLQueryProtocol!
        service.executeQuery(query) { (ticket : GTLServiceTicket!, messages : AnyObject!, error : NSError?) -> Void in
            if error == nil {
                let messages = (messages as! GTLGmailDraft)
                messages.message.threadId = model.threadID
                self.sendMailRequest(messages, model: model, request: request)
            } else {
                request(status: false, result: "upload success")
            }
        }
    }

    func sendMailRequest(draft: GTLGmailDraft, model: MEMailMessageModel, request: CompletionRequest) {

        let query = GTLQueryGmail.queryForUsersDraftsSendWithUploadParameters(nil) as! GTLQueryGmail
        draft.message.raw = self.generateRawString(model)
        query.draft = draft

        self.service.executeQuery(query, completionHandler: { (ticket, response, error) -> Void in
            if error == nil {
                request(status: true, result: "send success") // after this, the draft will be delete
            } else {
                request(status: false, result: "send failure")
            }
        })
    }

    func generateRawString(model: MEMailMessageModel) -> String {
        let date = MEMailMessagelFormatUtil.coverDateFromDate(NSDate(), dateFormat: "EEE, dd MMM yyyy HH:mm:ss Z")! // get current date

        var fromEamil = ""
        if let str = NSUserDefaults.standardUserDefaults().valueForKey("userEmail") as? String {
            fromEamil = str
        }

        var rawMessage = ""
        if model.isReply { // how to reply, but how to reply the email is another question.
            rawMessage = "" + "In-Reply-To: \(model.messageID!)\r\n"
            if let references = model.references {
                rawMessage += "References: \(references) \(model.messageID!)\r\n"
            } else {
                rawMessage += "References: \(model.messageID!)\r\n"
            }
        }

        rawMessage += "Date: \(date)\r\n" +
            "From: <\(fromEamil)>\r\n" +
            "To: \(model.toName!) <\(model.toMail)>\r\n" +
            "Subject: \(model.subject) \r\n\r\n" + "\(model.snippet)"

        return GTLEncodeWebSafeBase64(rawMessage.dataUsingEncoding(NSUTF8StringEncoding))
    }

这是我最终实现的最终解决方案:

播客文件:

pod 'GoogleAPIClient/Gmail'

示例Swift 5 代码:

import Foundation
import GoogleAPIClient

class GMailManager {

    let service = GTLServiceGmail()

    func sendEmail() {

        guard let query = GTLQueryGmail.queryForUsersMessagesSend(with: nil) else {
            return
        }

        let gtlMessage = GTLGmailMessage()
        gtlMessage.raw = self.generateRawString()

        query.message = gtlMessage

        self.service.executeQuery(query, completionHandler: { (ticket, response, error) -> Void in
            print("ticket \(String(describing: ticket))")
            print("response \(String(describing: response))")
            print("error \(String(describing: error))")
        })
    }

    func generateRawString() -> String {

        let dateFormatter:DateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss Z"; //RFC2822-Format
        let todayString:String = dateFormatter.string(from: NSDate() as Date)

        let rawMessage = "" +
            "Date: \(todayString)\r\n" +
            "From: <mail>\r\n" +
            "To: username <mail>\r\n" +
            "Subject: Test send email\r\n\r\n" +
            "Test body"

        print("message \(rawMessage)")

        return GTLEncodeWebSafeBase64(rawMessage.data(using: String.Encoding.utf8))
    }
}