Introduction to the

The need to send mail is common in programs. The administrator and the person in charge need to be notified if there is any abnormal situation. The user may need to notify the order information after placing an order. The e-commerce platform, China Mobile and China Unicom all have monthly bills, which can be pushed through email. And we usually receive most of the junk mail is also sent through this way 😭. So how do YOU send emails in Go? This article introduces the use of the email library.

Quick to use

This library is not fast to use, why?

Install the library first, needless to say:

$ go get github.com/jordan-wright/email
Copy the code

We need some extra work. We know that mailboxes use protocols such as SMTP/POP3/IMAP to pull mail from mail servers. The mail is not sent directly to the mailbox, but is pulled by the mailbox. Therefore, we need to configure SMTP/POP3/IMAP server. It’s possible to build from scratch, and there are open source libraries available, but it’s a hassle. Now the general mail service business has opened SMTP/POP3/IMAP server. I take mailbox 126 as an example, using an SMTP server. Of course, you can also use QQ mailbox.

  • First, log in to your email;
  • Click on Settings at the top and selectPOP3/SMTP/IMAP;
  • Click to openIMAP/SMTPService, follow the steps to open, there is a password set, remember this password, useful behind.

Then you can code:

package main

import (
  "log"
  "net/smtp"

  "github.com/jordan-wright/email"
)

func main(a) {
  e := email.NewEmail()
  e.From = "dj <[email protected]>"
  e.To = []string{"[email protected]"}
  e.Subject = "Awesome web"
  e.Text = []byte("Text Body is, of course, supported!")
  err := e.Send("smtp.126.com:25", smtp.PlainAuth(""."[email protected]"."yyy"."smtp.126.com"))
  iferr ! =nil {
    log.Fatal(err)
  }
}
Copy the code

I’m hiding the real information here for my information security. Replace XXX with your email account and YYy with the password set above.

The code steps are relatively simple and clear:

  • First callNewEmailCreate an email;
  • Set up theFromThe sender,ToThe receiver,SubjectEmail subject (subject),TextSet the email content.
  • And then callSendParameter 1 is the IP address of the SMTP server, and parameter 2 is the authentication information.

Running the program will send an email to my QQ mailbox:

Some mailboxes will put this kind of mail in the trash, such as QQ😭. If you can’t find your inbox, look in the trash.

cc

Usually when we send emails, we may CC some people, and some people secretly CC 😄, namely Carbon Copy (CC) and Blind Carbon Copy (BCC). Email We can also set these two parameters:

package main

import (
  "log"
  "net/smtp"

  "github.com/jordan-wright/email"
)

func main(a) {
  e := email.NewEmail()
  e.From = "dj <[email protected]>"
  e.To = []string{"[email protected]"}
  e.Cc = []string{"[email protected]"."[email protected]"}
  e.Bcc = []string{"[email protected]"}
  e.Subject = "Awesome web"
  e.Text = []byte("Text Body is, of course, supported!")
  err := e.Send("smtp.126.com:25", smtp.PlainAuth(""."[email protected]"."yyy"."smtp.126.com"))
  iferr ! =nil {
    log.Fatal(err)
  }
}
Copy the code

Test1 /test2/secret

Running the program will send an email to my QQ email and cc another email to my 126 mailbox:

HTML format

Sending plain text is not pretty. Email supports sending HTML content. Similar to sending plain text, set the HTML field of the object directly:

package main

import (
  "log"
  "net/smtp"

  "github.com/jordan-wright/email"
)

func main(a) {
  e := email.NewEmail()
  e.From = "dj <[email protected]>"
  e.To = []string{"[email protected]"}
  e.Cc = []string{"[email protected]"}
  e.Subject = "Go one library a day"
  e.HTML = []byte(` < ul > < li > < a "https://darjun.github.io/2020/01/10/godailylib/flag/" > Go daily the flag of a library < / a > < / li > < li > < a "Https://darjun.github.io/2020/01/10/godailylib/go-flags/" > Go daily Go - the flags of a library < / a > < / li > < li > < a "Https://darjun.github.io/2020/01/14/godailylib/go-homedir/" > Go Go of a library - daily homedir < / a > < / li > < li > < a "Https://darjun.github.io/2020/01/15/godailylib/go-ini/" > Go Go of a library - daily ini < / a > < / li > < li > < a "Https://darjun.github.io/2020/01/17/godailylib/cobra/" > Go daily a library of cobra < / a > < / li > < li > < a "Https://darjun.github.io/2020/01/18/godailylib/viper/" > Go daily a library of 9 < / a > < / li > < li > < a "Https://darjun.github.io/2020/01/19/godailylib/fsnotify/" > Go daily a library of fsnotify < / a > < / li > < li > < a The cast of "https://darjun.github.io/2020/01/20/godailylib/cast/" > Go daily library < / a > < / li > < / ul > `)
  err := e.Send("smtp.126.com:25", smtp.PlainAuth(""."[email protected]"."yyy"."smtp.126.com"))
  iferr ! =nil {
    log.Fatal("failed to send email:", err)
  }
}
Copy the code

Send result:

Note that 126 SMTP server detection is more strict, plus HTML, it is easy to be identified as spam not to send, then CC itself OK.

The attachment

It is also easy to add attachments by calling AttachFile directly:

package main

import (
  "log"
  "net/smtp"

  "github.com/jordan-wright/email"
)

func main(a) {
  e := email.NewEmail()
  e.From = "dj <[email protected]>"
  e.To = []string{"[email protected]"}
  e.Subject = "Go one library a day"
  e.Text = []byte("Please see the attachment.")
  e.AttachFile("test.txt")
  err := e.Send("smtp.126.com:25", smtp.PlainAuth(""."[email protected]"."yyy"."smtp.126.com"))
  iferr ! =nil {
    log.Fatal("failed to send email:", err)
  }
}
Copy the code

Mail Received:

The connection pool

In fact, each time Send is invoked, a connection is established with the SMTP server. If a large number of emails are sent frequently, performance problems may occur. Email provides connection pooling to reuse network connections:

package main

import (
  "fmt"
  "log"
  "net/smtp"
  "os"
  "sync"
  "time"

  "github.com/jordan-wright/email"
)

func main(a) {
  ch := make(chan *email.Email, 10)
  p, err := email.NewPool(
    "smtp.126.com:25".4,
    smtp.PlainAuth(""."[email protected]"."yyy"."smtp.126.com"),iferr ! =nil {
    log.Fatal("failed to create pool:", err)
  }

  var wg sync.WaitGroup
  wg.Add(4)
  for i := 0; i < 4; i++ {
    go func(a) {
      defer wg.Done()
      for e := range ch {
        err := p.Send(e, 10*time.Second)
        iferr ! =nil {
          fmt.Fprintf(os.Stderr, "email:%v sent error:%v\n", e, err)
        }
      }
    }()
  }

  for i := 0; i < 10; i++ {
    e := email.NewEmail()
    e.From = "dj <[email protected]>"
    e.To = []string{"[email protected]"}
    e.Subject = "Awesome web"
    e.Text = []byte(fmt.Sprintf("Awesome Web %d", i+1))
    ch <- e
  }

  close(ch)
  wg.Wait()
}
Copy the code

In the above program, we create 4 goroutines to share a connection pool to send mail, send 10 messages after the program exit. We used sync.waitGroup to wait for the program to exit until all the messages had been sent or failed.

Mailboxes were bombed:

Due to the use of Goroutine, mail order is not guaranteed.

conclusion

This article describes how to use the Go program to send emails. The program code is available on GitHub github.com/darjun/go-d… . All code passed the test, please rest assured to eat ~

If you find a fun and useful Go library, please Go to GitHub and submit issue😄

reference

  1. Email GitHub:github.com/jordan-wrig…
  2. GitHub: github.com/darjun/go-d…

I

My blog

Welcome to follow my wechat public account [GoUpUp], learn together, progress together ~

This article is published by OpenWrite!