Caesar Mail
Learn how to abstract email services using the Caesar Mail package.
Overview
The Caesar Mail package provides an abstraction over email services such as Resend, AWS SES, and SMTP. This guide will walk you through setting up and using Caesar Mail in your application.
Setting Up Caesar Mail
Step 1: Install the Dependency
First, download the Caesar Mail package dependency:
go get -u github.com/caesar-rocks/mail
Step 2: Validate Environment Variables
Configure the necessary environment variables in the ./config/env.go
file. Here's how to do it for Resend:
package config
import (
"github.com/caesar-rocks/core"
)
// EnvironmentVariables is a struct that holds all the environment variables that need to be validated.
type EnvironmentVariables struct {
RESEND_KEY string `validate:"required"`
// Other environment variables...
}
func ProvideEnvironmentVariables() *EnvironmentVariables {
return core.ValidateEnvironmentVariables[EnvironmentVariables]()
}
Step 3: Add Mailer Configuration
Next, create a ./config/mailer.go
file to configure the Mailer service:
package config
import mailer "github.com/caesar-rocks/mail"
func ProvideMailer(env *EnvironmentVariables) *mailer.Mailer {
return mailer.NewMailer(mailer.MailCfg{
APIService: mailer.RESEND,
APIKey: env.RESEND_KEY,
})
}
Step 4: Register Mailer as a Provider
Finally, register the Mailer service as a provider in your ./config/app.go
file:
package config
import (
"myapp/app/repositories"
"github.com/caesar-rocks/core"
)
func ProvideApp() *core.App {
app := core.NewApp(&core.AppConfig{
Addr: ":8080",
})
env := ProvideEnvironmentVariables()
mailer := ProvideMailer(env)
// Register providers
app.RegisterProviders(
ProvideEnvironmentVariables,
ProvideMailer,
// Other providers...
)
// Other invokers...
return app
}
Creating Mail Templates
You can create mail templates using Go Templ. Here’s an example of a forgot password email template:
package mails
templ ForgotPasswordMail(name string, url string) {
<p>
Hi { name },
<br/>
<br/>
You have requested to reset your password. Please <a href={ templ.SafeURL(url) }>click here</a> to reset your password.
<br/>
<br/>
If you did not request to reset your password, please ignore this email.
<br/>
<br/>
Thanks,
<br/>
The Software Citadel Team.
</p>
}
Save this template in the ./views/mails/forgot_password.templ
file.
Using Caesar Mail in Controllers
To demonstrate how to send an email using Caesar Mail, let’s consider a scenario where a user wants to reset their password.
Forgot Password Controller
Define a controller to handle the forgot password functionality:
package authControllers
import (
"bytes"
"citadel/app/repositories"
"citadel/views/mails"
authPages "citadel/views/pages/auth"
"log/slog"
caesar "github.com/caesar-rocks/core"
mailer "github.com/caesar-rocks/mail"
)
type ForgotPwdController struct {
mailer *mailer.Mailer
repo *repositories.UsersRepository
}
func NewForgotPwdController(mailer *mailer.Mailer, repo *repositories.UsersRepository) *ForgotPwdController {
return &ForgotPwdController{mailer, repo}
}
func (c *ForgotPwdController) Show(ctx *caesar.CaesarCtx) error {
return ctx.Render(authPages.ForgotPasswordPage())
}
type ForgotPwdValidator struct {
Email string `form:"email" validate:"required,email"`
}
func (c *ForgotPwdController) Handle(ctx *caesar.CaesarCtx) error {
data, _, ok := caesar.Validate[ForgotPwdValidator](ctx)
if !ok {
return ctx.Render(authPages.ForgotPasswordSuccessAlert())
}
user, _ := c.repo.FindOneBy(ctx.Context(), "email", data.Email)
if user == nil {
return ctx.Render(authPages.ForgotPasswordSuccessAlert())
}
var buf bytes.Buffer
res := mails.ForgotPasswordMail(data.Email, "http://localhost:3000/reset-password")
if err := res.Render(ctx.Context(), &buf); err != nil {
slog.Error("Failed to render email", "err", err)
return ctx.Render(authPages.ForgotPasswordSuccessAlert())
}
if err := c.mailer.Send(mailer.Mail{
From: "Software Citadel <contact@softwarecitadel.com>",
To: data.Email,
Subject: "Reset your password",
Html: buf.String(),
}); err != nil {
slog.Error("Failed to send email", "err", err)
}
return ctx.Render(authPages.ForgotPasswordPage())
}
Registering Routes
Register the controller methods in your application's route configuration:
package config
import (
"myapp/app/controllers"
caesar "github.com/caesar-rocks/core"
mailer "github.com/caesar-rocks/mail"
)
func RegisterRoutes(mailer *mailer.Mailer, usersRepo *repositories.UsersRepository) *caesar.Router {
forgotPwdController := controllers.NewForgotPwdController(mailer, usersRepo)
router := caesar.NewRouter()
router.Get("/forgot-password", forgotPwdController.Show)
router.Post("/forgot-password", forgotPwdController.Handle)
return router
}
In the ProvideApp()
function from ./config/app.go
, ensure that RegisterRoutes
is called with the correct parameters:
func ProvideApp() *core.App {
app := core.NewApp(&core.AppConfig{
Addr: ":8080",
})
env := ProvideEnvironmentVariables()
mailer := ProvideMailer(env)
// Register routes
router := RegisterRoutes(mailer, usersRepo)
app.SetRouter(router)
// Register other providers and invokers...
return app
}
Summary
The Caesar Mail package provides a simplified and unified interface to send emails using different services like Resend, AWS SES, and SMTP. By following this guide, you can set up and use Caesar Mail in your application to handle email functionalities efficiently.