Email Settings
Configure email notifications, sender identity, and email templates for your store.
Email Configuration
- Go to Admin → Settings → Email
- Configure:
| Field | Description |
|---|---|
| Enable Email Auth | Allow customers to log in via OTP codes |
| Sender Name | Display name for outgoing emails |
| Sender Email | Verified "From" address (e.g., [email protected]) |
| OTP Template | Custom Thymeleaf HTML for verification emails |
| OTP Expiry | Validity period in hours (1-168) |
| Sending Domain | Custom domain for email delivery |
All settings are stored per store in the database.
Email Providers
Configure your email delivery provider per store. Go to Admin → Settings → Email and add the following custom fields:
Resend (Default)
| Field | Description |
|---|---|
| resendApiKey | Your Resend API key (re_...) |
| senderEmail | The verified sender address |
SendGrid
| Field | Description |
|---|---|
| sendgridApiKey | Your SendGrid API key (SG...) |
| senderEmail | The verified sender address |
AWS SES
| Field | Description |
|---|---|
| awsAccessKey | AWS IAM access key |
| awsSecretKey | AWS IAM secret key |
| senderEmail | Verified SES sender address |
Provider credentials are stored in the database as part of your store settings, not as server environment variables.
Notification Templates
Go to Admin → Settings → Notifications to configure templates for different events:
| Event | Channels | Description |
|---|---|---|
| Order Confirmed | Email, SMS | Sent when an order is confirmed |
| Order Shipped | Email, SMS | Sent with tracking information |
| Order Delivered | Delivery confirmation | |
| Payment Received | Payment success notification | |
| Password Reset | Password reset link |
Each template supports variable placeholders (e.g., {{orderNumber}}, {{customerName}}).
Sample Email Templates
OTP Login / Verification
This template is used when customers sign in via email OTP. The following variables are available:
| Variable | Description |
|---|---|
{{otp}} |
The one-time code (6+ digits) |
{{storeName}} |
Your store's display name |
{{baseUrl}} |
Your store's base URL |
{{expiryMinutes}} |
OTP validity period in minutes |
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 480px; margin: 0 auto; padding: 24px; }
.header { text-align: center; padding: 24px 0; }
.otp-code { font-size: 32px; font-weight: 700; letter-spacing: 8px; background: #f0f0f0; padding: 16px 24px; border-radius: 8px; text-align: center; margin: 20px 0; color: #1a1a1a; }
.footer { color: #999; font-size: 13px; margin-top: 24px; border-top: 1px solid #eee; padding-top: 16px; }
</style>
</head>
<body>
<div class="header">
<h1 th:text="|Welcome to ${storeName}|">Welcome</h1>
</div>
<p>Your verification code is:</p>
<div class="otp-code" th:text="${otp}">123456</div>
<p>Enter this code to sign in. It expires in <strong th:text="${expiryMinutes}">10</strong> minutes.</p>
<p th:if="${baseUrl != null}">
Or click here:
<a th:href="|${baseUrl}/verify?code=${otp}|">Verify Now</a>
</p>
<div class="footer">
<p>If you didn't request this code, you can safely ignore this email.</p>
<p th:text="|${storeName}|">Store Name</p>
</div>
</body>
</html>
Welcome Email (Storefront Registration)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 480px; margin: 0 auto; padding: 24px; }
.header { text-align: center; padding: 24px 0; background: #f9fafb; border-radius: 8px; }
.cta { display: inline-block; background: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin: 16px 0; }
</style>
</head>
<body>
<div class="header">
<h1 th:text="|Welcome to ${storeName}!|">Welcome!</h1>
</div>
<p>Hi <strong th:text="${customerName}">there</strong>,</p>
<p>Thanks for creating an account. You can now:</p>
<ul>
<li>Track your orders</li>
<li>Save your addresses</li>
<li>Check out faster</li>
</ul>
<a th:href="${baseUrl}" class="cta">Start Shopping</a>
<p style="color: #999; font-size: 13px;" th:text="|— The ${storeName} team|">— The team</p>
</body>
</html>
Schema-Driven Settings
Notification templates use a schema-driven system. Each event type + channel combination has its own JSON Schema. The admin panel reads the schema to dynamically generate the form.
GET /api/v1/settings/schemas/notifications/order_confirmation
Schemas are public and can be fetched without authentication. This means new notification types can be added without frontend changes.