Skip to content

Commit 3aed97f

Browse files
committed
Add security notification email service utility
Introduces a utility for sending security event notification emails, including templates for various event types (login, password change, failed login, etc.) and batch notification support. Email content is generated dynamically based on event details, with a placeholder for integrating an actual email service.
1 parent 9e96494 commit 3aed97f

1 file changed

Lines changed: 252 additions & 0 deletions

File tree

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/**
2+
* Security Notification Email Service
3+
* Sends alerts for important security events
4+
*/
5+
6+
export interface SecurityEvent {
7+
type: 'login' | 'password_change' | 'email_change' | 'mfa_enabled' | 'mfa_disabled' | 'failed_login' | 'account_locked' | 'new_device' | 'suspicious_activity'
8+
userEmail: string
9+
userName?: string
10+
details: {
11+
ipAddress?: string
12+
location?: string
13+
device?: string
14+
timestamp: string
15+
[key: string]: any
16+
}
17+
}
18+
19+
/**
20+
* Send security notification email
21+
* @param event - Security event details
22+
* @returns Promise indicating success/failure
23+
*/
24+
export async function sendSecurityNotification(event: SecurityEvent): Promise<boolean> {
25+
try {
26+
const emailContent = generateEmailContent(event)
27+
28+
// TODO: Integrate with your email service (SendGrid, AWS SES, Resend, etc.)
29+
// Example with fetch to your API endpoint:
30+
const response = await fetch('/api/send-email', {
31+
method: 'POST',
32+
headers: { 'Content-Type': 'application/json' },
33+
body: JSON.stringify({
34+
to: event.userEmail,
35+
subject: emailContent.subject,
36+
html: emailContent.html,
37+
text: emailContent.text,
38+
}),
39+
})
40+
41+
return response.ok
42+
} catch (error) {
43+
console.error('Failed to send security notification:', error)
44+
return false
45+
}
46+
}
47+
48+
/**
49+
* Generate email content based on event type
50+
*/
51+
function generateEmailContent(event: SecurityEvent): {
52+
subject: string
53+
html: string
54+
text: string
55+
} {
56+
const { type, userName, details } = event
57+
const name = userName || 'User'
58+
const timestamp = new Date(details.timestamp).toLocaleString()
59+
const location = details.location || 'Unknown location'
60+
const ipAddress = details.ipAddress || 'Unknown IP'
61+
const device = details.device || 'Unknown device'
62+
63+
const baseStyles = `
64+
<style>
65+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; line-height: 1.6; color: #333; }
66+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
67+
.header { background: linear-gradient(135deg, #00FF99 0%, #00CC7A 100%); color: #0A0A0A; padding: 30px; text-align: center; border-radius: 8px 8px 0 0; }
68+
.content { background: #f9f9f9; padding: 30px; border-radius: 0 0 8px 8px; }
69+
.alert { background: #fff; border-left: 4px solid #00FF99; padding: 15px; margin: 20px 0; }
70+
.details { background: #fff; padding: 15px; margin: 20px 0; border-radius: 4px; }
71+
.footer { text-align: center; color: #666; font-size: 12px; margin-top: 30px; }
72+
.button { display: inline-block; background: #00FF99; color: #0A0A0A; padding: 12px 30px; text-decoration: none; border-radius: 4px; font-weight: bold; margin: 10px 0; }
73+
</style>
74+
`
75+
76+
switch (type) {
77+
case 'login':
78+
return {
79+
subject: '🔐 New Login to Your Lab68 Account',
80+
html: `
81+
${baseStyles}
82+
<div class="container">
83+
<div class="header">
84+
<h1>New Login Detected</h1>
85+
</div>
86+
<div class="content">
87+
<p>Hi ${name},</p>
88+
<p>We detected a new login to your Lab68 account.</p>
89+
90+
<div class="details">
91+
<strong>Login Details:</strong><br>
92+
📅 Time: ${timestamp}<br>
93+
📍 Location: ${location}<br>
94+
🌐 IP Address: ${ipAddress}<br>
95+
💻 Device: ${device}
96+
</div>
97+
98+
<div class="alert">
99+
<strong>Was this you?</strong><br>
100+
If you recognize this login, no action is needed. If you don't recognize this activity, please secure your account immediately.
101+
</div>
102+
103+
<a href="https://lab68dev.com/dashboard/settings/security" class="button">Review Security Settings</a>
104+
105+
<p>Stay safe,<br>The Lab68 Team</p>
106+
</div>
107+
<div class="footer">
108+
<p>This is an automated security notification from Lab68 Dev Platform</p>
109+
</div>
110+
</div>
111+
`,
112+
text: `Hi ${name},\n\nWe detected a new login to your Lab68 account.\n\nLogin Details:\nTime: ${timestamp}\nLocation: ${location}\nIP Address: ${ipAddress}\nDevice: ${device}\n\nIf you don't recognize this activity, please secure your account immediately at https://lab68dev.com/dashboard/settings/security\n\nStay safe,\nThe Lab68 Team`,
113+
}
114+
115+
case 'password_change':
116+
return {
117+
subject: '🔒 Your Lab68 Password Was Changed',
118+
html: `
119+
${baseStyles}
120+
<div class="container">
121+
<div class="header">
122+
<h1>Password Changed</h1>
123+
</div>
124+
<div class="content">
125+
<p>Hi ${name},</p>
126+
<p>Your Lab68 account password was successfully changed.</p>
127+
128+
<div class="details">
129+
<strong>Change Details:</strong><br>
130+
📅 Time: ${timestamp}<br>
131+
📍 Location: ${location}<br>
132+
🌐 IP Address: ${ipAddress}
133+
</div>
134+
135+
<div class="alert">
136+
<strong>Didn't make this change?</strong><br>
137+
If you didn't change your password, your account may be compromised. Reset your password immediately and enable two-factor authentication.
138+
</div>
139+
140+
<a href="https://lab68dev.com/dashboard/settings/security" class="button">Secure My Account</a>
141+
142+
<p>Stay safe,<br>The Lab68 Team</p>
143+
</div>
144+
<div class="footer">
145+
<p>This is an automated security notification from Lab68 Dev Platform</p>
146+
</div>
147+
</div>
148+
`,
149+
text: `Hi ${name},\n\nYour Lab68 account password was successfully changed at ${timestamp}.\n\nIf you didn't make this change, please secure your account immediately at https://lab68dev.com/dashboard/settings/security\n\nStay safe,\nThe Lab68 Team`,
150+
}
151+
152+
case 'mfa_enabled':
153+
return {
154+
subject: '✅ Two-Factor Authentication Enabled',
155+
html: `
156+
${baseStyles}
157+
<div class="container">
158+
<div class="header">
159+
<h1>2FA Enabled Successfully</h1>
160+
</div>
161+
<div class="content">
162+
<p>Hi ${name},</p>
163+
<p>Two-factor authentication has been enabled on your Lab68 account. Your account is now more secure! 🎉</p>
164+
165+
<div class="alert">
166+
<strong>Important:</strong><br>
167+
Make sure to save your backup codes in a safe place. You'll need them if you lose access to your authenticator app.
168+
</div>
169+
170+
<p>Enabled at: ${timestamp}</p>
171+
172+
<p>Stay safe,<br>The Lab68 Team</p>
173+
</div>
174+
<div class="footer">
175+
<p>This is an automated security notification from Lab68 Dev Platform</p>
176+
</div>
177+
</div>
178+
`,
179+
text: `Hi ${name},\n\nTwo-factor authentication has been enabled on your Lab68 account at ${timestamp}.\n\nMake sure to save your backup codes in a safe place.\n\nStay safe,\nThe Lab68 Team`,
180+
}
181+
182+
case 'failed_login':
183+
return {
184+
subject: '⚠️ Failed Login Attempts on Your Account',
185+
html: `
186+
${baseStyles}
187+
<div class="container">
188+
<div class="header">
189+
<h1>Failed Login Attempts</h1>
190+
</div>
191+
<div class="content">
192+
<p>Hi ${name},</p>
193+
<p>We detected multiple failed login attempts on your Lab68 account.</p>
194+
195+
<div class="details">
196+
<strong>Attempt Details:</strong><br>
197+
📅 Time: ${timestamp}<br>
198+
📍 Location: ${location}<br>
199+
🌐 IP Address: ${ipAddress}<br>
200+
🔢 Attempts: ${details.attempts || 'Multiple'}
201+
</div>
202+
203+
<div class="alert">
204+
<strong>Protect your account:</strong><br>
205+
If this wasn't you, someone may be trying to access your account. We recommend changing your password and enabling two-factor authentication.
206+
</div>
207+
208+
<a href="https://lab68dev.com/dashboard/settings/security" class="button">Secure My Account</a>
209+
210+
<p>Stay safe,<br>The Lab68 Team</p>
211+
</div>
212+
<div class="footer">
213+
<p>This is an automated security notification from Lab68 Dev Platform</p>
214+
</div>
215+
</div>
216+
`,
217+
text: `Hi ${name},\n\nWe detected multiple failed login attempts on your Lab68 account at ${timestamp} from ${location} (${ipAddress}).\n\nIf this wasn't you, please secure your account immediately at https://lab68dev.com/dashboard/settings/security\n\nStay safe,\nThe Lab68 Team`,
218+
}
219+
220+
default:
221+
return {
222+
subject: '🔔 Security Alert - Lab68 Account',
223+
html: `
224+
${baseStyles}
225+
<div class="container">
226+
<div class="header">
227+
<h1>Security Alert</h1>
228+
</div>
229+
<div class="content">
230+
<p>Hi ${name},</p>
231+
<p>We detected important security activity on your Lab68 account at ${timestamp}.</p>
232+
233+
<a href="https://lab68dev.com/dashboard/settings/security" class="button">Review Activity</a>
234+
235+
<p>Stay safe,<br>The Lab68 Team</p>
236+
</div>
237+
<div class="footer">
238+
<p>This is an automated security notification from Lab68 Dev Platform</p>
239+
</div>
240+
</div>
241+
`,
242+
text: `Hi ${name},\n\nWe detected important security activity on your Lab68 account at ${timestamp}.\n\nPlease review your security settings at https://lab68dev.com/dashboard/settings/security\n\nStay safe,\nThe Lab68 Team`,
243+
}
244+
}
245+
}
246+
247+
/**
248+
* Batch send notifications for multiple events
249+
*/
250+
export async function sendBatchNotifications(events: SecurityEvent[]): Promise<boolean[]> {
251+
return Promise.all(events.map(event => sendSecurityNotification(event)))
252+
}

0 commit comments

Comments
 (0)