为了账号安全,请及时绑定邮箱和手机立即绑定

带有 Go 和 gmail.NewService 的 Gmail API 无效内存地址或 nil

带有 Go 和 gmail.NewService 的 Gmail API 无效内存地址或 nil

Go
BIG阳 2022-11-08 16:25:27
我对 gmail api 的新 NewService 功能有疑问。如果我使用已弃用的 gmail.New() 一切正常。使用 NewService() 我得到invalid memory address or nil pointer dereference我的实现如下type MailData struct {    To      string    Name    string    Subject string    Content template.HTML}    func doSend(msg *gmail.Message, srv *gmail.Service) error {    _, err := srv.Users.Messages.Send("me", msg).Do()    if err != nil {        return err    }    return nil}func ComposeMessage(m models.MailData) *gmail.Message {    var gmailMessage gmail.Message    from := mail.Address{Name: "Sender", Address: os.Getenv("MAIL_FROM")}    replyTo := os.Getenv("MAIL_REPLYTO")    to := mail.Address{Name: m.Name, Address: m.To}    header := make(map[string]string)    header["From"] = from.String()    header["Reply-To"] = replyTo    header["To"] = to.String()    header["Subject"] = m.Subject    header["MIME-Version"] = "1.0"    header["Content-Type"] = "text/html; charset=\"utf-8\""    header["Content-Transfer-Encoding"] = "base64"    var msg string    for k, v := range header {        msg += fmt.Sprintf("%s: %s\r\n", k, v)    }    msg += "\r\n" + string(m.Content)    gmailMessage.Raw = base64.RawURLEncoding.EncodeToString([]byte(msg))    return &gmailMessage}使用旧的 gmail.New() 有效,但它指出该功能已弃用,因此我需要将其更改为新的 gmail.NewService。虽然像下面这样实现它是行不通的func sendGMail(m models.MailData) error {    credentials := "../gmail_credentials.json"    ctx := context.Background()    srv, err := gmail.NewService(        ctx,        option.WithCredentialsFile(credentials),        option.WithScopes("https://www.googleapis.com/auth/gmail.send"),    )    if err != nil {        return errors.New(fmt.Sprintf("unable to retrieve gmail client: %s", err))    }    // Create message    gMessage := ComposeMessage(m)    if err := doSend(gMessage, srv); err != nil {        return errors.New(fmt.Sprintf("could not send mail: %s", err))    }    fmt.Println("Email sent")    return nil}
查看完整描述

1 回答

?
守着星空守着你

TA贡献1799条经验 获得超8个赞

这个问题并不那么明显,但很容易解决。在初始化时,gmail.NewService()我需要将配置参数作为选项传递,就像之前的实现gmail.New()是使用


所以之前是


client := getClient(config)

srv, err := gmail.New(client)

现在是


client := getClient(config)

ctx := context.Background()

srv, err := gmail.NewService(

    ctx,

    option.WithHTTPClient(client),

)

在 Go 的 Gmail API 实现的更多上下文中,您需要使用所有使用的函数


https://developers.google.com/gmail/api/quickstart/go或


https://github.com/googleworkspace/go-samples/blob/master/gmail/quickstart/quickstart.go


并将它们放入您的 go 文件中。这些将生成 AccessToken 和凭据,如果您正确遵循指南,则需要将其保存为 json 文件并重复使用。credentials.json 用于更新您的 AccessToken。


现在代替使用gmail.New(),正确的方法是使用如上所示的函数。


整个sendGmail函数如下


func sendGMail(m models.MailData) error {

    credentials := "../gmail_credentials.json"

    b, err := ioutil.ReadFile(credentials)

    if err != nil {

        return errors.New(fmt.Sprint("unable to read credentials file:", err))

    }


    config, err := google.ConfigFromJSON(b, gmail.GmailSendScope)

    if err != nil {

        return errors.New(fmt.Sprint("unable to parse credentials file config:", err))

    }


    client := getClient(config)

    ctx := context.Background()

    srv, err := gmail.NewService(

        ctx,

        option.WithHTTPClient(client),

        option.WithScopes("https://www.googleapis.com/auth/gmail.send"),

    )

    if err != nil {

        return fmt.Errorf("unable to retrieve gmail client: %s", err)

    }


    // Create message

    gMessage := ComposeMessage(m)


    if err := doSend(gMessage, srv); err != nil {

        return fmt.Errorf("could not send mail: %s", err)

    }

    fmt.Println("Email sent")


    return nil

}


查看完整回答
反对 回复 2022-11-08
  • 1 回答
  • 0 关注
  • 64 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信