douxueke5653 2014-08-19 11:57
浏览 109

如何通过Gmail Go SDK发送电子邮件?

I'm trying to send a new email through the gmail package . However the Message type which is required by the send method is poorly documented. Most of the fields seem used to actually parse/read emails. The only field which makes sense (at some degree) for the send method is Payload of type MessagePart though I can't figure it out how to generate the MessagePartBody as it seems to be a kind of mime type. Below is the code I have so far.

func (em *Email) SendMessage(cl *Client) error {
    config.ClientId = cl.Username
    config.ClientSecret = cl.Password

    t := &oauth.Transport{

        Config:    config,
        Transport: http.DefaultTransport,
    }
    var tk oauth.Token
    err := json.Unmarshal([]byte(cl.Meta), &tk)
    t.Token = &tk
    if err != nil {
        log.Errorf("meta %v, err %v", cl.Meta, err)
        return err
    }
    gmailService, err := gmail.New(t.Client())
    if err != nil {
        log.Error(err)
        return err
    }

    p := gmail.MessagePart{}
    p.Headers = append(p.Headers, &gmail.MessagePartHeader{
        Name:  "From",
        Value: em.FromEmail,
    })
    p.Headers = append(p.Headers, &gmail.MessagePartHeader{
        Name:  "To",
        Value: em.ToEmail,
    })
    p.Headers = append(p.Headers, &gmail.MessagePartHeader{
        Name:  "Subject",
        Value: em.Subject,
    })

    emsg := base64.StdEncoding.EncodeToString(em.Message)
    log.Info(emsg)
    msg := gmail.Message{
        Payload: &p,
        Raw:     "",
    }
    _, err = gmailService.Users.Messages.Send("me", &msg).Do()
    if err != nil {
        log.Error(err)
        return err
    }
    return err
}

The "REST" API is even more confusing. It requires an uploadType param (WTF to upload) and a raw field which I guess is the raw message which requires a format provided by messages.get. Why would you send a message from your inbox which literally would be a 'resend' as your are on the receipt list ? Am I the only one who thinks this API(or at least the documentation) is just crap ?

  • 写回答

2条回答 默认 最新

  • douque9982 2014-08-19 15:44
    关注

    It was a bit tricky but here is how you can send emails through the GMAIL API

    import(
        "code.google.com/p/goauth2/oauth"
        "code.google.com/p/google-api-go-client/gmail/v1"
        log "github.com/golang/glog"
    
        "encoding/base64"
        "encoding/json"
        "net/mail"
        "strings"
        )
    
    
    type Email struct {
        FromName, FromEmail, ToName, ToEmail, Subject string
        Message                                       string
    }
    
    func (em *Email) SendMessage(cl *Client) error {
        config.ClientId = cl.Username //oauth clientID
        config.ClientSecret = cl.Password  //oauth client secret 
    
        t := &oauth.Transport{
            Config:    config,
            Transport: http.DefaultTransport,
        }
        var tk oauth.Token
        err := json.Unmarshal([]byte(cl.Meta), &tk)
        t.Token = &tk
        if err != nil {
            log.Errorf("meta %v, err %v", cl.Meta, err)
            return err
        }
        gmailService, err := gmail.New(t.Client())
        if err != nil {
            log.Error(err)
            return err
        }
    
        from := mail.Address{em.FromName, em.FromEmail}
        to := mail.Address{em.ToName, em.ToEmail}
    
        header := make(map[string]string)
        header["From"] = from.String()
        header["To"] = to.String()
        header["Subject"] = encodeRFC2047(em.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
    ", k, v)
        }
        msg += "
    " + em.Message
    
        gmsg := gmail.Message{
            Raw: encodeWeb64String([]byte(msg)),
        }
    
        _, err = gmailService.Users.Messages.Send("me", &gmsg).Do()
        if err != nil {
            log.Errorf("em %v, err %v", gmsg, err)
            return err
        }
        return err
    }
    
    
    
    func encodeRFC2047(s string) string {
        // use mail's rfc2047 to encode any string
        addr := mail.Address{s, ""}
        return strings.Trim(addr.String(), " <>")
    }
    
    func encodeWeb64String(b []byte) string {
    
        s := base64.URLEncoding.EncodeToString(b)
    
        var i = len(s) - 1
        for s[i] == '=' {
            i--
        }
    
        return s[0 : i+1]
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作