This document provides an overview of all email templates used in the PropChain system, including sample payloads, variable references, and preview examples.
Template File: src/email/templates/password-reset.ejs
Purpose: Sent when a user requests a password reset.
Variables:
resetUrl- The password reset link containing the reset token
Sample Payload:
{
"resetUrl": "http://localhost:3000/reset-password?token=abc123xyz789"
}Rendered Preview:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #333;">Password Reset Request</h2>
<p>You have requested to reset your password for your PropChain account.</p>
<p>Please click the link below to reset your password:</p>
<a href="http://localhost:3000/reset-password?token=abc123xyz789" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px; margin: 20px 0;">
Reset Password
</a>
<p>If you didn't request this password reset, please ignore this email.</p>
<p>This link will expire in 1 hour for security reasons.</p>
<p>Best regards,<br>The PropChain Team</p>
</div>Usage:
await emailService.sendPasswordResetEmail('user@example.com', 'abc123xyz789');Template File: src/email/templates/account-locked.ejs
Purpose: Sent when a user's account is temporarily locked due to multiple failed login attempts.
Variables:
lockoutDuration- Duration of the lockout in minutes
Sample Payload:
{
"lockoutDuration": 30
}Rendered Preview:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #d9534f;">Account Locked</h2>
<p>Your PropChain account has been temporarily locked due to multiple failed login attempts.</p>
<p>The lockout will automatically expire in 30 minutes.</p>
<p>If you did not attempt to log in, please reset your password immediately or contact our support team.</p>
<p>Best regards,<br>The PropChain Team</p>
</div>Usage:
await emailService.sendAccountLockedEmail('user@example.com', 30);Template File: src/email/templates/fraud-alert.ejs
Purpose: Sent to administrators when suspicious fraud activity is detected.
Variables:
alertId- Unique identifier for the fraud alertpattern- The fraud pattern detected (e.g., EXCESSIVE_FAILED_LOGINS)severity- Alert severity (LOW, MEDIUM, HIGH, CRITICAL)userEmail- Email of the user associated with the alertdescription- Detailed description of the suspicious activity
Sample Payload:
{
"alertId": "fraud-alert-123",
"pattern": "EXCESSIVE_FAILED_LOGINS",
"severity": "HIGH",
"userEmail": "user@example.com",
"description": "The account recorded 10 failed login attempts in the last 30 minutes."
}Rendered Preview:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #d9534f;">Fraud Alert Triggered</h2>
<p><strong>Alert ID:</strong> fraud-alert-123</p>
<p><strong>Pattern:</strong> EXCESSIVE_FAILED_LOGINS</p>
<p><strong>Severity:</strong> HIGH</p>
<p><strong>User:</strong> user@example.com</p>
<p><strong>Summary:</strong> The account recorded 10 failed login attempts in the last 30 minutes.</p>
</div>Usage:
await emailService.sendFraudAlertEmail(['admin@example.com'], {
alertId: 'fraud-alert-123',
pattern: 'EXCESSIVE_FAILED_LOGINS',
severity: 'HIGH',
title: 'Repeated failed login attempts detected',
description: 'The account recorded 10 failed login attempts in the last 30 minutes.',
userEmail: 'user@example.com'
});Template File: src/email/templates/transaction-status-pending.ejs
Purpose: Sent when a transaction is created and set to pending status.
Variables:
transactionId- Unique identifier for the transactionpropertyTitle- Title of the property involved in the transactionpropertyAddress- Address of the propertybuyerName- Name of the buyersellerName- Name of the selleramount- Transaction amountstatus- Current transaction status
Sample Payload:
{
"transactionId": "txn-123",
"propertyTitle": "Modern Downtown Apartment",
"propertyAddress": "123 Main St, New York, NY 10001",
"buyerName": "John Doe",
"sellerName": "Jane Smith",
"amount": "$500,000",
"status": "PENDING"
}Rendered Preview:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #333;">Transaction Created</h2>
<p>Your transaction has been successfully created and is now pending.</p>
<div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>Transaction ID:</strong> txn-123</p>
<p><strong>Property:</strong> Modern Downtown Apartment</p>
<p><strong>Address:</strong> 123 Main St, New York, NY 10001</p>
<p><strong>Amount:</strong> $500,000</p>
<p><strong>Status:</strong> PENDING</p>
</div>
<p>You will receive notifications as the transaction progresses.</p>
<p>Best regards,<br>The PropChain Team</p>
</div>Template File: src/email/templates/transaction-status-completed.ejs
Purpose: Sent when a transaction is successfully completed.
Variables:
transactionId- Unique identifier for the transactionpropertyTitle- Title of the property involved in the transactionpropertyAddress- Address of the propertybuyerName- Name of the buyersellerName- Name of the selleramount- Transaction amountcompletionDate- Date when transaction was completedblockchainTxHash- Blockchain transaction hash (if recorded)
Sample Payload:
{
"transactionId": "txn-123",
"propertyTitle": "Modern Downtown Apartment",
"propertyAddress": "123 Main St, New York, NY 10001",
"buyerName": "John Doe",
"sellerName": "Jane Smith",
"amount": "$500,000",
"completionDate": "January 15, 2026",
"blockchainTxHash": "0xabc123...xyz789"
}Rendered Preview:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #28a745;">Transaction Completed</h2>
<p>Congratulations! Your transaction has been successfully completed.</p>
<div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>Transaction ID:</strong> txn-123</p>
<p><strong>Property:</strong> Modern Downtown Apartment</p>
<p><strong>Address:</strong> 123 Main St, New York, NY 10001</p>
<p><strong>Amount:</strong> $500,000</p>
<p><strong>Completion Date:</strong> January 15, 2026</p>
<p><strong>Blockchain Hash:</strong> 0xabc123...xyz789</p>
</div>
<p>All documents and records have been updated. Thank you for using PropChain.</p>
<p>Best regards,<br>The PropChain Team</p>
</div>Template File: src/email/templates/transaction-status-cancelled.ejs
Purpose: Sent when a transaction is cancelled.
Variables:
transactionId- Unique identifier for the transactionpropertyTitle- Title of the property involved in the transactionpropertyAddress- Address of the propertybuyerName- Name of the buyersellerName- Name of the selleramount- Transaction amountcancellationReason- Reason for cancellation (if provided)cancelledDate- Date when transaction was cancelled
Sample Payload:
{
"transactionId": "txn-123",
"propertyTitle": "Modern Downtown Apartment",
"propertyAddress": "123 Main St, New York, NY 10001",
"buyerName": "John Doe",
"sellerName": "Jane Smith",
"amount": "$500,000",
"cancellationReason": "Mutual agreement between parties",
"cancelledDate": "January 10, 2026"
}Rendered Preview:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #d9534f;">Transaction Cancelled</h2>
<p>Your transaction has been cancelled.</p>
<div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>Transaction ID:</strong> txn-123</p>
<p><strong>Property:</strong> Modern Downtown Apartment</p>
<p><strong>Address:</strong> 123 Main St, New York, NY 10001</p>
<p><strong>Amount:</strong> $500,000</p>
<p><strong>Reason:</strong> Mutual agreement between parties</p>
<p><strong>Cancelled Date:</strong> January 10, 2026</p>
</div>
<p>If you have any questions about this cancellation, please contact our support team.</p>
<p>Best regards,<br>The PropChain Team</p>
</div>async sendPasswordResetEmail(email: string, resetToken: string): Promise<void>Sends a password reset email to the specified user.
Parameters:
email- User's email addressresetToken- Password reset token
async sendAccountLockedEmail(email: string, lockoutDuration: number): Promise<void>Sends an account locked notification email.
Parameters:
email- User's email addresslockoutDuration- Lockout duration in minutes
async sendFraudAlertEmail(recipients: string[], payload: FraudAlertEmailPayload): Promise<void>Sends fraud alert notifications to administrators.
Parameters:
recipients- Array of admin email addressespayload- Fraud alert details
FraudAlertEmailPayload Interface:
interface FraudAlertEmailPayload {
alertId: string;
pattern: string;
severity: string;
title: string;
description: string;
userEmail?: string | null;
}async sendTransactionStatusEmail(
email: string,
status: TransactionStatus,
payload: TransactionStatusPayload
): Promise<void>Sends transaction status change notifications.
Parameters:
email- Recipient's email addressstatus- Transaction status (PENDING, COMPLETED, CANCELLED)payload- Transaction details
TransactionStatusPayload Interface:
interface TransactionStatusPayload {
transactionId: string;
propertyTitle: string;
propertyAddress: string;
buyerName: string;
sellerName: string;
amount: string;
completionDate?: string;
blockchainTxHash?: string;
cancellationReason?: string;
cancelledDate?: string;
}For admin preview purposes, the following endpoint can be used to render email templates with sample data:
Description: Renders a preview of the specified email template with sample data.
Authentication: Required (Admin only)
Parameters:
templateName- Name of the template to preview (e.g., password-reset, account-locked, fraud-alert, transaction-status-pending, transaction-status-completed, transaction-status-cancelled)
Response: HTML rendered template
Example Request:
GET /admin/email/preview/password-resetExample Response:
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #333;">Password Reset Request</h2>
<p>You have requested to reset your password for your PropChain account.</p>
<p>Please click the link below to reset your password:</p>
<a href="http://localhost:3000/reset-password?token=sample-token-123" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px; margin: 20px 0;">
Reset Password
</a>
<p>If you didn't request this password reset, please ignore this email.</p>
<p>This link will expire in 1 hour for security reasons.</p>
<p>Best regards,<br>The PropChain Team</p>
</div>Email templates should be tested with the following test cases:
- Variable Rendering: Ensure all template variables are properly rendered
- Missing Variables: Test behavior when optional variables are missing
- HTML Validation: Ensure rendered HTML is valid
- Responsive Design: Verify templates render correctly on mobile devices
- Link Functionality: Test that all links in templates are functional
Use the following sample data for testing:
const testEmailData = {
passwordReset: {
resetUrl: 'http://localhost:3000/reset-password?token=test-token-123'
},
accountLocked: {
lockoutDuration: 30
},
fraudAlert: {
alertId: 'test-alert-123',
pattern: 'EXCESSIVE_FAILED_LOGINS',
severity: 'HIGH',
userEmail: 'test@example.com',
description: 'Test fraud alert description'
},
transactionPending: {
transactionId: 'txn-test-123',
propertyTitle: 'Test Property',
propertyAddress: '123 Test St, Test City, TC 12345',
buyerName: 'Test Buyer',
sellerName: 'Test Seller',
amount: '$100,000',
status: 'PENDING'
},
transactionCompleted: {
transactionId: 'txn-test-123',
propertyTitle: 'Test Property',
propertyAddress: '123 Test St, Test City, TC 12345',
buyerName: 'Test Buyer',
sellerName: 'Test Seller',
amount: '$100,000',
completionDate: 'January 15, 2026',
blockchainTxHash: '0xabc123...xyz789'
},
transactionCancelled: {
transactionId: 'txn-test-123',
propertyTitle: 'Test Property',
propertyAddress: '123 Test St, Test City, TC 12345',
buyerName: 'Test Buyer',
sellerName: 'Test Seller',
amount: '$100,000',
cancellationReason: 'Test cancellation',
cancelledDate: 'January 10, 2026'
}
};- Keep Templates Simple: Avoid complex logic in templates
- Use Inline CSS: Email clients have limited CSS support
- Test Across Clients: Test templates in Gmail, Outlook, Apple Mail, etc.
- Include Plain Text: Always provide a plain text fallback
- Responsive Design: Ensure templates work on mobile devices
- Accessibility: Use semantic HTML and alt text for images
- Personalization: Use recipient names when possible
- Clear Call-to-Action: Make action buttons prominent and clear
- Brand Consistency: Maintain consistent branding across all templates
- Legal Compliance: Include required footer information (unsubscribe, privacy policy)
- Add email template versioning
- Implement A/B testing for email templates
- Add support for multi-language templates
- Create template editor UI for admins
- Add email analytics tracking
- Implement template preview with custom data