A small project that collects various nice things to get started with Go Web Development.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
3.7 KiB

package common_email
import (
"github.com/wneessen/go-mail"
"encoding/json"
"context"
"log"
"github.com/redis/go-redis/v9"
"github.com/yuin/goldmark"
"MY/webapp/config"
"path/filepath"
"text/template"
"os"
"strings"
)
func NewSender(ctx context.Context) (Sender){
client := redis.NewClient(&redis.Options{
Addr: config.Settings.Redis.HostPort,
Password: config.Settings.Redis.Password,
DB: config.Settings.Redis.DB,
})
return Sender{client, ctx}
}
func NewRouter(ctx context.Context) (Router, error) {
var router Router
var err error
router.ctx = ctx
router.redis_client = redis.NewClient(&redis.Options{
Addr: config.Settings.Redis.HostPort,
Password: config.Settings.Redis.Password,
DB: config.Settings.Redis.DB,
})
router.smtp_client, err = mail.NewClient(config.Settings.Email.Host,
mail.WithPort(config.Settings.Email.Port),
mail.WithTLSPolicy(mail.NoTLS))
return router, err
}
func (router *Router) Close() {
router.redis_client.Close()
router.smtp_client.Close()
}
func (sender *Sender) Close() {
sender.redis_client.Close()
}
func (router *Router) Render(tmpl_path string, data any) (string, string, error) {
tmpl_path = filepath.Join(config.Settings.Email.Templates, tmpl_path)
// load the markdown file
md_file, err := os.ReadFile(tmpl_path)
if err != nil { return "", "", err }
// template it
tmpl, err := template.New(tmpl_path).Parse(string(md_file))
if err != nil { return "", "", err }
out := new(strings.Builder)
err = tmpl.Execute(out, data)
if err != nil { return "", "", err }
text_out := out.String()
// convert to html
out.Reset()
err = goldmark.Convert([]byte(text_out), out)
if err != nil { return "", "", err }
html_out := out.String()
// return the template .md as plain text and .html as html
return string(text_out), string(html_out), nil
}
func (router *Router) DeliverEmail(msg EmailMessage) error {
email_msg := mail.NewMsg()
err := email_msg.From(msg.From)
if err != nil { return err }
err = email_msg.To(msg.To)
if err != nil { return err }
email_msg.Subject(msg.Subject)
if config.Settings.Email.XMailer != "" {
email_msg.SetGenHeader(mail.HeaderXMailer, config.Settings.Email.XMailer)
}
if config.Settings.Email.UserAgent != "" {
email_msg.SetGenHeader(mail.HeaderUserAgent, config.Settings.Email.UserAgent)
}
text, html, err := router.Render(msg.Template, nil)
if err != nil { return err }
email_msg.SetBodyString(mail.TypeTextHTML, html)
email_msg.AddAlternativeString(mail.TypeTextPlain, text)
err = router.smtp_client.DialAndSendWithContext(router.ctx, email_msg)
if err != nil { return err }
return nil
}
func (router *Router) ReceiveEmail() (EmailMessage, error) {
var msg EmailMessage
result, err := router.redis_client.BRPop(
router.ctx, 0,
config.Settings.Email.RedisQueue).Result()
if err != nil { return msg, err }
// NOTE: 0=queue name, 1=message
err = json.Unmarshal([]byte(result[1]), &msg)
if err != nil { return msg, err }
return msg, nil
}
func (router *Router) HandleEmailRequest() error {
msg, err := router.ReceiveEmail()
if err != nil { return err }
err = router.DeliverEmail(msg)
if err != nil { return err }
return nil
}
func (sender *Sender) QueueEmail(msg EmailMessage) error {
msg_json, err := json.Marshal(msg)
if err != nil { return err }
_, err = sender.redis_client.LPush(
sender.ctx,
config.Settings.Email.RedisQueue,
string(msg_json)).Result()
if err != nil { return err }
return nil
}
func OneShotSend(msg EmailMessage) {
ctx := context.Background()
sender := NewSender(ctx)
defer sender.Close()
err := sender.QueueEmail(msg)
if err != nil {
log.Print(err)
}
}