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

Commit

Permalink
Merge pull request #762 from gobuffalo/mail-merge
Browse files Browse the repository at this point in the history
Proposal: move github.com/gobuffalo/x/mail into Buffalo "Core" fixes #752
  • Loading branch information
markbates authored Nov 17, 2017
2 parents a08810f + a057b31 commit 65de218
Show file tree
Hide file tree
Showing 12 changed files with 539 additions and 0 deletions.
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 contact@myapp.com
func SendContactMessage(c *models.Contact) error {

//Creates a new message
m := mail.NewMessage()
m.From = "sender@myapp.com"
m.Subject = "New Contact"
m.To = []string{"contact@myapp.com"}

// 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", "your@email.com")
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

0 comments on commit 65de218

Please sign in to comment.