2020-04-08 08:56:42 +02:00
|
|
|
package mail
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
gomail "gopkg.in/mail.v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
type SendFunc func(*SendOption)
|
|
|
|
|
|
|
|
type SendOption struct {
|
|
|
|
Charset string
|
|
|
|
AddressHeaders []AddressHeader
|
|
|
|
Headers []Header
|
|
|
|
Body Body
|
|
|
|
AlternativeBodies []Body
|
|
|
|
}
|
|
|
|
|
|
|
|
type AddressHeader struct {
|
|
|
|
Field string
|
|
|
|
Address string
|
|
|
|
Name string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Header struct {
|
|
|
|
Field string
|
|
|
|
Values []string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Body struct {
|
|
|
|
Type string
|
|
|
|
Content string
|
|
|
|
PartSetting gomail.PartSetting
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithCharset(charset string) func(*SendOption) {
|
|
|
|
return func(opt *SendOption) {
|
|
|
|
opt.Charset = charset
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:27:07 +02:00
|
|
|
func WithSender(address string, name string) func(*SendOption) {
|
2020-04-08 08:56:42 +02:00
|
|
|
return WithAddressHeader("From", address, name)
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:27:07 +02:00
|
|
|
func WithSubject(subject string) func(*SendOption) {
|
|
|
|
return WithHeader("Subject", subject)
|
|
|
|
}
|
|
|
|
|
2020-04-08 08:56:42 +02:00
|
|
|
func WithAddressHeader(field, address, name string) func(*SendOption) {
|
|
|
|
return func(opt *SendOption) {
|
|
|
|
opt.AddressHeaders = append(opt.AddressHeaders, AddressHeader{field, address, name})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithHeader(field string, values ...string) func(*SendOption) {
|
|
|
|
return func(opt *SendOption) {
|
|
|
|
opt.Headers = append(opt.Headers, Header{field, values})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:27:07 +02:00
|
|
|
func WithRecipients(addresses ...string) func(*SendOption) {
|
|
|
|
return WithHeader("To", addresses...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithCopies(addresses ...string) func(*SendOption) {
|
|
|
|
return WithHeader("Cc", addresses...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithInvisibleCopies(addresses ...string) func(*SendOption) {
|
|
|
|
return WithHeader("Cci", addresses...)
|
|
|
|
}
|
|
|
|
|
2020-04-08 08:56:42 +02:00
|
|
|
func WithBody(contentType string, content string, setting gomail.PartSetting) func(*SendOption) {
|
|
|
|
return func(opt *SendOption) {
|
2020-04-24 09:27:07 +02:00
|
|
|
if setting == nil {
|
|
|
|
setting = gomail.SetPartEncoding(gomail.Unencoded)
|
|
|
|
}
|
2020-04-08 08:56:42 +02:00
|
|
|
opt.Body = Body{contentType, content, setting}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithAlternativeBody(contentType string, content string, setting gomail.PartSetting) func(*SendOption) {
|
|
|
|
return func(opt *SendOption) {
|
2020-04-24 09:27:07 +02:00
|
|
|
if setting == nil {
|
|
|
|
setting = gomail.SetPartEncoding(gomail.Unencoded)
|
|
|
|
}
|
2020-04-08 08:56:42 +02:00
|
|
|
opt.AlternativeBodies = append(opt.AlternativeBodies, Body{contentType, content, setting})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Mailer) Send(funcs ...SendFunc) error {
|
|
|
|
opt := &SendOption{
|
|
|
|
Charset: "UTF-8",
|
|
|
|
Body: Body{
|
|
|
|
Type: "text/plain",
|
|
|
|
Content: "",
|
|
|
|
PartSetting: gomail.SetPartEncoding(gomail.Unencoded),
|
|
|
|
},
|
|
|
|
AddressHeaders: make([]AddressHeader, 0),
|
|
|
|
Headers: make([]Header, 0),
|
|
|
|
AlternativeBodies: make([]Body, 0),
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, f := range funcs {
|
|
|
|
f(opt)
|
|
|
|
}
|
|
|
|
|
|
|
|
conn, err := m.openConnection()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "could not open connection")
|
|
|
|
}
|
|
|
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
|
|
message := gomail.NewMessage(gomail.SetCharset(opt.Charset))
|
|
|
|
|
|
|
|
for _, h := range opt.AddressHeaders {
|
|
|
|
message.SetAddressHeader(h.Field, h.Address, h.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, h := range opt.Headers {
|
|
|
|
message.SetHeader(h.Field, h.Values...)
|
|
|
|
}
|
|
|
|
|
|
|
|
message.SetBody(opt.Body.Type, opt.Body.Content, opt.Body.PartSetting)
|
|
|
|
|
|
|
|
for _, b := range opt.AlternativeBodies {
|
|
|
|
message.AddAlternative(b.Type, b.Content, b.PartSetting)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := gomail.Send(conn, message); err != nil {
|
|
|
|
return errors.Wrap(err, "could not send message")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Mailer) openConnection() (gomail.SendCloser, error) {
|
|
|
|
dialer := gomail.NewDialer(
|
|
|
|
m.opt.Host,
|
|
|
|
m.opt.Port,
|
|
|
|
m.opt.User,
|
|
|
|
m.opt.Password,
|
|
|
|
)
|
|
|
|
|
|
|
|
if m.opt.InsecureSkipVerify {
|
|
|
|
dialer.TLSConfig = &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conn, err := dialer.Dial()
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not dial smtp server")
|
|
|
|
}
|
|
|
|
|
|
|
|
return conn, nil
|
|
|
|
}
|