介绍

常用的电子邮件协议包括 SMTP,POP3,IMAP, SMTP(Simple Mail Transfer Protocol)是常用协议

依赖库

go get github.com/jordan-wright/email

准备

需要登录邮箱服务商开启 SMTP/POP3/IMAP服务, 开启时,需要记录授权码, 发送的时候会使用

例如: mail.163.com

  • 登陆
  • 在顶部菜单选择设置
  • 选择导航栏POP3/SMTP/IMAP
  • 新增授权密码

服务器地址

1服务器地址:
2  POP3服务器: pop.163.com
3  SMTP服务器: smtp.163.com
4  IMAP服务器: imap.163.com
5安全支持:
6  POP3/SMTP/IMAP服务全部支持SSL连接

简单发送

 1package main
 2
 3import (
 4	"crypto/tls"
 5	"fmt"
 6	"net/smtp"
 7	"net/textproto"
 8	"os"
 9	"testing"
10
11	"github.com/jordan-wright/email"
12)
13
14func TestSimpleEmail(*testing.T) {
15	pwd := os.Getenv("EMAIL_PASSWORD")
16	e := &email.Email{
17		To:      []string{"458914534@qq.com"},
18		From:    "clibing <wmsjhappy@163.com>",
19		Subject: "邮件发送测试",
20		Text:    []byte("纯文本内容"),
21		HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
22		Headers: textproto.MIMEHeader{},
23	}
24	err := e.Send("smtp.163.com:25", smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"))
25	if err != nil {
26		fmt.Println("send email error")
27	} else {
28		fmt.Println("send email succuss!")
29	}
30
31	err = e.SendWithTLS("smtp.163.com:465",
32		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
33		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
34	)
35	if err != nil {
36		fmt.Println("tls send email error")
37	} else {
38		fmt.Println("tls send email succuss!")
39	}
40}

发送

接收

抄送

  • CC 普通抄送
  • BCC 秘密抄送
 1
 2func TestCarbonCopyEmail(*testing.T) {
 3	pwd := os.Getenv("EMAIL_PASSWORD")
 4	e := &email.Email{
 5		To:      []string{"458914534@qq.com"},
 6		From:    "clibing <wmsjhappy@163.com>",
 7		Subject: "邮件发送测试",
 8		Cc:      []string{"wmsjhappy@126.com"},   // 普通抄送
 9		Bcc:     []string{"wmsjhappy@gmail.com"}, // 密码抄送
10		Text:    []byte("纯文本内容"),
11		HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
12		Headers: textproto.MIMEHeader{},
13	}
14	err := e.Send("smtp.163.com:25", smtp.PlainAuth("", "wmsjhappy@163.com", "YWCDXEEMAYFYLOCC", "smtp.163.com"))
15	if err != nil {
16		fmt.Println("send email error")
17	} else {
18		fmt.Println("send email succuss!")
19	}
20
21	err = e.SendWithTLS("smtp.163.com:465",
22		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
23		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
24	)
25	if err != nil {
26		fmt.Println("tls send email error")
27	} else {
28		fmt.Println("tls send email succuss!")
29	}
30}

抄送

秘密抄送

附件

 1func TestAttachFileEmail(*testing.T) {
 2	pwd := os.Getenv("EMAIL_PASSWORD")
 3	e := &email.Email{
 4		To:      []string{"458914534@qq.com"},
 5		From:    "clibing <wmsjhappy@163.com>",
 6		Subject: "邮件发送测试-附件",
 7		Text:    []byte("纯文本内容"),
 8		HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
 9		Headers: textproto.MIMEHeader{},
10	}
11	e.AttachFile("test.txt")
12	err := e.SendWithTLS(
13		"smtp.163.com:465",
14		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
15		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
16	)
17	if err != nil {
18		fmt.Println("tls send email error")
19	} else {
20		fmt.Println("tls send email succuss!")
21	}
22}

连接池

注意:不能使用smtp.163.com:465端口需要使用25

 1func TestSendEmailWithPool(*testing.T) {
 2	// 敏感密码
 3	pwd := os.Getenv("EMAIL_PASSWORD")
 4
 5	coreSize := 4
 6	maxSize := 8
 7
 8	ch := make(chan *email.Email, maxSize)
 9
10	p, err := email.NewPool(
11		"smtp.163.com:25",
12		coreSize,
13		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
14		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
15	)
16
17	if err != nil {
18		fmt.Printf("创建连接池异常: %v\n", err)
19		return
20	}
21
22	var wg sync.WaitGroup
23	wg.Add(coreSize)
24
25	for i := 0; i < coreSize; i++ {
26		go func() {
27			defer wg.Done()
28			for e := range ch {
29				err := p.Send(e, 15*time.Second)
30				if err != nil {
31					fmt.Printf("failed, email: %s err: %v\n", e.Subject, err)
32				}
33			}
34		}()
35	}
36
37	for i := 0; i < maxSize; i++ {
38		v := &email.Email{
39			To:      []string{"458914534@qq.com"},
40			From:    "clibing <wmsjhappy@163.com>",
41			Subject: fmt.Sprintf("邮件发送测试: %d", i),
42			Text:    []byte("纯文本内容"),
43			HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
44			Headers: textproto.MIMEHeader{},
45		}
46		// if i == 0 {
47		// 	p.Send(v, 10*time.Second)
48		// }
49		ch <- v
50	}
51	close(ch)
52	wg.Wait()
53}

完整测试代码

  1package main
  2
  3import (
  4	"crypto/tls"
  5	"fmt"
  6	"net/smtp"
  7	"net/textproto"
  8	"os"
  9	"sync"
 10	"testing"
 11	"time"
 12
 13	"github.com/jordan-wright/email"
 14)
 15
 16/**
 17 * https://darjun.github.io/2020/02/16/godailylib/email/
 18 */
 19func TestSimpleEmail(*testing.T) {
 20	pwd := os.Getenv("EMAIL_PASSWORD")
 21	e := &email.Email{
 22		To:      []string{"458914534@qq.com"},
 23		From:    "clibing <wmsjhappy@163.com>",
 24		Subject: "邮件发送测试",
 25		Text:    []byte("纯文本内容"),
 26		HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
 27		Headers: textproto.MIMEHeader{},
 28	}
 29	err := e.Send("smtp.163.com:25", smtp.PlainAuth("", "wmsjhappy@163.com", "YWCDXEEMAYFYLOCC", "smtp.163.com"))
 30	if err != nil {
 31		fmt.Println("send email error")
 32	} else {
 33		fmt.Println("send email succuss!")
 34	}
 35
 36	err = e.SendWithTLS("smtp.163.com:465",
 37		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
 38		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
 39	)
 40	if err != nil {
 41		fmt.Println("tls send email error")
 42	} else {
 43		fmt.Println("tls send email succuss!")
 44	}
 45}
 46
 47func TestCarbonCopyEmail(*testing.T) {
 48	pwd := os.Getenv("EMAIL_PASSWORD")
 49	e := &email.Email{
 50		To:      []string{"458914534@qq.com"},
 51		From:    "clibing <wmsjhappy@163.com>",
 52		Subject: "邮件发送测试",
 53		Cc:      []string{"wmsjhappy@126.com"},   // 普通抄送
 54		Bcc:     []string{"wmsjhappy@gmail.com"}, // 密码抄送
 55		Text:    []byte("纯文本内容"),
 56		HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
 57		Headers: textproto.MIMEHeader{},
 58	}
 59	err := e.Send("smtp.163.com:25", smtp.PlainAuth("", "wmsjhappy@163.com", "YWCDXEEMAYFYLOCC", "smtp.163.com"))
 60	if err != nil {
 61		fmt.Println("send email error")
 62	} else {
 63		fmt.Println("send email succuss!")
 64	}
 65
 66	err = e.SendWithTLS("smtp.163.com:465",
 67		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
 68		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
 69	)
 70	if err != nil {
 71		fmt.Println("tls send email error")
 72	} else {
 73		fmt.Println("tls send email succuss!")
 74	}
 75}
 76
 77func TestAttachFileEmail(*testing.T) {
 78	pwd := os.Getenv("EMAIL_PASSWORD")
 79	e := &email.Email{
 80		To:      []string{"458914534@qq.com"},
 81		From:    "clibing <wmsjhappy@163.com>",
 82		Subject: "邮件发送测试-附件",
 83		Text:    []byte("纯文本内容"),
 84		HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
 85		Headers: textproto.MIMEHeader{},
 86	}
 87	e.AttachFile("test.txt")
 88	err := e.SendWithTLS(
 89		"smtp.163.com:465",
 90		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
 91		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
 92	)
 93	if err != nil {
 94		fmt.Println("tls send email error")
 95	} else {
 96		fmt.Println("tls send email succuss!")
 97	}
 98}
 99
100func TestSendEmailWithPool(*testing.T) {
101	// 敏感密码
102	pwd := os.Getenv("EMAIL_PASSWORD")
103
104	coreSize := 4
105	maxSize := 8
106
107	ch := make(chan *email.Email, maxSize)
108
109	p, err := email.NewPool(
110		"smtp.163.com:25",
111		coreSize,
112		smtp.PlainAuth("", "wmsjhappy@163.com", pwd, "smtp.163.com"),
113		&tls.Config{InsecureSkipVerify: false, ServerName: "smtp.163.com"},
114	)
115
116	if err != nil {
117		fmt.Printf("创建连接池异常: %v\n", err)
118		return
119	}
120
121	var wg sync.WaitGroup
122	wg.Add(coreSize)
123
124	for i := 0; i < coreSize; i++ {
125		go func() {
126			defer wg.Done()
127			for e := range ch {
128				err := p.Send(e, 15*time.Second)
129				if err != nil {
130					fmt.Printf("failed, email: %s err: %v\n", e.Subject, err)
131				}
132			}
133		}()
134	}
135
136	for i := 0; i < maxSize; i++ {
137		v := &email.Email{
138			To:      []string{"458914534@qq.com"},
139			From:    "clibing <wmsjhappy@163.com>",
140			Subject: fmt.Sprintf("邮件发送测试: %d", i),
141			Text:    []byte("纯文本内容"),
142			HTML:    []byte("发送富文本内容,需要服务商支持,目前常用的邮件服务商基本都支持, <h3>hello</h3>, <a href='https://clibing.com'>clibing.com</a>"),
143			Headers: textproto.MIMEHeader{},
144		}
145		// if i == 0 {
146		// 	p.Send(v, 10*time.Second)
147		// }
148		ch <- v
149	}
150	close(ch)
151	wg.Wait()
152}