2017-01-16 13:20:59 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-12-01 13:51:43 +01:00
|
|
|
"bufio"
|
2017-01-16 13:20:59 +01:00
|
|
|
"crypto/tls"
|
2020-12-01 13:51:43 +01:00
|
|
|
"os"
|
|
|
|
|
2017-01-16 13:20:59 +01:00
|
|
|
log "github.com/Sirupsen/logrus"
|
|
|
|
"github.com/aymerick/douceur/inliner"
|
|
|
|
"github.com/drone/drone-go/template"
|
|
|
|
"github.com/jaytaylor/html2text"
|
2021-10-29 22:27:55 +02:00
|
|
|
gomail "gopkg.in/mail.v2"
|
2017-01-16 13:20:59 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
Repo struct {
|
2017-01-17 10:58:35 +01:00
|
|
|
FullName string
|
|
|
|
Owner string
|
|
|
|
Name string
|
|
|
|
SCM string
|
|
|
|
Link string
|
|
|
|
Avatar string
|
|
|
|
Branch string
|
|
|
|
Private bool
|
|
|
|
Trusted bool
|
|
|
|
}
|
|
|
|
|
|
|
|
Remote struct {
|
|
|
|
URL string
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Author struct {
|
|
|
|
Name string
|
|
|
|
Email string
|
|
|
|
Avatar string
|
|
|
|
}
|
|
|
|
|
2017-01-17 10:58:35 +01:00
|
|
|
Commit struct {
|
|
|
|
Sha string
|
2017-01-16 13:20:59 +01:00
|
|
|
Ref string
|
|
|
|
Branch string
|
|
|
|
Link string
|
2017-01-17 10:58:35 +01:00
|
|
|
Message string
|
|
|
|
Author Author
|
|
|
|
}
|
|
|
|
|
|
|
|
Build struct {
|
|
|
|
Number int
|
|
|
|
Event string
|
|
|
|
Status string
|
|
|
|
Link string
|
|
|
|
Created int64
|
|
|
|
Started int64
|
|
|
|
Finished int64
|
|
|
|
}
|
|
|
|
|
|
|
|
PrevBuild struct {
|
|
|
|
Status string
|
|
|
|
Number int
|
|
|
|
}
|
|
|
|
|
|
|
|
PrevCommit struct {
|
|
|
|
Sha string
|
|
|
|
}
|
|
|
|
|
|
|
|
Prev struct {
|
|
|
|
Build PrevBuild
|
|
|
|
Commit PrevCommit
|
|
|
|
}
|
|
|
|
|
|
|
|
Job struct {
|
|
|
|
Status string
|
|
|
|
ExitCode int
|
|
|
|
Started int64
|
|
|
|
Finished int64
|
|
|
|
}
|
|
|
|
|
|
|
|
Yaml struct {
|
|
|
|
Signed bool
|
|
|
|
Verified bool
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Config struct {
|
2021-10-13 08:52:55 +02:00
|
|
|
FromAddress string
|
|
|
|
FromName string
|
2017-01-16 13:20:59 +01:00
|
|
|
Host string
|
|
|
|
Port int
|
|
|
|
Username string
|
|
|
|
Password string
|
|
|
|
SkipVerify bool
|
2021-11-01 18:56:45 +01:00
|
|
|
NoStartTLS bool
|
2017-01-16 13:20:59 +01:00
|
|
|
Recipients []string
|
2020-12-01 13:51:43 +01:00
|
|
|
RecipientsFile string
|
2017-01-16 13:20:59 +01:00
|
|
|
RecipientsOnly bool
|
|
|
|
Subject string
|
|
|
|
Body string
|
2017-08-31 11:14:08 +02:00
|
|
|
Attachment string
|
2019-08-23 18:06:45 +02:00
|
|
|
Attachments []string
|
2020-12-01 13:51:43 +01:00
|
|
|
ClientHostname string
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Plugin struct {
|
2017-01-17 10:58:35 +01:00
|
|
|
Repo Repo
|
|
|
|
Remote Remote
|
|
|
|
Commit Commit
|
|
|
|
Build Build
|
|
|
|
Prev Prev
|
|
|
|
Job Job
|
|
|
|
Yaml Yaml
|
|
|
|
Tag string
|
|
|
|
PullRequest int
|
|
|
|
DeployTo string
|
|
|
|
Config Config
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// Exec will send emails over SMTP
|
|
|
|
func (p Plugin) Exec() error {
|
|
|
|
var dialer *gomail.Dialer
|
|
|
|
|
|
|
|
if !p.Config.RecipientsOnly {
|
2017-01-24 14:39:13 +01:00
|
|
|
exists := false
|
|
|
|
for _, recipient := range p.Config.Recipients {
|
|
|
|
if recipient == p.Commit.Author.Email {
|
|
|
|
exists = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !exists {
|
|
|
|
p.Config.Recipients = append(p.Config.Recipients, p.Commit.Author.Email)
|
|
|
|
}
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
|
2020-12-01 13:51:43 +01:00
|
|
|
if p.Config.RecipientsFile != "" {
|
|
|
|
f, err := os.Open(p.Config.RecipientsFile)
|
|
|
|
if err == nil {
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
|
|
for scanner.Scan() {
|
|
|
|
p.Config.Recipients = append(p.Config.Recipients, scanner.Text())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Errorf("Could not open RecipientsFile %s: %v", p.Config.RecipientsFile, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-16 13:20:59 +01:00
|
|
|
if p.Config.Username == "" && p.Config.Password == "" {
|
|
|
|
dialer = &gomail.Dialer{Host: p.Config.Host, Port: p.Config.Port}
|
|
|
|
} else {
|
|
|
|
dialer = gomail.NewDialer(p.Config.Host, p.Config.Port, p.Config.Username, p.Config.Password)
|
|
|
|
}
|
2021-10-29 22:27:55 +02:00
|
|
|
|
2017-01-16 13:20:59 +01:00
|
|
|
if p.Config.SkipVerify {
|
|
|
|
dialer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
|
|
|
}
|
2021-10-29 22:27:55 +02:00
|
|
|
|
2021-11-01 18:56:45 +01:00
|
|
|
if p.Config.NoStartTLS {
|
2021-10-29 22:27:55 +02:00
|
|
|
dialer.StartTLSPolicy = gomail.NoStartTLS
|
|
|
|
}
|
|
|
|
|
2020-12-01 13:51:43 +01:00
|
|
|
dialer.LocalName = p.Config.ClientHostname
|
2017-01-16 13:20:59 +01:00
|
|
|
|
|
|
|
closer, err := dialer.Dial()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Error while dialing SMTP server: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
type Context struct {
|
2017-01-17 10:58:35 +01:00
|
|
|
Repo Repo
|
|
|
|
Remote Remote
|
|
|
|
Commit Commit
|
|
|
|
Build Build
|
|
|
|
Prev Prev
|
|
|
|
Job Job
|
|
|
|
Yaml Yaml
|
|
|
|
Tag string
|
|
|
|
PullRequest int
|
|
|
|
DeployTo string
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
ctx := Context{
|
2017-01-17 10:58:35 +01:00
|
|
|
Repo: p.Repo,
|
|
|
|
Remote: p.Remote,
|
|
|
|
Commit: p.Commit,
|
|
|
|
Build: p.Build,
|
|
|
|
Prev: p.Prev,
|
|
|
|
Job: p.Job,
|
|
|
|
Yaml: p.Yaml,
|
|
|
|
Tag: p.Tag,
|
|
|
|
PullRequest: p.PullRequest,
|
|
|
|
DeployTo: p.DeployTo,
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Render body in HTML and plain text
|
|
|
|
renderedBody, err := template.RenderTrim(p.Config.Body, ctx)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Could not render body template: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
html, err := inliner.Inline(renderedBody)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Could not inline rendered body: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
plainBody, err := html2text.FromString(html)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Could not convert html to text: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Render subject
|
|
|
|
subject, err := template.RenderTrim(p.Config.Subject, ctx)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Could not render subject template: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send emails
|
|
|
|
message := gomail.NewMessage()
|
|
|
|
for _, recipient := range p.Config.Recipients {
|
2018-02-27 12:00:49 +01:00
|
|
|
if len(recipient) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
2021-10-13 08:52:55 +02:00
|
|
|
message.SetAddressHeader("From", p.Config.FromAddress, p.Config.FromName)
|
2017-01-16 13:20:59 +01:00
|
|
|
message.SetAddressHeader("To", recipient, "")
|
|
|
|
message.SetHeader("Subject", subject)
|
|
|
|
message.AddAlternative("text/plain", plainBody)
|
|
|
|
message.AddAlternative("text/html", html)
|
|
|
|
|
2017-08-31 11:14:08 +02:00
|
|
|
if p.Config.Attachment != "" {
|
2019-09-06 22:43:01 +02:00
|
|
|
attach(message, p.Config.Attachment)
|
2017-08-31 11:14:08 +02:00
|
|
|
}
|
|
|
|
|
2019-08-23 18:06:45 +02:00
|
|
|
for _, attachment := range p.Config.Attachments {
|
2019-09-06 22:43:01 +02:00
|
|
|
attach(message, attachment)
|
2019-08-23 18:06:45 +02:00
|
|
|
}
|
|
|
|
|
2017-01-16 13:20:59 +01:00
|
|
|
if err := gomail.Send(closer, message); err != nil {
|
|
|
|
log.Errorf("Could not send email to %q: %v", recipient, err)
|
2017-07-12 15:48:45 +02:00
|
|
|
return err
|
2017-01-16 13:20:59 +01:00
|
|
|
}
|
|
|
|
message.Reset()
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2019-09-06 22:43:01 +02:00
|
|
|
|
|
|
|
func attach(message *gomail.Message, attachment string) {
|
|
|
|
if _, err := os.Stat(attachment); err == nil {
|
|
|
|
message.Attach(attachment)
|
|
|
|
}
|
|
|
|
}
|