Noah Petherbridge
2a8a1df6ab
* Initial codebase (lot of work!) * Uses vanilla Go net/http and implements by hand: session cookies backed by Redis; log in/out; CSRF protection; email verification flow; initial database models (User table)
90 lines
2.2 KiB
Go
90 lines
2.2 KiB
Go
// Package mail provides e-mail sending faculties.
|
|
package mail
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"html/template"
|
|
"strings"
|
|
|
|
"git.kirsle.net/apps/gosocial/pkg/config"
|
|
"git.kirsle.net/apps/gosocial/pkg/log"
|
|
"github.com/microcosm-cc/bluemonday"
|
|
"gopkg.in/gomail.v2"
|
|
)
|
|
|
|
// Message configuration.
|
|
type Message struct {
|
|
To string
|
|
ReplyTo string
|
|
Subject string
|
|
Template string // path relative to the templates dir, e.g. "email/verify_email.html"
|
|
Data map[string]interface{}
|
|
}
|
|
|
|
// Send an email.
|
|
func Send(msg Message) error {
|
|
conf := config.Current.Mail
|
|
|
|
// Verify configuration.
|
|
if !conf.Enabled {
|
|
return errors.New(
|
|
"Email sending is not configured for this app. Please contact the website administrator about this error.",
|
|
)
|
|
} else if conf.Host == "" || conf.Port == 0 || conf.From == "" {
|
|
return errors.New(
|
|
"Email settings are misconfigured for this app. Please contact the website administrator about this error.",
|
|
)
|
|
}
|
|
|
|
// Get and render the template to HTML.
|
|
var html bytes.Buffer
|
|
tmpl, err := template.New(msg.Template).ParseFiles(config.TemplatePath + "/" + msg.Template)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Execute the template.
|
|
err = tmpl.ExecuteTemplate(&html, "content", msg)
|
|
if err != nil {
|
|
return fmt.Errorf("Mail template execute error: %s", err)
|
|
}
|
|
|
|
// Condense the HTML down into the plaintext version.
|
|
rawLines := strings.Split(
|
|
bluemonday.StrictPolicy().Sanitize(html.String()),
|
|
"\n",
|
|
)
|
|
var lines []string
|
|
for _, line := range rawLines {
|
|
line = strings.TrimSpace(line)
|
|
if len(line) == 0 {
|
|
continue
|
|
}
|
|
lines = append(lines, line)
|
|
}
|
|
plaintext := strings.Join(lines, "\n\n")
|
|
|
|
// Prepare the e-mail!
|
|
m := gomail.NewMessage()
|
|
m.SetHeader("From", fmt.Sprintf("%s <%s>", config.Title, conf.From))
|
|
m.SetHeader("To", msg.To)
|
|
if msg.ReplyTo != "" {
|
|
m.SetHeader("Reply-To", msg.ReplyTo)
|
|
}
|
|
m.SetHeader("Subject", msg.Subject)
|
|
m.SetBody("text/plain", plaintext)
|
|
m.AddAlternative("text/html", html.String())
|
|
|
|
// Deliver.
|
|
d := gomail.NewDialer(conf.Host, conf.Port, conf.Username, conf.Password)
|
|
|
|
log.Info("mail.Send: %s (%s) to %s", msg.Subject, msg.Template, msg.To)
|
|
if err := d.DialAndSend(m); err != nil {
|
|
log.Error("mail.Send: %s", err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|