Closed markbates closed 7 years ago
I'm thinking of being able to send emails with different smtp options, support templates, etc...
@markbates can i take this story ? i would love to work on it for the next release, WDYT ?
@apaganobeleno sure, go for it!
here's an implementation of something I have in an app:
package mailers
import (
"path/filepath"
"strconv"
"github.com/gobuffalo/buffalo"
"github.com/gobuffalo/envy"
"github.com/gobuffalo/packr"
"github.com/gobuffalo/plush"
"github.com/gopherguides/web/models"
"github.com/pkg/errors"
"github.com/shurcooL/github_flavored_markdown"
gomail "gopkg.in/gomail.v2"
)
var dialer *gomail.Dialer
var templateBox = packr.NewBox("../templates")
func init() {
port, _ := strconv.Atoi(envy.Get("SMTP_PORT", "1025"))
dialer = gomail.NewDialer(envy.Get("SMTP_HOST", "localhost"), port, envy.Get("SMTP_USER", ""), envy.Get("SMTP_PASSWORD", ""))
}
type Message struct {
*gomail.Message
dialer *gomail.Dialer
}
func (m *Message) SetSubject(f string) {
m.Message.SetHeader("Subject", f)
}
func (m *Message) SetFrom(f string) {
m.Message.SetHeader("From", f)
}
func (m *Message) SetTo(to ...string) {
m.Message.SetHeader("To", to...)
}
func (m *Message) SetBody(ct string, path string, data map[string]interface{}) error {
tmpl, err := templateBox.MustString(path)
if err != nil {
return errors.WithStack(err)
}
s, err := plush.Render(tmpl, plush.NewContextWith(data))
if err != nil {
return errors.WithStack(err)
}
if filepath.Ext(path) == ".md" {
s = string(github_flavored_markdown.Markdown([]byte(s)))
}
m.Message.SetBody(ct, s)
return nil
}
func (m Message) Deliver() error {
return m.dialer.DialAndSend(m.Message)
}
func NewMessage() *Message {
return &Message{
dialer: dialer,
Message: gomail.NewMessage(),
}
}
func NewContactMessage(c *models.Contact) *Message {
m := NewMessage()
m.SetFrom("info@gopherguides.com")
m.SetTo("info@gopherguides.com")
m.SetBody("text/html", "mail/new_contact.md", map[string]interface{}{
"contact": c,
})
m.SetSubject("New Contact | Gopher Guides")
return m
}
func NewTrainerOpportunityMessage(c *models.TrainerOpportunity) *Message {
m := NewMessage()
m.SetFrom("info@gopherguides.com")
m.SetTo("info@gopherguides.com")
m.SetBody("text/html", "mail/new_trainer_opportunity.md", map[string]interface{}{
"trainerOpportunity": c,
})
m.SetSubject("New Trainer Opportunity | Gopher Guides")
return m
}
it's not perfect, but it might give you some ideas as to what the API might look like.
Thats a good start @markbates ! Adding here what i'm thinking mail support should be inside buffalo:
buffalo g mailer user
.are there other things i'm forgetting about ?
Those all sound correct to me. I'm sure we'll come up with other stuff as we move deeper into this.
@markbates i build this small Gist to show progress on this ticket https://gist.github.com/apaganobeleno/4bf9fc532857a4a36164627e8c3c6455, LMK your thoughts.
I have some "shape" questions for this implementation:
Cool. I'll have a look in the morning. But to answer your questions, I definitely think it should be in a separate package. perhaps the github.com/gobuffalo/x/
packages to start with. just a thought.
I'll review the gist tomorrow and outline a few of my own thoughts.
I think you need a proper message type, something like this:
type Message struct {
From string
To []string
CC []string
Bcc []string
Subject string
// ...
}
func (m *Message) AddBody(r render.Renderer, data render.Data) error {
return nil
}
func (m *Message) AddAttachment(name, content_type string, r io.Reader) error {
return nil
}
And an Deliverer
interface:
type Deliverer interface {
Deliver(Message) error
}
Then you can use it like this:
import "github.com/gobuffalo/x/mail/smtp"
var mailer Deliverer
func init() {
mailer = smtp.New(//...)
}
func SendWelcomeEmail(data render.Data) error {
m := NewMessage()
m.From = "mark@example.com"
// ...
m.AddBody(r.HTML("welcom.html"), data)
m.AddAttachment("foo.pdf", "application/pdf", myPDFReader)
return mailer.Deliver(m)
}
I hope that all makes sense, I know it's pseudo-code and all.
@markbates should we then move this issue to be on the gobuffalo/x repo ?
Yeah, we should.
@markbates Is the idea here , for there to be a
mail
helper or are we looking for something that supports different smtp options including templates?I'm thinking along the lines of the
mail_to
helper in Rails...