diff --git a/common/email/api.go b/common/email/api.go new file mode 100644 index 0000000..2789ab2 --- /dev/null +++ b/common/email/api.go @@ -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 +} + diff --git a/common/email/data.go b/common/email/data.go new file mode 100644 index 0000000..750db8a --- /dev/null +++ b/common/email/data.go @@ -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 +} + diff --git a/data/models.go b/data/models.go index 93de3c3..2c59352 100644 --- a/data/models.go +++ b/data/models.go @@ -32,11 +32,4 @@ func Models() map[string]reflect.Type { } } -type EmailMessage struct { - To string - From string - Subject string - Text string - HTML string -} diff --git a/features/email/api.go b/features/email/api.go index 6e56ec5..8bae348 100644 --- a/features/email/api.go +++ b/features/email/api.go @@ -5,11 +5,11 @@ import ( ) func GetApiExample(c *fiber.Ctx) error { - tables := []string{"test", "that"} + tables := []string{"To", "From"} return c.JSON(tables) } func SetupApi(app *fiber.App) { - app.Get("/api/email/example", GetApiExample) + app.Get("/api/email/send", GetApiExample) } diff --git a/static/style.css b/static/style.css index 2e3d29d..64be2dc 100644 --- a/static/style.css +++ b/static/style.css @@ -11,7 +11,6 @@ --color-red-300: oklch(80.8% 0.114 19.571); --color-red-500: oklch(63.7% 0.237 25.331); --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-yellow-300: oklch(90.5% 0.182 98.111); --color-green-400: oklch(79.2% 0.209 151.711); diff --git a/tools/cmd/mailer/main.go b/tools/cmd/mailer/main.go index 248936d..ea44eea 100644 --- a/tools/cmd/mailer/main.go +++ b/tools/cmd/mailer/main.go @@ -1,75 +1,36 @@ package main import ( - "github.com/wneessen/go-mail" - "fmt" "context" - "github.com/redis/go-redis/v9" "time" - "encoding/json" - "MY/webapp/data" + "fmt" + email "MY/webapp/common/email" ) -func SendEmail(msg data.EmailMessage) { - email_msg := mail.NewMsg() - err := email_msg.From(msg.From) - if err != nil { panic(err) } - - 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 +func EmailReceiver(ctx context.Context) { + router, err := email.NewRouter(ctx, email.Config{ + RedisHostPort: "127.0.0.1:6379", + SMTPHost: "localhost", + SMTPPort: 1025, + }) - err := json.Unmarshal([]byte(result), &msg) if err != nil { panic(err) } - - return msg -} - -func EmailListener(ctx context.Context) { - client := redis.NewClient(&redis.Options{ - Addr: "127.0.0.1:6379", - Password: "", - DB: 0, - }) + defer router.Close() for { - result, err := client.BRPop(ctx, 0, "queue").Result() + err := router.HandleEmailRequest() - if err != nil { panic(err) } - - fmt.Printf("received: %v\n", result) - - // NOTE: 0=queue name, 1=message - msg := LoadMessage(result[1]) - - SendEmail(msg) - - fmt.Println("SENT EMAIL") + if err != nil { + fmt.Println(err) + } } } func main() { ctx := context.Background() - go EmailListener(ctx) + go EmailReceiver(ctx) time.Sleep(time.Second * 100) } - diff --git a/tools/cmd/qmgr/main.go b/tools/cmd/qmgr/main.go index 277dda2..ac43c22 100644 --- a/tools/cmd/qmgr/main.go +++ b/tools/cmd/qmgr/main.go @@ -1,39 +1,27 @@ package main import ( - "context" - "github.com/redis/go-redis/v9" - "encoding/json" + email "MY/webapp/common/email" "fmt" - "MY/webapp/data" + "context" ) -func producer(ctx context.Context) { - client := redis.NewClient(&redis.Options{ - Addr: "127.0.0.1:6379", - Password: "", - DB: 0, - }) - - _, err := client.Ping(ctx).Result() - if err != nil { panic(err) } +func main() { + ctx := context.Background() - msg := data.EmailMessage{ + msg := email.EmailMessage{ To: "tina.recip@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), HTML: fmt.Sprintf("

Random number %v

", 200), } - msg_json, err := json.Marshal(msg) - if err != nil { panic(err) } + sender := email.NewSender(ctx, email.Config{ + 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) } } - -func main() { - ctx := context.Background() - producer(ctx) -} diff --git a/views/email/index.html b/views/email/index.html new file mode 100644 index 0000000..bee3867 --- /dev/null +++ b/views/email/index.html @@ -0,0 +1,3 @@ +

email

+ +

Replace me.