Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Proposal: move github.com/gobuffalo/x/mail into Buffalo "Core" fixes #752 #762

Merged
merged 1 commit into from
Nov 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ RUN filetest -c $GOPATH/src/github.com/gobuffalo/buffalo/buffalo/cmd/filetests/g
RUN buffalo g resource person_event
RUN filetest -c $GOPATH/src/github.com/gobuffalo/buffalo/buffalo/cmd/filetests/generate_underscore.json

RUN buffalo g mailer welcome_email
RUN filetest -c $GOPATH/src/github.com/gobuffalo/buffalo/buffalo/cmd/filetests/generate_mailer.json

RUN rm -rf bin
RUN buffalo build -k -e
RUN filetest -c $GOPATH/src/github.com/gobuffalo/buffalo/buffalo/cmd/filetests/no_assets_build.json
30 changes: 30 additions & 0 deletions buffalo/cmd/filetests/generate_mailer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[{
"path": "mailers/mailers.go",
"contains": [
"github.com/gobuffalo/buffalo/mail",
"smtp, err = mail.NewSMTPSender(host, port, user, password)"
],
"!contains": [
"github.com/gobuffalo/x/mail"
]
},
{
"path": "templates/mail/layout.html",
"contains": [
"<h1>templates/mailers/layout.html</h1>"
]
},
{
"path": "mailers/welcome_email.go",
"contains": [
"err := m.AddBody(r.HTML(\"welcome_email.html\"), render.Data{})"
]
},
{
"path": "templates/mail/welcome_email.html",
"contains": [
"<h2>Welcome Email</h2>",
"<h3>../templates/mail/welcome_email.html</h3>"
]
}
]
1 change: 1 addition & 0 deletions buffalo/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func init() {
generateCmd.AddCommand(generate.ActionCmd)
generateCmd.AddCommand(generate.DockerCmd)
generateCmd.AddCommand(generate.TaskCmd)
generateCmd.AddCommand(generate.MailCmd)
decorate("generate", generateCmd)

RootCmd.AddCommand(generateCmd)
Expand Down
31 changes: 31 additions & 0 deletions buffalo/cmd/generate/mailer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package generate

import (
"github.com/gobuffalo/buffalo/generators/mail"
"github.com/gobuffalo/buffalo/meta"
"github.com/gobuffalo/makr"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var mailer = mail.Generator{}

// MailCmd for generating mailers
var MailCmd = &cobra.Command{
Use: "mailer",
Short: "Generates a new mailer for Buffalo",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("you must supply a name for your mailer")
}
mailer.App = meta.New(".")
mailer.Name = meta.Name(args[0])
data := makr.Data{}
return mailer.Run(".", data)

},
}

func init() {
MailCmd.Flags().BoolVar(&mailer.SkipInit, "skip-init", false, "skip initializing mailers/")
}
36 changes: 36 additions & 0 deletions generators/mail/init/templates/mailers/mailers.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package mailers

import (
"log"

"github.com/gobuffalo/buffalo/render"
"github.com/gobuffalo/envy"
"github.com/gobuffalo/packr"
"github.com/gobuffalo/buffalo/mail"
"github.com/pkg/errors"
)

var smtp mail.Sender
var r *render.Engine

func init() {

// Pulling config from the env.
port := envy.Get("SMTP_PORT", "1025")
host := envy.Get("SMTP_HOST", "localhost")
user := envy.Get("SMTP_USER", "")
password := envy.Get("SMTP_PASSWORD", "")

var err error
smtp, err = mail.NewSMTPSender(host, port, user, password)

if err != nil {
log.Fatal(err)
}

r = render.New(render.Options{
HTMLLayout: "layout.html",
TemplatesBox: packr.NewBox("../templates/mail"),
Helpers: render.Helpers{},
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>templates/mailers/layout.html</h1>

<%= yield %>
84 changes: 84 additions & 0 deletions generators/mail/mail.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package mail

import (
"os"
"path/filepath"

"github.com/gobuffalo/buffalo/generators"
"github.com/gobuffalo/buffalo/meta"
"github.com/gobuffalo/makr"
"github.com/pkg/errors"
)

// Generator for creating new mailers
type Generator struct {
App meta.App `json:"app"`
Name meta.Name `json:"name"`
SkipInit bool `json:"skip_init"`
}

// Run the new mailer generator. It will init the mailers directory
// if it doesn't already exist
func (d Generator) Run(root string, data makr.Data) error {
g := makr.New()
defer g.Fmt(root)
data["opts"] = d

if err := d.initGenerator(data); err != nil {
return errors.WithStack(err)
}

fn := d.Name.File()
g.Add(makr.NewFile(filepath.Join("mailers", fn+".go"), mailerTmpl))
g.Add(makr.NewFile(filepath.Join("templates", "mail", fn+".html"), mailTmpl))
return g.Run(root, data)
}

func (d Generator) initGenerator(data makr.Data) error {
files, err := generators.Find(filepath.Join(generators.TemplatesPath, "mail", "init"))
if err != nil {
return errors.WithStack(err)
}
g := makr.New()
for _, f := range files {
g.Add(makr.NewFile(f.WritePath, f.Body))
}

g.Should = func(data makr.Data) bool {
if d.SkipInit {
return false
}
if _, err := os.Stat(filepath.Join("mailers", "mailers.go")); err == nil {
return false
}
return true
}
return g.Run(".", data)
}

const mailerTmpl = `package mailers
import (
"github.com/gobuffalo/buffalo/render"
"github.com/gobuffalo/buffalo/mail"
"github.com/pkg/errors"
)
func Send{{.opts.Name.Model}}() error {
m := mail.NewMessage()
// fill in with your stuff:
m.Subject = "{{.opts.Name.Title}}"
m.From = ""
m.To = []string{}
err := m.AddBody(r.HTML("{{.opts.Name.File}}.html"), render.Data{})
if err != nil {
return errors.WithStack(err)
}
return smtp.Send(m)
}
`

const mailTmpl = `<h2>{{.opts.Name.Title}}</h2>
<h3>../templates/mail/{{.opts.Name.File}}.html</h3>`
125 changes: 125 additions & 0 deletions mail/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# github.com/gobuffalo/buffalo/mail

This package is intended to allow easy Email sending with Buffalo, it allows you to define your custom `mail.Sender` for the provider you would like to use.

## Generator

```bash
$ buffalo generate mailer welcome_email
```

## Example Usage

```go
//actions/mail.go
package x

import (
"log"

"github.com/gobuffalo/buffalo/render"
"github.com/gobuffalo/envy"
"github.com/gobuffalo/packr"
"github.com/gobuffalo/plush"
"github.com/gobuffalo/buffalo/mail"
"github.com/pkg/errors"
"gitlab.com/wawandco/app/models"
)

var smtp mail.Sender
var r *render.Engine

func init() {

//Pulling config from the env.
port := envy.Get("SMTP_PORT", "1025")
host := envy.Get("SMTP_HOST", "localhost")
user := envy.Get("SMTP_USER", "")
password := envy.Get("SMTP_PASSWORD", "")

var err error
smtp, err = mail.NewSMTPSender(host, port, user, password)

if err != nil {
log.Fatal(err)
}

//The rendering engine, this is usually generated inside actions/render.go in your buffalo app.
r = render.New(render.Options{
TemplatesBox: packr.NewBox("../templates"),
})
}

//SendContactMessage Sends contact message to [email protected]
func SendContactMessage(c *models.Contact) error {

//Creates a new message
m := mail.NewMessage()
m.From = "[email protected]"
m.Subject = "New Contact"
m.To = []string{"[email protected]"}

// Data that will be used inside the templates when rendering.
data := map[string]interface{}{
"contact": c,
}

// You can add multiple bodies to the message you're creating to have content-types alternatives.
err := m.AddBodies(data, r.HTML("mail/contact.html"), r.Plain("mail/contact.txt"))

if err != nil {
return errors.WithStack(err)
}

err = smtp.Send(m)
if err != nil {
return errors.WithStack(err)
}

return nil
}

```

This `SendContactMessage` could be called by one of your actions, p.e. the action that handles your contact form submission.

```go
//actions/contact.go
...

func ContactFormHandler(c buffalo.Context) error {
contact := &models.Contact{}
c.Bind(contact)

//Calling to send the message
SendContactMessage(contact)
return c.Redirect(302, "contact/thanks")
}
...
```

If you're using Gmail or need to configure your SMTP connection you can use the Dialer property on the SMTPSender, p.e: (for Gmail)

```go
...
var smtp mail.Sender

func init() {
port := envy.Get("SMTP_PORT", "465")
// or 587 with TLS

host := envy.Get("SMTP_HOST", "smtp.gmail.com")
user := envy.Get("SMTP_USER", "[email protected]")
password := envy.Get("SMTP_PASSWORD", "yourp4ssw0rd")

var err error
sender, err := mail.NewSMTPSender(host, port, user, password)
sender.Dialer.SSL = true

//or if TLS
sender.Dialer.TLSConfig = &tls.Config{...}

smtp = sender
}
...
```
6 changes: 6 additions & 0 deletions mail/mail.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package mail

// Sender interface for any upcomming mailers.
type Sender interface {
Send(Message) error
}
Loading