如何使用Go发送电子邮件

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

How to send an e-mail from Go

问题

我正在尝试在Golang中发送电子邮件,但遇到了很多问题。我在Go中是新手,所以也许这很简单,但我在文档中找不到答案。

这是我想做的事情:

  1. 从STDIN获取电子邮件
  2. 解析电子邮件(获取发件人、收件人、主题、附件等)
  3. 发送这封电子邮件(将其再次放入本地 postfix 队列)

我已经完成了第1和第2步,但在第3步遇到了问题。

这是我现在的代码:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/jhillyerd/go.enmime"
  5. // "github.com/sendgrid/sendgrid-go"
  6. "net/smtp"
  7. "github.com/jordan-wright/email"
  8. "os"
  9. "net/mail"
  10. "io/ioutil"
  11. "bytes"
  12. )
  13. func main() {
  14. mail_stdin, err := ioutil.ReadAll(os.Stdin)
  15. if err != nil {
  16. return
  17. }
  18. // Convert type to io.Reader
  19. buf := bytes.NewBuffer(mail_stdin)
  20. msg, err := mail.ReadMessage(buf)
  21. if err != nil {
  22. return
  23. }
  24. mime, err := enmime.ParseMIMEBody(msg)
  25. if err != nil {
  26. return
  27. }
  28. // 保存附件
  29. for _, value := range mime.Attachments {
  30. fmt.Println(value.FileName())
  31. err := ioutil.WriteFile(value.FileName(), value.Content(), 0664)
  32. if err != nil {
  33. //panic(err)
  34. return
  35. }
  36. }
  37. fmt.Printf("From: %v\n", msg.Header.Get("From"))
  38. fmt.Printf("Subject: %v\n", mime.GetHeader("Subject"))
  39. fmt.Printf("Text Body: %v chars\n", len(mime.Text))
  40. fmt.Printf("HTML Body: %v chars\n", len(mime.Html))
  41. fmt.Printf("Inlines: %v\n", len(mime.Inlines))
  42. fmt.Printf("Attachments: %v\n", len(mime.Attachments))
  43. fmt.Println(mime.Attachments)
  44. fmt.Println(mime.OtherParts)
  45. fmt.Printf("Attachments: %v\n", mime.Attachments)
  46. }

我已经使用 net/smtp、sendgrid-go 和 jordan-wright/email 进行了一些测试。
我想做的就是将电子邮件(不更改任何内容)从服务器发送到队列中。大多数模块都需要进行身份验证,但我只想简单地使用 sendmail 发送,就像我可以在 bash 中这样做一样:

  1. # echo "test" | mail {address}
英文:

I'm trying to send an e-mail in Golang and I have a lot of problems with it. I'm new in Go so maybe this is very simply but I cannot find the answer on the doc.

This is what I want to do:

  1. get an e-mail from the STDIN
  2. parse the e-mail (getting from, to, subject, attachments and so on)
  3. send this e-mail (put it again to the queue in local postfix)

I did 1 and 2 but I have a problem with 3th one.

This is what I have now:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/jhillyerd/go.enmime"
  5. //"github.com/sendgrid/sendgrid-go"
  6. "net/smtp"
  7. "github.com/jordan-wright/email"
  8. "os"
  9. "net/mail"
  10. "io/ioutil"
  11. "bytes"
  12. )
  13. func main() {
  14. mail_stdin, err := ioutil.ReadAll(os.Stdin)
  15. if err != nil {
  16. return
  17. }
  18. // Convert type to io.Reader
  19. buf := bytes.NewBuffer(mail_stdin)
  20. msg, err := mail.ReadMessage(buf)
  21. if err != nil {
  22. return
  23. }
  24. mime, err := enmime.ParseMIMEBody(msg)
  25. if err != nil {
  26. return
  27. }
  28. # saving attachments
  29. for _, value := range mime.Attachments {
  30. fmt.Println(value.FileName())
  31. err := ioutil.WriteFile(value.FileName(), value.Content(), 0664)
  32. if err != nil {
  33. //panic(err)
  34. return
  35. }
  36. fmt.Printf("From: %v\n", msg.Header.Get("From"))
  37. fmt.Printf("Subject: %v\n", mime.GetHeader("Subject"))
  38. fmt.Printf("Text Body: %v chars\n", len(mime.Text))
  39. fmt.Printf("HTML Body: %v chars\n", len(mime.Html))
  40. fmt.Printf("Inlines: %v\n", len(mime.Inlines))
  41. fmt.Printf("Attachments: %v\n", len(mime.Attachments))
  42. fmt.Println(mime.Attachments)
  43. fmt.Println(mime.OtherParts)
  44. fmt.Printf("Attachments: %v\n", mime.Attachments)
  45. }

I already did few tests using: net/smtp, sendgrid-go and jordan-wright/email.
All I want to do is to send an e-mail (without changing anything) from the server to the queue again. Most of those modules needs to have Auth, but I just want to simply send is using sendmail, in the same way as I can do this from the bash:

  1. # echo "test" | mail {address}

答案1

得分: 2

使用net/smtp包,你可以相对容易地实现这个功能...假设你有一个运行中的 SMTP 服务器,可以在没有身份验证的情况下连接到它。我猜你想要实现的功能可能更容易通过像 Gmail 这样简单的方式来完成(https://www.digitalocean.com/community/tutorials/how-to-use-google-s-smtp-server)。

无论如何,下面是几个代码示例,涵盖了两种情况:

  1. c, err := smtp.Dial("mail.example.com:25")
  2. if err != nil {
  3. log.Fatal(err)
  4. }
  5. defer c.Close()
  6. // 设置发件人和收件人。
  7. c.Mail("sender@example.org")
  8. c.Rcpt("recipient@example.net")
  9. // 发送邮件正文。
  10. wc, err := c.Data()
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. defer wc.Close()
  15. buf := bytes.NewBufferString("This is the email body.")
  16. if _, err = buf.WriteTo(wc); err != nil {
  17. log.Fatal(err)
  18. }

另外,这里有一个使用简单身份验证的 Go Playground 示例:http://play.golang.org/p/ATDCgJGKZ3,除非你已经在你的开发机上运行了一个 SMTP 服务器,按照这样的方式进行操作可能会更容易一些。

英文:

Using net/smtp you can do this fairly easily... Assuming you have an smtp server running that you can connect to without authentication. I would guess for what you're trying to accomplish it's actually a lot easier to do through something simple like your gmail ( https://www.digitalocean.com/community/tutorials/how-to-use-google-s-smtp-server )

Anyway, here's a couple code samples to cover either case;

  1. c, err := smtp.Dial("mail.example.com:25")
  2. if err != nil {
  3. log.Fatal(err)
  4. }
  5. defer c.Close()
  6. // Set the sender and recipient.
  7. c.Mail("sender@example.org")
  8. c.Rcpt("recipient@example.net")
  9. // Send the email body.
  10. wc, err := c.Data()
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. defer wc.Close()
  15. buf := bytes.NewBufferString("This is the email body.")
  16. if _, err = buf.WriteTo(wc); err != nil {
  17. log.Fatal(err)
  18. }

Alternatively here's a go playground example that uses simple auth; http://play.golang.org/p/ATDCgJGKZ3 unless you've already got an smtp server running on your dev box following something like that will probably be a lot easier.

huangapple
  • 本文由 发表于 2015年7月7日 23:18:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/31272725.html
匿名

发表评论

匿名网友

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

确定