Email

This guide explains how to create HTML email templates using UIx components and send emails from your application.

Email Component System

The saas.common.ui.email namespace provides a set of UIx components specifically designed for creating consistent HTML emails. These components are inspired by React Email but implemented with ClojureScript and UIx.

Available Components

The email component library includes:

  • html - Root wrapper for email content

  • head - Contains head elements like styles and meta tags

  • body - Wrapper for all email content

  • container - Centers content with proper width constraints

  • heading - A block of heading text (h1-h6)

  • text - Paragraph text with consistent styling

  • button - A link styled as a button

  • link - Styled hyperlink

  • img - Image component optimized for email clients

  • row - Horizontal layout container

  • column - Column within a row

  • section - Content section

  • preview - Sets inbox preview text

  • hr - Horizontal rule divider

  • code-inline - Displays code snippets with cross-client support

Creating Email Templates

To create an email template:

  1. Import the necessary components:

(ns your.namespace
  (:require
   [saas.common.ui.email :as email]
   [uix.core :refer [$]]))
  1. Define your email template using UIx components:

(defn welcome-email [{:keys [user-name verification-url]}]
  ($ email/html
     ($ email/head)
     ($ email/preview "Welcome to Ship Clojure! Verify your account")
     ($ email/body
        ($ email/container
           ($ email/heading "Welcome to Ship Clojure!")
           ($ email/text (str "Hello " user-name ", thank you for signing up!"))
           ($ email/text "Please verify your account by clicking the button below:")
           ($ email/button {:href verification-url
                           :style {:background-color "#5881D8"
                                   :color "#ffffff"
                                   :padding "11px 23px"}}
              "Verify Account")))))
  1. Convert the UIx components to HTML:

(def html-email (email/render-email 
                  ($ welcome-email 
                     {:user-name "Jane Doe"
                      :verification-url "https://your-app.com/verify?token=abc123"})))

Styling Components

Components accept style maps similar to React's style prop:

($ email/text {:style {:color "#333333" 
                      :font-size "16px"
                      :line-height "1.5"}}
   "This is styled text")

For margin utilities, use :m, :mt, :mr, :mb, :ml, :mx, or :my:

($ email/heading {:m 10 :mb 20} "Heading with margins")

Sending Emails

Use the saas.email namespace to send emails:

(require '[saas.email :as email]
         '[saas.common.ui.email :as email-ui])

;; Generate the HTML for your email
(def html-email (email-ui/render-email
                  ($ email-ui/verification-email 
                     {:verification-url "https://your-app.com/verify?token=abc123"
                      :otp "123456"
                      :type "onboarding"})))

;; Send the email using the EmailSender protocol
(email/send-email email-sender
                 {:html html-email
                  :subject "Verify your account"
                  :to "user@example.com"
                  :from "Your App <noreply@your-app.com>"})

The email-sender is typically injected via the system's dependency injection:

;; In a handler that receives the email-sender as dependency
(defn send-verification-email [{:keys [email-sender]} user verification-code]
  (let [html (email-ui/render-email
               ($ email-ui/verification-email 
                  {:verification-url (str "https://your-app.com/verify/" verification-code)
                   :otp verification-code
                   :type "onboarding"}))]
    
    (email/send-email email-sender
                     {:html html
                      :subject "Verify your account"
                      :to (:email user)
                      :from "Your App <noreply@your-app.com>"})))

Email Configuration

The system uses Resend as the email service provider. Configuration is handled via the :services/email Integrant component:

;; In your system.edn
{:services/email 
 {:secrets #ig/ref :services/secrets
  :api-url "https://api.resend.com/emails"}}

For local development, a mock email sender is used that logs email contents instead of sending actual emails.

Extracting Plain Text

For better deliverability, include both HTML and plain text versions of your email:

(def html-email (email-ui/render-email your-email-component))
(def text-email (email/extract-text html-email))

(email/send-email email-sender
                 {:html html-email
                  :text text-email
                  :subject "Your Subject"
                  :to "user@example.com"
                  :from "Your App <noreply@your-app.com>"})

Example Email Templates

The library includes pre-built templates:

  1. login-code-email - For sending login verification codes with magic links

  2. verification-email - For account verification (onboarding, password reset)

Example usage:

(email-ui/render-email 
  ($ email-ui/login-code-email 
     {:code "123456"
      :code-href "https://your-app.com/verify/123456"
      :homepage "https://your-app.com"}))

Last updated