- Fork elmeg-demo codebase for multi-band support - Add data importer infrastructure with base class - Create band-specific importers: - phish.py: Phish.net API v5 - grateful_dead.py: Grateful Stats API - setlistfm.py: Dead & Company, Billy Strings (Setlist.fm) - Add spec-kit configuration for Gemini - Update README with supported bands and architecture
176 lines
5.3 KiB
TypeScript
176 lines
5.3 KiB
TypeScript
/**
|
|
* 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;
|
|
*/
|