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

huangapple go评论129阅读模式
英文:

How to send email through Gmail Go SDK?

问题

我正在尝试通过gmail包发送一封新邮件。然而,send方法所需的Message类型文档不够详细。大多数字段似乎用于解析/读取邮件。对于send方法而言,唯一有些意义的字段是类型为MessagePart的Payload,但我无法弄清楚如何生成MessagePartBody,因为它似乎是一种MIME类型。以下是我目前的代码。

  1. func (em *Email) SendMessage(cl *Client) error {
  2. config.ClientId = cl.Username
  3. config.ClientSecret = cl.Password
  4. t := &oauth.Transport{
  5. Config: config,
  6. Transport: http.DefaultTransport,
  7. }
  8. var tk oauth.Token
  9. err := json.Unmarshal([]byte(cl.Meta), &tk)
  10. t.Token = &tk
  11. if err != nil {
  12. log.Errorf("meta %v, err %v", cl.Meta, err)
  13. return err
  14. }
  15. gmailService, err := gmail.New(t.Client())
  16. if err != nil {
  17. log.Error(err)
  18. return err
  19. }
  20. p := gmail.MessagePart{}
  21. p.Headers = append(p.Headers, &gmail.MessagePartHeader{
  22. Name: "From",
  23. Value: em.FromEmail,
  24. })
  25. p.Headers = append(p.Headers, &gmail.MessagePartHeader{
  26. Name: "To",
  27. Value: em.ToEmail,
  28. })
  29. p.Headers = append(p.Headers, &gmail.MessagePartHeader{
  30. Name: "Subject",
  31. Value: em.Subject,
  32. })
  33. emsg := base64.StdEncoding.EncodeToString(em.Message)
  34. log.Info(emsg)
  35. msg := gmail.Message{
  36. Payload: &p,
  37. Raw: "",
  38. }
  39. _, err = gmailService.Users.Messages.Send("me", &msg).Do()
  40. if err != nil {
  41. log.Error(err)
  42. return err
  43. }
  44. return err
  45. }

这个"REST" API更加令人困惑。它需要一个uploadType参数(上传什么?)和一个raw字段,我猜这是原始消息,需要通过messages.get提供的格式。为什么要从收件箱发送一条消息,而这条消息实际上是一个“转发”?难道只有我觉得这个API(或者至少是文档)很糟糕吗?

英文:

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.

  1. func (em *Email) SendMessage(cl *Client) error {
  2. config.ClientId = cl.Username
  3. config.ClientSecret = cl.Password
  4. t := &oauth.Transport{
  5. Config: config,
  6. Transport: http.DefaultTransport,
  7. }
  8. var tk oauth.Token
  9. err := json.Unmarshal([]byte(cl.Meta), &tk)
  10. t.Token = &tk
  11. if err != nil {
  12. log.Errorf("meta %v, err %v", cl.Meta, err)
  13. return err
  14. }
  15. gmailService, err := gmail.New(t.Client())
  16. if err != nil {
  17. log.Error(err)
  18. return err
  19. }
  20. p := gmail.MessagePart{}
  21. p.Headers = append(p.Headers, &gmail.MessagePartHeader{
  22. Name: "From",
  23. Value: em.FromEmail,
  24. })
  25. p.Headers = append(p.Headers, &gmail.MessagePartHeader{
  26. Name: "To",
  27. Value: em.ToEmail,
  28. })
  29. p.Headers = append(p.Headers, &gmail.MessagePartHeader{
  30. Name: "Subject",
  31. Value: em.Subject,
  32. })
  33. emsg := base64.StdEncoding.EncodeToString(em.Message)
  34. log.Info(emsg)
  35. msg := gmail.Message{
  36. Payload: &p,
  37. Raw: "",
  38. }
  39. _, err = gmailService.Users.Messages.Send("me", &msg).Do()
  40. if err != nil {
  41. log.Error(err)
  42. return err
  43. }
  44. return err
  45. }

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 ?

答案1

得分: 6

这是通过GMAIL API发送电子邮件的代码示例:

  1. import (
  2. "code.google.com/p/goauth2/oauth"
  3. "code.google.com/p/google-api-go-client/gmail/v1"
  4. log "github.com/golang/glog"
  5. "encoding/base64"
  6. "encoding/json"
  7. "net/mail"
  8. "strings"
  9. )
  10. type Email struct {
  11. FromName, FromEmail, ToName, ToEmail, Subject string
  12. Message string
  13. }
  14. func (em *Email) SendMessage(cl *Client) error {
  15. config.ClientId = cl.Username //oauth clientID
  16. config.ClientSecret = cl.Password //oauth client secret
  17. t := &oauth.Transport{
  18. Config: config,
  19. Transport: http.DefaultTransport,
  20. }
  21. var tk oauth.Token
  22. err := json.Unmarshal([]byte(cl.Meta), &tk)
  23. t.Token = &tk
  24. if err != nil {
  25. log.Errorf("meta %v, err %v", cl.Meta, err)
  26. return err
  27. }
  28. gmailService, err := gmail.New(t.Client())
  29. if err != nil {
  30. log.Error(err)
  31. return err
  32. }
  33. from := mail.Address{em.FromName, em.FromEmail}
  34. to := mail.Address{em.ToName, em.ToEmail}
  35. header := make(map[string]string)
  36. header["From"] = from.String()
  37. header["To"] = to.String()
  38. header["Subject"] = encodeRFC2047(em.Subject)
  39. header["MIME-Version"] = "1.0"
  40. header["Content-Type"] = "text/html; charset=\"utf-8\""
  41. header["Content-Transfer-Encoding"] = "base64"
  42. var msg string
  43. for k, v := range header {
  44. msg += fmt.Sprintf("%s: %s\r\n", k, v)
  45. }
  46. msg += "\r\n" + em.Message
  47. gmsg := gmail.Message{
  48. Raw: encodeWeb64String([]byte(msg)),
  49. }
  50. _, err = gmailService.Users.Messages.Send("me", &gmsg).Do()
  51. if err != nil {
  52. log.Errorf("em %v, err %v", gmsg, err)
  53. return err
  54. }
  55. return err
  56. }
  57. func encodeRFC2047(s string) string {
  58. // use mail's rfc2047 to encode any string
  59. addr := mail.Address{s, ""}
  60. return strings.Trim(addr.String(), " <>")
  61. }
  62. func encodeWeb64String(b []byte) string {
  63. s := base64.URLEncoding.EncodeToString(b)
  64. var i = len(s) - 1
  65. for s[i] == '=' {
  66. i--
  67. }
  68. return s[0 : i+1]
  69. }

希望对你有帮助!

英文:

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

  1. import(
  2. &quot;code.google.com/p/goauth2/oauth&quot;
  3. &quot;code.google.com/p/google-api-go-client/gmail/v1&quot;
  4. log &quot;github.com/golang/glog&quot;
  5. &quot;encoding/base64&quot;
  6. &quot;encoding/json&quot;
  7. &quot;net/mail&quot;
  8. &quot;strings&quot;
  9. )
  10. type Email struct {
  11. FromName, FromEmail, ToName, ToEmail, Subject string
  12. Message string
  13. }
  14. func (em *Email) SendMessage(cl *Client) error {
  15. config.ClientId = cl.Username //oauth clientID
  16. config.ClientSecret = cl.Password //oauth client secret
  17. t := &amp;oauth.Transport{
  18. Config: config,
  19. Transport: http.DefaultTransport,
  20. }
  21. var tk oauth.Token
  22. err := json.Unmarshal([]byte(cl.Meta), &amp;tk)
  23. t.Token = &amp;tk
  24. if err != nil {
  25. log.Errorf(&quot;meta %v, err %v&quot;, cl.Meta, err)
  26. return err
  27. }
  28. gmailService, err := gmail.New(t.Client())
  29. if err != nil {
  30. log.Error(err)
  31. return err
  32. }
  33. from := mail.Address{em.FromName, em.FromEmail}
  34. to := mail.Address{em.ToName, em.ToEmail}
  35. header := make(map[string]string)
  36. header[&quot;From&quot;] = from.String()
  37. header[&quot;To&quot;] = to.String()
  38. header[&quot;Subject&quot;] = encodeRFC2047(em.Subject)
  39. header[&quot;MIME-Version&quot;] = &quot;1.0&quot;
  40. header[&quot;Content-Type&quot;] = &quot;text/html; charset=\&quot;utf-8\&quot;&quot;
  41. header[&quot;Content-Transfer-Encoding&quot;] = &quot;base64&quot;
  42. var msg string
  43. for k, v := range header {
  44. msg += fmt.Sprintf(&quot;%s: %s\r\n&quot;, k, v)
  45. }
  46. msg += &quot;\r\n&quot; + em.Message
  47. gmsg := gmail.Message{
  48. Raw: encodeWeb64String([]byte(msg)),
  49. }
  50. _, err = gmailService.Users.Messages.Send(&quot;me&quot;, &amp;gmsg).Do()
  51. if err != nil {
  52. log.Errorf(&quot;em %v, err %v&quot;, gmsg, err)
  53. return err
  54. }
  55. return err
  56. }
  57. func encodeRFC2047(s string) string {
  58. // use mail&#39;s rfc2047 to encode any string
  59. addr := mail.Address{s, &quot;&quot;}
  60. return strings.Trim(addr.String(), &quot; &lt;&gt;&quot;)
  61. }
  62. func encodeWeb64String(b []byte) string {
  63. s := base64.URLEncoding.EncodeToString(b)
  64. var i = len(s) - 1
  65. for s[i] == &#39;=&#39; {
  66. i--
  67. }
  68. return s[0 : i+1]
  69. }

答案2

得分: 1

与@hey的答案类似,但我整理了一下,并允许在电子邮件正文中使用\n来插入换行符,并在电子邮件客户端上正确显示。此外,@hey没有使用新支持的Gmail API。以下是最终的代码:

  1. import (
  2. "encoding/base64"
  3. "golang.org/x/net/context"
  4. "golang.org/x/oauth2"
  5. "golang.org/x/oauth2/google"
  6. "google.golang.org/api/gmail/v1"
  7. "encoding/json"
  8. "net/mail"
  9. )
  10. type Email struct {
  11. FromName string
  12. FromEmail string
  13. ToName string
  14. ToEmail string
  15. Subject string
  16. Message string
  17. }
  18. func (em *Email) sendMailFromEmail() error {
  19. b, err := ioutil.ReadFile("credentials.json")
  20. if err != nil {
  21. log.Fatalf("Unable to read client secret file: %v", err)
  22. }
  23. // If modifying these scopes, delete your previously saved token.json.
  24. config, err := google.ConfigFromJSON(b, gmail.GmailSendScope)
  25. if err != nil {
  26. log.Fatalf("Unable to parse client secret file to config: %v", err)
  27. }
  28. cl := getClientMail(config)
  29. gmailService, err := gmail.New(cl)
  30. if err != nil {
  31. log.Fatalf("Unable to retrieve Gmail client: %v", err)
  32. }
  33. from := mail.Address{em.FromName, em.FromEmail}
  34. to := mail.Address{em.ToName, em.ToEmail}
  35. header := make(map[string]string)
  36. header["From"] = from.String()
  37. header["To"] = to.String()
  38. header["Subject"] = em.Subject
  39. header["MIME-Version"] = "1.0"
  40. header["Content-Type"] = "text/plain; charset=\"utf-8\""
  41. header["Content-Transfer-Encoding"] = "base64"
  42. var msg string
  43. for k, v := range header {
  44. msg += fmt.Sprintf("%s: %s\r\n", k, v)
  45. }
  46. msg += "\r\n" + em.Message
  47. gmsg := gmail.Message{
  48. Raw: base64.RawURLEncoding.EncodeToString([]byte(msg)),
  49. }
  50. _, err = gmailService.Users.Messages.Send("me", &gmsg).Do()
  51. if err != nil {
  52. log.Printf("em %v, err %v", gmsg, err)
  53. return err
  54. }
  55. return err
  56. }

我没有包含以下函数:getClient、getTokenFromWeb、tokenFromFile和saveToken。你可以在这个Google教程中找到它们,并学习如何通过Gmail API进行设置。

英文:

Similar to @hey 's answer, but I tidied it up, and allowed the email to put newlines in the email body through \n and show up correctly on the email client. Also, @hey is not using the new supported Gmail API. Here is the final code:

  1. import (
  2. &quot;encoding/base64&quot;
  3. &quot;golang.org/x/net/context&quot;
  4. &quot;golang.org/x/oauth2&quot;
  5. &quot;golang.org/x/oauth2/google&quot;
  6. &quot;google.golang.org/api/gmail/v1&quot;
  7. &quot;encoding/json&quot;
  8. &quot;net/mail&quot;
  9. )
  10. type Email struct {
  11. FromName string
  12. FromEmail string
  13. ToName string
  14. ToEmail string
  15. Subject string
  16. Message string
  17. }
  18. func (em *Email) sendMailFromEmail() error {
  19. b, err := ioutil.ReadFile(&quot;credentials.json&quot;)
  20. if err != nil {
  21. log.Fatalf(&quot;Unable to read client secret file: %v&quot;, err)
  22. }
  23. // If modifying these scopes, delete your previously saved token.json.
  24. config, err := google.ConfigFromJSON(b, gmail.GmailSendScope)
  25. if err != nil {
  26. log.Fatalf(&quot;Unable to parse client secret file to config: %v&quot;, err)
  27. }
  28. cl := getClientMail(config)
  29. gmailService, err := gmail.New(cl)
  30. if err != nil {
  31. log.Fatalf(&quot;Unable to retrieve Gmail client: %v&quot;, err)
  32. }
  33. from := mail.Address{em.FromName, em.FromEmail}
  34. to := mail.Address{em.ToName, em.ToEmail}
  35. header := make(map[string]string)
  36. header[&quot;From&quot;] = from.String()
  37. header[&quot;To&quot;] = to.String()
  38. header[&quot;Subject&quot;] = em.Subject
  39. header[&quot;MIME-Version&quot;] = &quot;1.0&quot;
  40. header[&quot;Content-Type&quot;] = &quot;text/plain; charset=\&quot;utf-8\&quot;&quot;
  41. header[&quot;Content-Transfer-Encoding&quot;] = &quot;base64&quot;
  42. var msg string
  43. for k, v := range header {
  44. msg += fmt.Sprintf(&quot;%s: %s\r\n&quot;, k, v)
  45. }
  46. msg += &quot;\r\n&quot; + em.Message
  47. gmsg := gmail.Message{
  48. Raw: base64.RawURLEncoding.EncodeToString([]byte(msg)),
  49. }
  50. _, err = gmailService.Users.Messages.Send(&quot;me&quot;, &amp;gmsg).Do()
  51. if err != nil {
  52. log.Printf(&quot;em %v, err %v&quot;, gmsg, err)
  53. return err
  54. }
  55. return err
  56. }

I did not include the following functions: getClient, getTokenFromWeb, tokenFromFile, and saveToken. You can find them, and learn how to enable the Gmail API through this tutorial by Google.

huangapple
  • 本文由 发表于 2014年8月19日 19:57:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/25382821.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定