mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
151 lines
3.7 KiB
Go
151 lines
3.7 KiB
Go
package notification
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/PuerkitoBio/goquery"
|
|
"github.com/apex/log"
|
|
"github.com/crawlab-team/crawlab/core/models/models/v2"
|
|
"github.com/crawlab-team/crawlab/trace"
|
|
"gopkg.in/gomail.v2"
|
|
"net/mail"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
func SendMail(s *models.NotificationSettingV2, ch *models.NotificationChannelV2, to, cc, bcc, title, content string) error {
|
|
// config
|
|
smtpConfig := smtpAuthentication{
|
|
Server: ch.SMTPServer,
|
|
Port: ch.SMTPPort,
|
|
SenderIdentity: s.SenderName,
|
|
SenderEmail: s.SenderEmail,
|
|
SMTPUser: ch.SMTPUsername,
|
|
SMTPPassword: ch.SMTPPassword,
|
|
}
|
|
|
|
options := sendOptions{
|
|
Subject: title,
|
|
To: to,
|
|
Cc: cc,
|
|
Bcc: bcc,
|
|
}
|
|
|
|
// convert html to text
|
|
text := content
|
|
if isHtml(text) {
|
|
text = convertHtmlToText(text)
|
|
}
|
|
|
|
// apply theme
|
|
if isHtml(content) {
|
|
content = GetTheme() + content
|
|
}
|
|
|
|
// send the email
|
|
if err := send(smtpConfig, options, content, text); err != nil {
|
|
log.Errorf("failed to send email: %v", err)
|
|
trace.PrintError(err)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func isHtml(content string) bool {
|
|
regex := regexp.MustCompile(`(?i)<\s*(html|head|body|div|span|p|a|img|table|tr|td|th|tbody|thead|tfoot|ul|ol|li|dl|dt|dd|form|input|textarea|button|select|option|optgroup|fieldset|legend|label|iframe|embed|object|param|video|audio|source|canvas|svg|math|style|link|script|meta|base|title|br|hr|b|strong|i|em|u|s|strike|del|ins|mark|small|sub|sup|big|pre|code|q|blockquote|abbr|address|bdo|cite|dfn|kbd|var|samp|ruby|rt|rp|time|progress|meter|output|area|map)`)
|
|
return regex.MatchString(content)
|
|
}
|
|
|
|
func convertHtmlToText(content string) string {
|
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
|
|
if err != nil {
|
|
log.Errorf("failed to convert html to text: %v", err)
|
|
trace.PrintError(err)
|
|
return ""
|
|
}
|
|
return doc.Text()
|
|
}
|
|
|
|
type smtpAuthentication struct {
|
|
Server string
|
|
Port int
|
|
SenderEmail string
|
|
SenderIdentity string
|
|
SMTPUser string
|
|
SMTPPassword string
|
|
}
|
|
|
|
// sendOptions are options for sending an email
|
|
type sendOptions struct {
|
|
Subject string
|
|
To string
|
|
Cc string
|
|
Bcc string
|
|
}
|
|
|
|
// send email
|
|
func send(smtpConfig smtpAuthentication, options sendOptions, htmlBody string, txtBody string) error {
|
|
if smtpConfig.Server == "" {
|
|
return errors.New("SMTP server config is empty")
|
|
}
|
|
|
|
if smtpConfig.Port == 0 {
|
|
return errors.New("SMTP port config is empty")
|
|
}
|
|
|
|
if smtpConfig.SMTPUser == "" {
|
|
return errors.New("SMTP user is empty")
|
|
}
|
|
|
|
if options.To == "" {
|
|
return errors.New("no receiver emails configured")
|
|
}
|
|
|
|
from := mail.Address{
|
|
Name: smtpConfig.SenderIdentity,
|
|
Address: smtpConfig.SenderEmail,
|
|
}
|
|
|
|
var toList []string
|
|
if strings.Contains(options.To, ";") {
|
|
toList = strings.Split(options.To, ";")
|
|
// trim space
|
|
for i, to := range toList {
|
|
toList[i] = strings.TrimSpace(to)
|
|
}
|
|
} else {
|
|
toList = []string{options.To}
|
|
}
|
|
|
|
m := gomail.NewMessage()
|
|
m.SetHeader("From", from.String())
|
|
m.SetHeader("To", getRecipientList(options.To)...)
|
|
m.SetHeader("Subject", options.Subject)
|
|
if options.Cc != "" {
|
|
m.SetHeader("Cc", getRecipientList(options.Cc)...)
|
|
}
|
|
if options.Bcc != "" {
|
|
m.SetHeader("Bcc", getRecipientList(options.Bcc)...)
|
|
}
|
|
|
|
m.SetBody("text/plain", txtBody)
|
|
m.AddAlternative("text/html", htmlBody)
|
|
|
|
d := gomail.NewDialer(smtpConfig.Server, smtpConfig.Port, smtpConfig.SMTPUser, smtpConfig.SMTPPassword)
|
|
|
|
return d.DialAndSend(m)
|
|
}
|
|
|
|
func getRecipientList(value string) (values []string) {
|
|
if strings.Contains(value, ";") {
|
|
values = strings.Split(value, ";")
|
|
// trim space
|
|
for i, v := range values {
|
|
values[i] = strings.TrimSpace(v)
|
|
}
|
|
} else {
|
|
values = []string{value}
|
|
}
|
|
return values
|
|
}
|