mail/smtp.go

122 lines
2.9 KiB
Go
Raw Normal View History

package mail
import (
"crypto/tls"
"fmt"
"io"
"apigo.cc/go/file"
"github.com/jaytaylor/html2text"
"gopkg.in/gomail.v2"
)
// SendOption 发送选项
type SendOption struct {
Cc []string
Bcc []string
HTML bool
Attachments []Attachment
Embeds []Attachment
}
// Send 发送邮件
func (m *Mailbox) Send(to []string, subject, content string, option *SendOption) error {
if m.config == nil || m.config.Username == "" {
return fmt.Errorf("mailbox not configured")
}
msg := gomail.NewMessage()
if m.config.SenderName != "" {
msg.SetHeader("From", msg.FormatAddress(m.config.Username, m.config.SenderName))
} else {
msg.SetHeader("From", m.config.Username)
}
msg.SetHeader("To", to...)
msg.SetHeader("Subject", subject)
useHTML := false
if option != nil {
if len(option.Cc) > 0 {
msg.SetHeader("Cc", option.Cc...)
}
if len(option.Bcc) > 0 {
msg.SetHeader("Bcc", option.Bcc...)
}
for _, attachment := range option.Attachments {
if attachment.Path != "" {
if file.Exists(attachment.Path) {
msg.Attach(attachment.Path)
} else {
m.logger.Error("Mail attachment file not found", "path", attachment.Path)
}
} else if len(attachment.Data) > 0 {
name := attachment.Name
if name == "" {
name = "attachment"
}
msg.Attach(name, gomail.SetCopyFunc(func(w io.Writer) error {
_, err := w.Write(attachment.Data)
return err
}))
}
}
for _, embed := range option.Embeds {
if embed.Path != "" {
if file.Exists(embed.Path) {
msg.Embed(embed.Path)
} else {
m.logger.Error("Mail embed file not found", "path", embed.Path)
}
} else if len(embed.Data) > 0 {
name := embed.Name
if name == "" {
name = "image"
}
msg.Embed(name, gomail.SetCopyFunc(func(w io.Writer) error {
_, err := w.Write(embed.Data)
return err
}))
}
}
useHTML = option.HTML
}
if useHTML {
msg.SetBody("text/html", content)
if textContent, err := html2text.FromString(content, html2text.Options{TextOnly: true, PrettyTables: true}); err == nil {
msg.AddAlternative("text/plain", textContent)
} else {
m.logger.Warning("Convert HTML to text failed", "err", err)
msg.AddAlternative("text/plain", content)
}
} else {
msg.SetBody("text/plain", content)
}
password := ""
if m.config.Password != nil {
p := m.config.Password.Open()
password = p.String()
defer p.Close()
}
dialer := gomail.NewDialer(m.config.SMTPHost, m.config.SMTPPort, m.config.Username, password)
if m.config.SMTPPort == 465 {
dialer.SSL = true
} else {
dialer.TLSConfig = &tls.Config{
ServerName: m.config.SMTPHost,
InsecureSkipVerify: false,
}
}
err := dialer.DialAndSend(msg)
if err != nil {
m.logger.Error("Send mail failed", "err", err, "to", to, "subject", subject)
} else {
m.logger.Info("Send mail success", "to", to, "subject", subject)
}
return err
}