diff --git a/email/README.md b/email/README.md
new file mode 100644
index 0000000..3a7b14d
--- /dev/null
+++ b/email/README.md
@@ -0,0 +1,147 @@
+# Elmeg Email Service
+
+Transactional email layer for Elmeg using Amazon SES v2 with stored templates.
+
+## Purpose
+
+This module provides a production-ready email service for user-initiated transactional emails:
+
+- **Email Verification** – Sent after user registration
+- **Password Reset** – Sent when user requests password recovery
+- **Security Alerts** – Sent for account security events (new logins, password changes)
+
+> **Compliance Note:** This service is strictly for transactional, user-initiated emails. No newsletters, marketing emails, or cold outreach. No purchased or third-party email lists are used.
+
+## Requirements
+
+- Node.js >= 18.0.0
+- AWS account with SES verified domain
+- SES templates deployed (see below)
+
+## Environment Variables
+
+```bash
+# Required
+AWS_ACCESS_KEY_ID=AKIA... # IAM user with SES permissions
+AWS_SECRET_ACCESS_KEY=... # IAM user secret key
+AWS_SES_REGION=us-east-1 # SES region (domain must be verified here)
+EMAIL_FROM=noreply@elmeg.xyz # Verified sender address
+
+# Optional
+FRONTEND_URL=https://elmeg.xyz # For generating email links
+SUPPORT_EMAIL=support@elmeg.xyz # Contact email in templates
+```
+
+## Installation
+
+```bash
+cd email
+npm install
+npm run build
+```
+
+## Deploy Templates to SES
+
+Before sending emails, deploy the templates to AWS SES:
+
+```bash
+npm run deploy-templates
+```
+
+This creates/updates three templates in SES:
+
+- `ELMEG_EMAIL_VERIFICATION`
+- `ELMEG_PASSWORD_RESET`
+- `ELMEG_SECURITY_ALERT`
+
+## Usage
+
+```typescript
+import {
+ sendVerificationEmail,
+ sendPasswordResetEmail,
+ sendSecurityAlertEmail,
+ generateVerificationLink,
+ generateResetLink,
+} from "@elmeg/email-service";
+
+// After user registration
+await sendVerificationEmail({
+ to: "user@example.com",
+ userName: "John",
+ verificationLink: generateVerificationLink(token),
+});
+
+// After password reset request
+await sendPasswordResetEmail({
+ to: "user@example.com",
+ userName: "John",
+ resetLink: generateResetLink(token),
+});
+
+// After suspicious login
+await sendSecurityAlertEmail({
+ to: "user@example.com",
+ userName: "John",
+ securityEventDescription: "New sign-in from Chrome on Windows at 10:30 AM",
+});
+```
+
+## Template Placeholders
+
+| Placeholder | Description | Templates |
+|-------------|-------------|-----------|
+| `{{app_name}}` | "Elmeg" | All |
+| `{{user_name}}` | User's name or email prefix | All |
+| `{{support_email}}` | Support contact | All |
+| `{{verification_link}}` | Email verification URL | Verification |
+| `{{reset_link}}` | Password reset URL | Password Reset |
+| `{{security_event_description}}` | Event details | Security Alert |
+
+## AWS SES Setup Checklist
+
+1. **Verify Domain** – Add `elmeg.xyz` in SES console with DKIM records
+2. **Request Production Access** – Move out of sandbox to send to any address
+3. **Create IAM User** – With `ses:SendEmail` and `ses:SendTemplatedEmail` permissions
+4. **Deploy Templates** – Run `npm run deploy-templates`
+
+## Compliance & Best Practices
+
+| Requirement | Implementation |
+|-------------|----------------|
+| User-initiated only | All emails triggered by user actions |
+| No purchased lists | Only registered users receive emails |
+| Bounce handling | SES automatically suppresses bounced addresses |
+| Complaint handling | SES suppresses addresses that report spam |
+| Unsubscribe | N/A for transactional (required action emails) |
+
+## Error Handling
+
+All send functions return a structured result:
+
+```typescript
+interface EmailResult {
+ success: boolean;
+ messageId?: string; // SES message ID on success
+ error?: {
+ code: string; // Error code from SES
+ message: string; // Human-readable error message
+ };
+}
+```
+
+## File Structure
+
+```
+email/
+├── src/
+│ ├── email-service.ts # Main service module
+│ └── examples.ts # Usage examples
+├── scripts/
+│ └── deploy-templates.ts # Template deployment script
+├── templates/
+│ └── README.md # Template documentation
+├── package.json
+├── tsconfig.json
+└── README.md # This file
+```
diff --git a/email/package.json b/email/package.json
new file mode 100644
index 0000000..2e7823b
--- /dev/null
+++ b/email/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "@elmeg/email-service",
+ "version": "1.0.0",
+ "description": "Transactional email service for Elmeg using AWS SES v2",
+ "main": "dist/email-service.js",
+ "types": "dist/email-service.d.ts",
+ "scripts": {
+ "build": "tsc",
+ "test": "jest",
+ "deploy-templates": "ts-node scripts/deploy-templates.ts"
+ },
+ "keywords": [
+ "email",
+ "ses",
+ "aws",
+ "transactional"
+ ],
+ "author": "Elmeg",
+ "license": "MIT",
+ "dependencies": {
+ "@aws-sdk/client-sesv2": "^3.478.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.10.0",
+ "typescript": "^5.3.0",
+ "ts-node": "^10.9.0",
+ "jest": "^29.7.0",
+ "@types/jest": "^29.5.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+}
\ No newline at end of file
diff --git a/email/scripts/deploy-templates.ts b/email/scripts/deploy-templates.ts
new file mode 100644
index 0000000..5b6ae2e
--- /dev/null
+++ b/email/scripts/deploy-templates.ts
@@ -0,0 +1,234 @@
+/**
+ * Deploy SES Templates to AWS
+ *
+ * Run this script to create or update the email templates in AWS SES.
+ * Usage: npx ts-node scripts/deploy-templates.ts
+ */
+
+import { SESv2Client, CreateEmailTemplateCommand, UpdateEmailTemplateCommand } from "@aws-sdk/client-sesv2";
+
+const sesClient = new SESv2Client({
+ region: process.env.AWS_SES_REGION || "us-east-1",
+});
+
+const APP_NAME = "Elmeg";
+const SUPPORT_EMAIL = "support@elmeg.xyz";
+
+// Template definitions
+const templates = [
+ {
+ TemplateName: "ELMEG_EMAIL_VERIFICATION",
+ TemplateContent: {
+ Subject: "Verify your Elmeg account",
+ Html: `
+
+
+
+
+
+
+
+
+
+ {{app_name}}
+ |
+
+
+
+ Verify your email address
+ Hi {{user_name}},
+ Thanks for signing up for {{app_name}}. Please verify your email address by clicking the button below.
+
+ This link will expire after 24 hours for your security.
+ If you did not create an account, you can safely ignore this email.
+
+ If the button above doesn't work, copy and paste this URL: {{verification_link}}
+ |
+
+
+ |
+ {{app_name}} • Contact: {{support_email}}
+ |
+
+
+
+`,
+ Text: `Verify your Elmeg account
+
+Hi {{user_name}},
+
+Thanks for signing up for {{app_name}}. Please verify your email address by clicking the link below:
+
+{{verification_link}}
+
+This link will expire after 24 hours for your security.
+
+If you did not create an account, you can safely ignore this email.
+
+---
+{{app_name}} • Contact: {{support_email}}`,
+ },
+ },
+ {
+ TemplateName: "ELMEG_PASSWORD_RESET",
+ TemplateContent: {
+ Subject: "Reset your Elmeg password",
+ Html: `
+
+
+
+
+
+
+
+
+
+ {{app_name}}
+ |
+
+
+
+ Reset your password
+ Hi {{user_name}},
+ We received a request to reset the password for your {{app_name}} account. Click the button below to choose a new password.
+
+ This link will expire after 1 hour for your security.
+ If you did not request a password reset, you can safely ignore this email.
+
+ If the button above doesn't work, copy and paste this URL: {{reset_link}}
+ |
+
+
+ |
+ {{app_name}} • Contact: {{support_email}}
+ |
+
+
+
+`,
+ Text: `Reset your Elmeg password
+
+Hi {{user_name}},
+
+We received a request to reset the password for your {{app_name}} account.
+
+Click the link below to choose a new password:
+
+{{reset_link}}
+
+This link will expire after 1 hour for your security.
+
+If you did not request a password reset, you can safely ignore this email.
+
+---
+{{app_name}} • Contact: {{support_email}}`,
+ },
+ },
+ {
+ TemplateName: "ELMEG_SECURITY_ALERT",
+ TemplateContent: {
+ Subject: "Security alert for your Elmeg account",
+ Html: `
+
+
+
+
+
+
+
+
+
+ {{app_name}}
+ |
+
+
+
+
+
+ |
+ ⚠️ Security Notice
+ |
+
+
+ Account activity detected
+ Hi {{user_name}},
+ We detected the following activity on your {{app_name}} account:
+
+
+ |
+ {{security_event_description}}
+ |
+
+
+ If this was you, no further action is needed.
+ If you did not perform this action, please secure your account immediately.
+ |
+
+
+ |
+ {{app_name}} • Contact: {{support_email}}
+ |
+
+
+
+`,
+ Text: `Security alert for your Elmeg account
+
+Hi {{user_name}},
+
+We detected the following activity on your {{app_name}} account:
+
+{{security_event_description}}
+
+If this was you, no further action is needed.
+
+If you did not perform this action, please secure your account immediately.
+
+---
+{{app_name}} • Contact: {{support_email}}`,
+ },
+ },
+];
+
+async function deployTemplates() {
+ console.log("🚀 Deploying SES email templates...\n");
+
+ for (const template of templates) {
+ try {
+ // Try to create the template first
+ const createCommand = new CreateEmailTemplateCommand(template);
+ await sesClient.send(createCommand);
+ console.log(`✅ Created template: ${template.TemplateName}`);
+ } catch (error: unknown) {
+ const err = error as { name?: string };
+ if (err.name === "AlreadyExistsException") {
+ // Template exists, update it
+ try {
+ const updateCommand = new UpdateEmailTemplateCommand(template);
+ await sesClient.send(updateCommand);
+ console.log(`🔄 Updated template: ${template.TemplateName}`);
+ } catch (updateError) {
+ console.error(`❌ Failed to update ${template.TemplateName}:`, updateError);
+ }
+ } else {
+ console.error(`❌ Failed to create ${template.TemplateName}:`, error);
+ }
+ }
+ }
+
+ console.log("\n✅ Template deployment complete!");
+}
+
+deployTemplates().catch(console.error);
diff --git a/email/src/email-service.ts b/email/src/email-service.ts
new file mode 100644
index 0000000..51076a1
--- /dev/null
+++ b/email/src/email-service.ts
@@ -0,0 +1,209 @@
+/**
+ * Elmeg Email Service - AWS SES v2 Integration
+ *
+ * Transactional email layer for user-initiated emails only.
+ * Uses AWS SES stored templates for consistent, reliable delivery.
+ */
+
+import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";
+
+// Configuration from environment variables
+const config = {
+ region: process.env.AWS_SES_REGION || "us-east-1",
+ fromAddress: process.env.EMAIL_FROM || "noreply@elmeg.xyz",
+ appName: "Elmeg",
+ supportEmail: process.env.SUPPORT_EMAIL || "support@elmeg.xyz",
+ frontendUrl: process.env.FRONTEND_URL || "https://elmeg.xyz",
+};
+
+// SES Template Names
+export const SES_TEMPLATES = {
+ EMAIL_VERIFICATION: "ELMEG_EMAIL_VERIFICATION",
+ PASSWORD_RESET: "ELMEG_PASSWORD_RESET",
+ SECURITY_ALERT: "ELMEG_SECURITY_ALERT",
+} as const;
+
+// Initialize SES v2 client
+const sesClient = new SESv2Client({
+ region: config.region,
+ // Credentials are loaded automatically from env vars:
+ // AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
+});
+
+// =============================================================================
+// Types
+// =============================================================================
+
+export interface SendVerificationEmailParams {
+ to: string;
+ userName: string;
+ verificationLink: string;
+}
+
+export interface SendPasswordResetEmailParams {
+ to: string;
+ userName: string;
+ resetLink: string;
+}
+
+export interface SendSecurityAlertEmailParams {
+ to: string;
+ userName: string;
+ securityEventDescription: string;
+}
+
+export interface EmailResult {
+ success: boolean;
+ messageId?: string;
+ error?: {
+ code: string;
+ message: string;
+ };
+}
+
+export class EmailError extends Error {
+ code: string;
+
+ constructor(code: string, message: string) {
+ super(message);
+ this.name = "EmailError";
+ this.code = code;
+ }
+}
+
+// =============================================================================
+// Email Sending Functions
+// =============================================================================
+
+/**
+ * Send email verification email to new users
+ */
+export async function sendVerificationEmail(
+ params: SendVerificationEmailParams
+): Promise {
+ const templateData = {
+ user_name: params.userName,
+ verification_link: params.verificationLink,
+ app_name: config.appName,
+ support_email: config.supportEmail,
+ };
+
+ return sendTemplatedEmail(
+ params.to,
+ SES_TEMPLATES.EMAIL_VERIFICATION,
+ templateData
+ );
+}
+
+/**
+ * Send password reset email
+ */
+export async function sendPasswordResetEmail(
+ params: SendPasswordResetEmailParams
+): Promise {
+ const templateData = {
+ user_name: params.userName,
+ reset_link: params.resetLink,
+ app_name: config.appName,
+ support_email: config.supportEmail,
+ };
+
+ return sendTemplatedEmail(
+ params.to,
+ SES_TEMPLATES.PASSWORD_RESET,
+ templateData
+ );
+}
+
+/**
+ * Send security alert email for account events
+ */
+export async function sendSecurityAlertEmail(
+ params: SendSecurityAlertEmailParams
+): Promise {
+ const templateData = {
+ user_name: params.userName,
+ security_event_description: params.securityEventDescription,
+ app_name: config.appName,
+ support_email: config.supportEmail,
+ };
+
+ return sendTemplatedEmail(
+ params.to,
+ SES_TEMPLATES.SECURITY_ALERT,
+ templateData
+ );
+}
+
+// =============================================================================
+// Core Email Function
+// =============================================================================
+
+async function sendTemplatedEmail(
+ to: string,
+ templateName: string,
+ templateData: Record
+): Promise {
+ try {
+ const command = new SendEmailCommand({
+ FromEmailAddress: config.fromAddress,
+ Destination: {
+ ToAddresses: [to],
+ },
+ Content: {
+ Template: {
+ TemplateName: templateName,
+ TemplateData: JSON.stringify(templateData),
+ },
+ },
+ });
+
+ const response = await sesClient.send(command);
+
+ return {
+ success: true,
+ messageId: response.MessageId,
+ };
+ } catch (error: unknown) {
+ const err = error as { name?: string; message?: string; Code?: string };
+
+ console.error(`[Email] Failed to send ${templateName} to ${to}:`, err.message);
+
+ return {
+ success: false,
+ error: {
+ code: err.Code || err.name || "UNKNOWN_ERROR",
+ message: err.message || "Failed to send email",
+ },
+ };
+ }
+}
+
+// =============================================================================
+// Utility Functions
+// =============================================================================
+
+/**
+ * Generate a verification link for a user
+ */
+export function generateVerificationLink(token: string): string {
+ return `${config.frontendUrl}/verify-email?token=${encodeURIComponent(token)}`;
+}
+
+/**
+ * Generate a password reset link for a user
+ */
+export function generateResetLink(token: string): string {
+ return `${config.frontendUrl}/reset-password?token=${encodeURIComponent(token)}`;
+}
+
+/**
+ * Check if the email service is properly configured
+ */
+export function isEmailConfigured(): boolean {
+ return !!(
+ process.env.AWS_ACCESS_KEY_ID &&
+ process.env.AWS_SECRET_ACCESS_KEY &&
+ process.env.AWS_SES_REGION
+ );
+}
diff --git a/email/src/examples.ts b/email/src/examples.ts
new file mode 100644
index 0000000..38c6682
--- /dev/null
+++ b/email/src/examples.ts
@@ -0,0 +1,176 @@
+/**
+ * Elmeg Email Service - Usage Examples
+ *
+ * These examples show how to integrate the email service
+ * into your application's user flows.
+ */
+
+import {
+ sendVerificationEmail,
+ sendPasswordResetEmail,
+ sendSecurityAlertEmail,
+ generateVerificationLink,
+ generateResetLink,
+ isEmailConfigured,
+} from "./email-service";
+
+// =============================================================================
+// Example 1: User Registration Flow
+// =============================================================================
+
+async function handleUserRegistration(
+ userEmail: string,
+ userName: string,
+ verificationToken: string
+) {
+ // Check if email is configured
+ if (!isEmailConfigured()) {
+ console.warn("[Email] Email service not configured, skipping verification email");
+ return;
+ }
+
+ // Generate the verification link
+ const verificationLink = generateVerificationLink(verificationToken);
+
+ // Send the verification email
+ const result = await sendVerificationEmail({
+ to: userEmail,
+ userName: userName || userEmail.split("@")[0],
+ verificationLink,
+ });
+
+ if (result.success) {
+ console.log(`[Email] Verification email sent to ${userEmail}, messageId: ${result.messageId}`);
+ } else {
+ console.error(`[Email] Failed to send verification email: ${result.error?.message}`);
+ // Handle error - maybe retry or alert admin
+ }
+}
+
+// =============================================================================
+// Example 2: Forgot Password Flow
+// =============================================================================
+
+async function handleForgotPassword(
+ userEmail: string,
+ userName: string,
+ resetToken: string
+) {
+ if (!isEmailConfigured()) {
+ console.warn("[Email] Email service not configured, skipping password reset email");
+ return;
+ }
+
+ const resetLink = generateResetLink(resetToken);
+
+ const result = await sendPasswordResetEmail({
+ to: userEmail,
+ userName: userName || userEmail.split("@")[0],
+ resetLink,
+ });
+
+ if (result.success) {
+ console.log(`[Email] Password reset email sent to ${userEmail}`);
+ } else {
+ console.error(`[Email] Failed to send password reset email: ${result.error?.message}`);
+ }
+}
+
+// =============================================================================
+// Example 3: Security Alert - New Login
+// =============================================================================
+
+async function handleNewLogin(
+ userEmail: string,
+ userName: string,
+ loginDetails: { ip: string; browser: string; location?: string; timestamp: Date }
+) {
+ if (!isEmailConfigured()) {
+ return;
+ }
+
+ const eventDescription = [
+ `New sign-in to your account`,
+ ``,
+ `Time: ${loginDetails.timestamp.toLocaleString()}`,
+ `IP Address: ${loginDetails.ip}`,
+ `Browser: ${loginDetails.browser}`,
+ loginDetails.location ? `Location: ${loginDetails.location}` : null,
+ ]
+ .filter(Boolean)
+ .join("\n");
+
+ const result = await sendSecurityAlertEmail({
+ to: userEmail,
+ userName: userName || userEmail.split("@")[0],
+ securityEventDescription: eventDescription,
+ });
+
+ if (!result.success) {
+ console.error(`[Email] Failed to send security alert: ${result.error?.message}`);
+ }
+}
+
+// =============================================================================
+// Example 4: Security Alert - Password Changed
+// =============================================================================
+
+async function handlePasswordChanged(
+ userEmail: string,
+ userName: string,
+ timestamp: Date
+) {
+ if (!isEmailConfigured()) {
+ return;
+ }
+
+ const eventDescription = `Your password was changed on ${timestamp.toLocaleString()}. If you did not make this change, please contact support immediately.`;
+
+ await sendSecurityAlertEmail({
+ to: userEmail,
+ userName: userName || userEmail.split("@")[0],
+ securityEventDescription: eventDescription,
+ });
+}
+
+// =============================================================================
+// Example 5: Express.js Route Handler Integration
+// =============================================================================
+
+/*
+import express from "express";
+import { sendVerificationEmail, generateVerificationLink } from "./email-service";
+
+const router = express.Router();
+
+router.post("/register", async (req, res) => {
+ const { email, password, name } = req.body;
+
+ // ... create user in database ...
+ const user = await createUser({ email, password, name });
+
+ // Generate verification token
+ const verificationToken = generateSecureToken();
+ await saveVerificationToken(user.id, verificationToken);
+
+ // Send verification email
+ const verificationLink = generateVerificationLink(verificationToken);
+
+ const emailResult = await sendVerificationEmail({
+ to: email,
+ userName: name || email.split("@")[0],
+ verificationLink,
+ });
+
+ if (!emailResult.success) {
+ console.error("Failed to send verification email:", emailResult.error);
+ // Don't fail registration, just log the error
+ }
+
+ res.status(201).json({
+ message: "Account created. Please check your email to verify your account."
+ });
+});
+
+export default router;
+*/
diff --git a/email/templates/README.md b/email/templates/README.md
new file mode 100644
index 0000000..108f7bc
--- /dev/null
+++ b/email/templates/README.md
@@ -0,0 +1,306 @@
+# AWS SES Email Templates for Elmeg
+
+## Template 1: Email Verification
+
+**Template Name:** `ELMEG_EMAIL_VERIFICATION`
+
+### Subject
+
+```
+Verify your Elmeg account
+```
+
+### HTML Body
+
+```html
+
+
+
+
+
+ Verify your email
+
+
+
+
+
+ {{app_name}}
+ |
+
+
+
+ Verify your email address
+
+ Hi {{user_name}},
+
+
+ Thanks for signing up for {{app_name}}. Please verify your email address by clicking the button below.
+
+
+
+ This link will expire after 24 hours for your security.
+
+
+ If you did not create an account, you can safely ignore this email.
+
+
+
+ If the button above doesn't work, copy and paste this URL into your browser:
+
+
+ {{verification_link}}
+
+ |
+
+
+ |
+
+ {{app_name}} – The Goose Community Archive
+
+
+ Questions? Contact us at {{support_email}}
+
+ |
+
+
+
+
+```
+
+### Plain Text Body
+
+```
+Verify your Elmeg account
+
+Hi {{user_name}},
+
+Thanks for signing up for {{app_name}}. Please verify your email address by clicking the link below:
+
+{{verification_link}}
+
+This link will expire after 24 hours for your security.
+
+If you did not create an account, you can safely ignore this email.
+
+---
+{{app_name}} – The Goose Community Archive
+Questions? Contact us at {{support_email}}
+```
+
+---
+
+## Template 2: Password Reset
+
+**Template Name:** `ELMEG_PASSWORD_RESET`
+
+### Subject
+
+```
+Reset your Elmeg password
+```
+
+### HTML Body
+
+```html
+
+
+
+
+
+ Reset your password
+
+
+
+
+
+ {{app_name}}
+ |
+
+
+
+ Reset your password
+
+ Hi {{user_name}},
+
+
+ We received a request to reset the password for your {{app_name}} account. Click the button below to choose a new password.
+
+
+
+ This link will expire after 1 hour for your security.
+
+
+ If you did not request a password reset, you can safely ignore this email. Your password will remain unchanged.
+
+
+
+ If the button above doesn't work, copy and paste this URL into your browser:
+
+
+ {{reset_link}}
+
+ |
+
+
+ |
+
+ {{app_name}} – The Goose Community Archive
+
+
+ Questions? Contact us at {{support_email}}
+
+ |
+
+
+
+
+```
+
+### Plain Text Body
+
+```
+Reset your Elmeg password
+
+Hi {{user_name}},
+
+We received a request to reset the password for your {{app_name}} account.
+
+Click the link below to choose a new password:
+
+{{reset_link}}
+
+This link will expire after 1 hour for your security.
+
+If you did not request a password reset, you can safely ignore this email. Your password will remain unchanged.
+
+---
+{{app_name}} – The Goose Community Archive
+Questions? Contact us at {{support_email}}
+```
+
+---
+
+## Template 3: Security Alert
+
+**Template Name:** `ELMEG_SECURITY_ALERT`
+
+### Subject
+
+```
+Security alert for your Elmeg account
+```
+
+### HTML Body
+
+```html
+
+
+
+
+
+ Security Alert
+
+
+
+
+
+ {{app_name}}
+ |
+
+
+
+
+
+ |
+ ⚠️ Security Notice
+ |
+
+
+ Account activity detected
+
+ Hi {{user_name}},
+
+
+ We detected the following activity on your {{app_name}} account:
+
+
+
+ |
+
+ {{security_event_description}}
+
+ |
+
+
+
+ If this was you, no further action is needed.
+
+
+ If you did not perform this action, we recommend you secure your account immediately by changing your password.
+
+
+
+ This is an automated security notification. If you have concerns about your account security, please contact us at {{support_email}}.
+
+ |
+
+
+ |
+
+ {{app_name}} – The Goose Community Archive
+
+
+ Questions? Contact us at {{support_email}}
+
+ |
+
+
+
+
+```
+
+### Plain Text Body
+
+```
+Security alert for your Elmeg account
+
+Hi {{user_name}},
+
+We detected the following activity on your {{app_name}} account:
+
+{{security_event_description}}
+
+If this was you, no further action is needed.
+
+If you did not perform this action, we recommend you secure your account immediately by changing your password.
+
+---
+This is an automated security notification. If you have concerns about your account security, please contact us at {{support_email}}.
+
+{{app_name}} – The Goose Community Archive
+```
+
+---
+
+## Template Placeholders Reference
+
+| Placeholder | Description | Used In |
+|-------------|-------------|---------|
+| `{{app_name}}` | Application name ("Elmeg") | All templates |
+| `{{user_name}}` | User's display name or email | All templates |
+| `{{support_email}}` | Support contact email | All templates |
+| `{{verification_link}}` | Email verification URL | Email Verification |
+| `{{reset_link}}` | Password reset URL | Password Reset |
+| `{{security_event_description}}` | Description of the security event | Security Alert |
diff --git a/email/tsconfig.json b/email/tsconfig.json
new file mode 100644
index 0000000..3fb3621
--- /dev/null
+++ b/email/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "commonjs",
+ "lib": [
+ "ES2022"
+ ],
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "resolveJsonModule": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file