Email sending/queue api now works nicer.

master
Zed A. Shaw 4 weeks ago
parent 94e0970fd3
commit 5c07583ba4
  1. 100
      common/email/api.go
  2. 35
      common/email/data.go
  3. 7
      data/models.go
  4. 4
      features/email/api.go
  5. 1
      static/style.css
  6. 67
      tools/cmd/mailer/main.go
  7. 34
      tools/cmd/qmgr/main.go
  8. 3
      views/email/index.html

@ -0,0 +1,100 @@
package common_email
import (
"github.com/wneessen/go-mail"
"encoding/json"
"context"
"github.com/redis/go-redis/v9"
)
func NewSender(ctx context.Context, config Config) (Sender){
client := redis.NewClient(&redis.Options{
Addr: config.RedisHostPort,
Password: config.RedisPassword,
DB: config.RedisDB,
})
return Sender{client, ctx}
}
func NewRouter(ctx context.Context, config Config) (Router, error) {
var router Router
var err error
router.ctx = ctx
router.redis_client = redis.NewClient(&redis.Options{
Addr: config.RedisHostPort,
Password: config.RedisPassword,
DB: config.RedisDB,
})
router.smtp_client, err = mail.NewClient(config.SMTPHost,
mail.WithPort(config.SMTPPort),
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) 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)
email_msg.SetBodyString(mail.TypeTextPlain, msg.Text)
email_msg.SetBodyString(mail.TypeTextHTML, msg.HTML)
if err != nil { return err }
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, "queue").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, "queue", string(msg_json)).Result()
if err != nil { return err }
return nil
}

@ -0,0 +1,35 @@
package common_email
import (
"github.com/redis/go-redis/v9"
"github.com/wneessen/go-mail"
"context"
)
type Config struct {
RedisHostPort string
RedisPassword string
RedisDB int
SMTPHost string
SMTPPort int
}
type EmailMessage struct {
To string
From string
Subject string
Text string
HTML string
}
type Sender struct {
redis_client *redis.Client
ctx context.Context
}
type Router struct {
redis_client *redis.Client
smtp_client *mail.Client
ctx context.Context
}

@ -32,11 +32,4 @@ func Models() map[string]reflect.Type {
} }
} }
type EmailMessage struct {
To string
From string
Subject string
Text string
HTML string
}

@ -5,11 +5,11 @@ import (
) )
func GetApiExample(c *fiber.Ctx) error { func GetApiExample(c *fiber.Ctx) error {
tables := []string{"test", "that"} tables := []string{"To", "From"}
return c.JSON(tables) return c.JSON(tables)
} }
func SetupApi(app *fiber.App) { func SetupApi(app *fiber.App) {
app.Get("/api/email/example", GetApiExample) app.Get("/api/email/send", GetApiExample)
} }

@ -11,7 +11,6 @@
--color-red-300: oklch(80.8% 0.114 19.571); --color-red-300: oklch(80.8% 0.114 19.571);
--color-red-500: oklch(63.7% 0.237 25.331); --color-red-500: oklch(63.7% 0.237 25.331);
--color-red-800: oklch(44.4% 0.177 26.899); --color-red-800: oklch(44.4% 0.177 26.899);
--color-red-900: oklch(39.6% 0.141 25.723);
--color-orange-500: oklch(70.5% 0.213 47.604); --color-orange-500: oklch(70.5% 0.213 47.604);
--color-yellow-300: oklch(90.5% 0.182 98.111); --color-yellow-300: oklch(90.5% 0.182 98.111);
--color-green-400: oklch(79.2% 0.209 151.711); --color-green-400: oklch(79.2% 0.209 151.711);

@ -1,75 +1,36 @@
package main package main
import ( import (
"github.com/wneessen/go-mail"
"fmt"
"context" "context"
"github.com/redis/go-redis/v9"
"time" "time"
"encoding/json" "fmt"
"MY/webapp/data" email "MY/webapp/common/email"
) )
func SendEmail(msg data.EmailMessage) { func EmailReceiver(ctx context.Context) {
email_msg := mail.NewMsg() router, err := email.NewRouter(ctx, email.Config{
err := email_msg.From(msg.From) RedisHostPort: "127.0.0.1:6379",
if err != nil { panic(err) } SMTPHost: "localhost",
SMTPPort: 1025,
err = email_msg.To(msg.To) })
if err != nil { panic(err) }
email_msg.Subject(msg.Subject)
email_msg.SetBodyString(mail.TypeTextPlain, msg.Text)
email_msg.SetBodyString(mail.TypeTextHTML, msg.HTML)
client, err := mail.NewClient("localhost",
mail.WithPort(1025),
mail.WithTLSPolicy(mail.NoTLS))
if err != nil { panic(err) }
err = client.DialAndSend(email_msg)
if err != nil { panic(err) }
}
func LoadMessage(result string) data.EmailMessage {
var msg data.EmailMessage
err := json.Unmarshal([]byte(result), &msg)
if err != nil { panic(err) } if err != nil { panic(err) }
defer router.Close()
return msg
}
func EmailListener(ctx context.Context) {
client := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Password: "",
DB: 0,
})
for { for {
result, err := client.BRPop(ctx, 0, "queue").Result() err := router.HandleEmailRequest()
if err != nil { panic(err) } if err != nil {
fmt.Println(err)
fmt.Printf("received: %v\n", result) }
// NOTE: 0=queue name, 1=message
msg := LoadMessage(result[1])
SendEmail(msg)
fmt.Println("SENT EMAIL")
} }
} }
func main() { func main() {
ctx := context.Background() ctx := context.Background()
go EmailListener(ctx) go EmailReceiver(ctx)
time.Sleep(time.Second * 100) time.Sleep(time.Second * 100)
} }

@ -1,39 +1,27 @@
package main package main
import ( import (
"context" email "MY/webapp/common/email"
"github.com/redis/go-redis/v9"
"encoding/json"
"fmt" "fmt"
"MY/webapp/data" "context"
) )
func producer(ctx context.Context) { func main() {
client := redis.NewClient(&redis.Options{ ctx := context.Background()
Addr: "127.0.0.1:6379",
Password: "",
DB: 0,
})
_, err := client.Ping(ctx).Result()
if err != nil { panic(err) }
msg := data.EmailMessage{ msg := email.EmailMessage{
To: "tina.recip@example.com", To: "tina.recip@example.com",
From: "toni.sender@example.com", From: "toni.sender@example.com",
Subject: "This is my first mail.", Subject: "This is my first mail.",
Text: fmt.Sprintf("Random number %v", 200), Text: fmt.Sprintf("Random number %v", 200),
HTML: fmt.Sprintf("<h1>Random number %v</h1>", 200), HTML: fmt.Sprintf("<h1>Random number %v</h1>", 200),
} }
msg_json, err := json.Marshal(msg) sender := email.NewSender(ctx, email.Config{
if err != nil { panic(err) } RedisHostPort: "127.0.0.1:6379",
})
defer sender.Close()
_, err = client.LPush(ctx, "queue", string(msg_json)).Result() err := sender.QueueEmail(msg)
if err != nil { panic(err) } if err != nil { panic(err) }
} }
func main() {
ctx := context.Background()
producer(ctx)
}

@ -0,0 +1,3 @@
<h1>email</h1>
<p>Replace me.</p>
Loading…
Cancel
Save