Skip to content

Commit

Permalink
feat: add SMTP support to the announces (#2485)
Browse files Browse the repository at this point in the history
Signed-off-by: Batuhan Apaydın <batuhan.apaydin@trendyol.com>
Co-authored-with: Erkan Zileli <erkan.zileli@trendyol.com>
Co-authored-with: Furkan Turkal <furkan.turkal@trendyol.com>
  • Loading branch information
developer-guy committed Sep 15, 2021
1 parent a9074a3 commit afad409
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 9 deletions.
2 changes: 2 additions & 0 deletions go.mod
Expand Up @@ -110,6 +110,7 @@ require (
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 // indirect
google.golang.org/grpc v1.40.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/mail.v2 v2.3.1
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
Expand All @@ -130,4 +131,5 @@ require (
github.com/aws/smithy-go v1.8.0 // indirect
github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Expand Up @@ -1122,6 +1122,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand All @@ -1132,6 +1134,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
Expand Down
2 changes: 2 additions & 0 deletions internal/pipe/announce/announce.go
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/goreleaser/goreleaser/internal/pipe/discord"
"github.com/goreleaser/goreleaser/internal/pipe/reddit"
"github.com/goreleaser/goreleaser/internal/pipe/slack"
"github.com/goreleaser/goreleaser/internal/pipe/smtp"
"github.com/goreleaser/goreleaser/internal/pipe/teams"
"github.com/goreleaser/goreleaser/internal/pipe/twitter"
"github.com/goreleaser/goreleaser/pkg/context"
Expand All @@ -33,6 +34,7 @@ var announcers = []Announcer{
discord.Pipe{},
reddit.Pipe{},
slack.Pipe{},
smtp.Pipe{},
teams.Pipe{},
twitter.Pipe{},
}
Expand Down
96 changes: 96 additions & 0 deletions internal/pipe/smtp/smtp.go
@@ -0,0 +1,96 @@
package smtp

import (
"crypto/tls"
"fmt"

"github.com/apex/log"
"github.com/caarlos0/env/v6"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/context"
gomail "gopkg.in/mail.v2"
)

const (
defaultSubjectTemplate = `{{ .ProjectName }} {{ .Tag }} is out!`
defaultBodyTemplate = `You can view details from: {{ .GitURL }}/releases/tag/{{ .Tag }}`
)

type Pipe struct{}

func (Pipe) String() string { return "reddit" }

type Config struct {
Host string `env:"SMTP_HOST,notEmpty"`
Port int `env:"SMTP_PORT,notEmpty"`
Username string `env:"SMTP_USERNAME,notEmpty"`
Password string `env:"SMTP_PASSWORD,notEmpty"`
}

func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Announce.SMTP.SubjectTemplate == "" {
ctx.Config.Announce.SMTP.SubjectTemplate = defaultSubjectTemplate
}

if ctx.Config.Announce.SMTP.BodyTemplate == "" {
ctx.Config.Announce.SMTP.BodyTemplate = defaultBodyTemplate
}

return nil
}

func (Pipe) Announce(ctx *context.Context) error {
if ctx.SkipAnnounce {
return pipe.ErrSkipAnnounceEnabled
}
if !ctx.Config.Announce.SMTP.Enabled {
return pipe.ErrSkipDisabledPipe
}

subject, err := tmpl.New(ctx).Apply(ctx.Config.Announce.SMTP.SubjectTemplate)
if err != nil {
return fmt.Errorf("announce: failed to announce to SMTP: %w", err)
}

body, err := tmpl.New(ctx).Apply(ctx.Config.Announce.SMTP.BodyTemplate)
if err != nil {
return fmt.Errorf("announce: failed to announce to SMTP: %w", err)
}

m := gomail.NewMessage()

// Set E-Mail sender
m.SetHeader("From", ctx.Config.Announce.SMTP.From)

// Set E-Mail receivers
receivers := ctx.Config.Announce.SMTP.To
m.SetHeader("To", receivers...)

// Set E-Mail subject
m.SetHeader("Subject", subject)

// Set E-Mail body. You can set plain text or html with text/html
m.SetBody("text/plain", body)

var cfg Config
if err := env.Parse(&cfg); err != nil {
return fmt.Errorf("announce: failed to announce to SMTP: %w", err)
}

// Settings for SMTP server
d := gomail.NewDialer(cfg.Host, cfg.Port, cfg.Username, cfg.Password)

// This is only needed when SSL/TLS certificate is not valid on server.
// In production this should be set to false.
d.TLSConfig = &tls.Config{InsecureSkipVerify: ctx.Config.Announce.SMTP.InsecureSkipVerify}

// Now send E-Mail
if err := d.DialAndSend(m); err != nil {
return fmt.Errorf("announce: failed to announce to SMTP: %w", err)
}

log.Infof("announce: The mail has been send from %s to %s\n", ctx.Config.Announce.SMTP.From, receivers)

return nil
}
13 changes: 13 additions & 0 deletions pkg/config/config.go
Expand Up @@ -696,6 +696,7 @@ type Announce struct {
Slack Slack `yaml:"slack,omitempty"`
Discord Discord `yaml:"discord,omitempty"`
Teams Teams `yaml:"teams,omitempty"`
SMTP SMTP `yaml:"smtp,omitempty"`
}

type Twitter struct {
Expand Down Expand Up @@ -737,6 +738,18 @@ type Teams struct {
IconURL string `yaml:"icon_url,omitempty"`
}

type SMTP struct {
Enabled bool `yaml:"enabled,omitempty"`
Host string `yaml:"host,omitempty"`
Port int `yaml:"port,omitempty"`
Username string `yaml:"username,omitempty"`
From string `yaml:"from,omitempty"`
To []string `yaml:"to,omitempty"`
SubjectTemplate string `yaml:"subject_template,omitempty"`
BodyTemplate string `yaml:"body_template,omitempty"`
InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty"`
}

// Load config file.
func Load(file string) (config Project, err error) {
f, err := os.Open(file) // #nosec
Expand Down
2 changes: 2 additions & 0 deletions pkg/defaults/defaults.go
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/goreleaser/goreleaser/internal/pipe/scoop"
"github.com/goreleaser/goreleaser/internal/pipe/sign"
"github.com/goreleaser/goreleaser/internal/pipe/slack"
"github.com/goreleaser/goreleaser/internal/pipe/smtp"
"github.com/goreleaser/goreleaser/internal/pipe/snapcraft"
"github.com/goreleaser/goreleaser/internal/pipe/snapshot"
"github.com/goreleaser/goreleaser/internal/pipe/sourcearchive"
Expand Down Expand Up @@ -65,5 +66,6 @@ var Defaulters = []Defaulter{
slack.Pipe{},
teams.Pipe{},
twitter.Pipe{},
smtp.Pipe{},
milestone.Pipe{},
}
66 changes: 57 additions & 9 deletions www/docs/customization/announce.md
Expand Up @@ -4,11 +4,13 @@ title: Announce

GoReleaser can also announce new releases to Twitter, Reddit, Slack, Discourse and Microsoft Teams.

It runs at the very end of the pipeline and can be skipped with the `--skip-announce` flag of the [`release`](/cmd/goreleaser_release/) command.
It runs at the very end of the pipeline and can be skipped with the `--skip-announce` flag of
the [`release`](/cmd/goreleaser_release/) command.

## Twitter

For it to work, you'll need to [create a new Twitter app](https://developer.twitter.com/en/portal/apps/new), and set some environment variables on your pipeline:
For it to work, you'll need to [create a new Twitter app](https://developer.twitter.com/en/portal/apps/new), and set
some environment variables on your pipeline:

- `TWITTER_CONSUMER_KEY`
- `TWITTER_CONSUMER_SECRET`
Expand All @@ -32,7 +34,9 @@ announce:

## Teams

To use [Teams](https://www.microsoft.com/de-de/microsoft-teams/group-chat-software), you need to [create a Webhook](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook), and set following environment variable on your pipeline:
To use [Teams](https://www.microsoft.com/de-de/microsoft-teams/group-chat-software), you need
to [create a Webhook](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook)
, and set following environment variable on your pipeline:

- `TEAMS_WEBHOOK`

Expand Down Expand Up @@ -65,7 +69,9 @@ announce:

## Discord

To use [Discord](https://discord.com/), you need to [create a Webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks), and set following environment variables on your pipeline:
To use [Discord](https://discord.com/), you need
to [create a Webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks), and set following
environment variables on your pipeline:

- `DISCORD_WEBHOOK_ID`
- `DISCORD_WEBHOOK_TOKEN`
Expand Down Expand Up @@ -97,10 +103,10 @@ announce:
icon_url: ''
```


## Slack

For it to work, you'll need to [create a new Incoming Webhook](https://api.slack.com/messaging/webhooks), and set some environment variables on your pipeline:
For it to work, you'll need to [create a new Incoming Webhook](https://api.slack.com/messaging/webhooks), and set some
environment variables on your pipeline:

- `SLACK_WEBHOOK`

Expand Down Expand Up @@ -131,12 +137,12 @@ announce:
icon_url: ''
```

!!! tip
Learn more about the [name template engine](/customization/templates/).
!!! tip Learn more about the [name template engine](/customization/templates/).

## Reddit

For it to work, you'll need to [create a new Reddit app](https://www.reddit.com/prefs/apps), and set some environment variables on your pipeline:
For it to work, you'll need to [create a new Reddit app](https://www.reddit.com/prefs/apps), and set some environment
variables on your pipeline:

- `REDDIT_SECRET`
- `REDDIT_PASSWORD`
Expand Down Expand Up @@ -165,3 +171,45 @@ announce:
# Defaults to `{{ .ProjectName }} {{ .Tag }} is out!`
title_template: ''GoReleaser {{ .Tag }} was just released!''
```

## SMTP

For it to work, you'll need to set some environment variables on your pipeline:

- `SMTP_PASSWORD`

Then, you can add something like the following to your `.goreleaser.yml` config:

```yaml
# .goreleaser.yml
announce:
smtp:
# Wether its enabled or not.
# Defaults to false.
enabled: true

# SMTP Host
host: "smtp.gmail.com"

# SMTP Port
port: 587

# Sender of the email
from: ""

# Receivers of the email
to:
- ""
- ""

# Owner of the email
username: ""

# Body template to use within the email.
# Defaults to `You can view details from: {{ .GitURL }}/releases/tag/{{ .Tag }}`
body_template: 'https://github.com/goreleaser/goreleaser/releases/tag/{{ .Tag }}'

# Subject template to use within the email subject.
# Defaults to `{{ .ProjectName }} {{ .Tag }} is out!`
subject_template: ''GoReleaser {{ .Tag }} was just released!''
```

1 comment on commit afad409

@vercel
Copy link

@vercel vercel bot commented on afad409 Sep 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.