1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
import nodemailer from 'nodemailer';
// Email configuration
// Required environment variables:
// - SMTP_HOST: Your SMTP server host (e.g. smtp.gmail.com)
// - SMTP_PORT: Your SMTP server port (e.g. 587 for TLS, 465 for SSL)
// - SMTP_USER: Your SMTP server username/email
// - SMTP_PASSWORD: Your SMTP server password or app password
// - EMAIL_FROM: The email address that will appear as sender
const smtpConfig = {
host: process.env.SMTP_HOST,
port: parseInt(process.env.SMTP_PORT || '587'),
secure: process.env.SMTP_PORT === '465', // true for 465, false for other ports
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
};
// For development, if SMTP credentials aren't provided, log messages instead of sending
const devMode = process.env.NODE_ENV !== 'production' &&
(!process.env.SMTP_HOST || !process.env.SMTP_USER || !process.env.SMTP_PASSWORD);
// Create a reusable transporter object
let transporter: nodemailer.Transporter;
// Initialize the transporter
export const initializeEmailTransporter = () => {
if (devMode) {
console.log('Email dev mode active: emails will be logged instead of sent');
// Use Nodemailer's testing account for development
return nodemailer.createTransport({
jsonTransport: true // This outputs the email to the console instead of sending it
});
}
if (!transporter) {
transporter = nodemailer.createTransport(smtpConfig);
}
return transporter;
};
// Send location sharing email
export const sendLocationSharingEmail = async ({
to,
senderName,
locationUrl,
expiryTime,
}: {
to: string;
senderName: string;
locationUrl: string;
expiryTime?: Date;
}) => {
const emailTransporter = initializeEmailTransporter();
const expiryMessage = expiryTime
? `This location share will expire on ${expiryTime.toLocaleString()}.`
: 'This location share does not expire.';
const mailOptions = {
from: process.env.EMAIL_FROM || `"Location Tracker" <${process.env.SMTP_USER || '[email protected]'}>`,
to,
subject: `${senderName} shared their location with you`,
text: `
${senderName} has shared their real-time location with you.
Click the link below to view their current location:
${locationUrl}
${expiryMessage}
This is an automated message, please do not reply.
`,
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #4a5568;">Location Shared with You</h2>
<p>${senderName} has shared their real-time location with you.</p>
<div style="margin: 20px 0;">
<a href="${locationUrl}" style="background-color: #4299e1; color: white; padding: 10px 15px; text-decoration: none; border-radius: 5px; display: inline-block;">
View Location
</a>
</div>
<p style="color: #718096; font-size: 14px;">${expiryMessage}</p>
<hr style="border: none; border-top: 1px solid #e2e8f0; margin: 20px 0;" />
<p style="color: #a0aec0; font-size: 12px;">
This is an automated message from Real-Time Location Tracker. Please do not reply.
</p>
</div>
`,
};
try {
if (devMode) {
// In dev mode, log the email details instead of sending
console.log('DEV MODE: Email would be sent with the following details:');
console.log('To:', to);
console.log('Subject:', mailOptions.subject);
console.log('Location URL:', locationUrl);
return { success: true, messageId: 'dev-mode-email', devMode: true };
}
const info = await emailTransporter.sendMail(mailOptions);
return { success: true, messageId: info.messageId };
} catch (error) {
console.error('Error sending email:', error);
throw new Error('Failed to send email. Please check your SMTP settings.');
}
};
|