-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathserver.js
More file actions
147 lines (125 loc) · 5.85 KB
/
server.js
File metadata and controls
147 lines (125 loc) · 5.85 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import express from 'express';
import cors from 'cors';
import nodemailer from 'nodemailer';
import dotenv from 'dotenv';
dotenv.config({ path: '.env.local' });
const app = express();
const PORT = 3001;
// CORS Configuration
const allowedOrigins = process.env.CORS_ALLOWED_ORIGINS
? process.env.CORS_ALLOWED_ORIGINS.split(',').map(origin => origin.trim())
: ['http://localhost:5173', 'http://localhost:3000', 'http://localhost:4173'];
const corsOptions = {
origin: function (origin, callback) {
// Allow requests with no origin (like mobile apps or curl requests)
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) !== -1) {
callback(null, true);
} else {
console.warn(`CORS blocked origin: ${origin}`);
callback(new Error('Not allowed by CORS'));
}
},
credentials: process.env.CORS_ALLOW_CREDENTIALS === 'true',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
};
app.use(cors(corsOptions));
app.use(express.json());
app.post('/api/send-email', async (req, res) => {
const { firstName, lastName, email, message } = req.body;
if (!firstName || !lastName || !email || !message) {
return res.status(400).json({ error: 'All fields are required' });
}
try {
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST || 'smtp.gmail.com',
port: parseInt(process.env.SMTP_PORT || '587'),
secure: process.env.SMTP_SECURE === 'true',
auth: {
user: process.env.GMAIL_USER,
pass: process.env.GMAIL_PASS
},
tls: {
rejectUnauthorized: false
}
});
const htmlTemplate = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Contact Form Submission</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f8fafc;">
<div style="max-width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
<!-- Header -->
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; text-align: center;">
<h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">New Contact Message</h1>
<p style="color: #e2e8f0; margin: 10px 0 0 0; font-size: 16px;">From your portfolio website</p>
</div>
<!-- Content -->
<div style="padding: 40px 30px;">
<!-- Contact Info Card -->
<div style="background-color: #f8fafc; border-radius: 8px; padding: 25px; margin-bottom: 25px; border-left: 4px solid #667eea;">
<h2 style="color: #1e293b; margin: 0 0 20px 0; font-size: 20px; font-weight: 600;">Contact Information</h2>
<div style="margin-bottom: 15px;">
<span style="display: inline-block; width: 80px; color: #64748b; font-weight: 500;">Name:</span>
<span style="color: #1e293b; font-weight: 600;">${firstName} ${lastName}</span>
</div>
<div style="margin-bottom: 15px;">
<span style="display: inline-block; width: 80px; color: #64748b; font-weight: 500;">Email:</span>
<a href="mailto:${email}" style="color: #667eea; text-decoration: none; font-weight: 500;">${email}</a>
</div>
<div>
<span style="display: inline-block; width: 80px; color: #64748b; font-weight: 500;">Date:</span>
<span style="color: #1e293b;">${new Date().toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZone: 'Asia/Kolkata'
})}</span>
</div>
</div>
<!-- Message Card -->
<div style="background-color: #ffffff; border: 1px solid #e2e8f0; border-radius: 8px; padding: 25px;">
<h3 style="color: #1e293b; margin: 0 0 15px 0; font-size: 18px; font-weight: 600;">Message:</h3>
<div style="background-color: #f8fafc; padding: 20px; border-radius: 6px; border-left: 3px solid #10b981;">
<p style="color: #374151; line-height: 1.6; margin: 0; font-size: 16px;">${message}</p>
</div>
</div>
<!-- Quick Actions -->
<div style="margin-top: 30px; text-align: center;">
<a href="mailto:${email}" style="display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; padding: 12px 30px; text-decoration: none; border-radius: 6px; font-weight: 500; margin-right: 10px;">Reply to ${firstName}</a>
</div>
</div>
<!-- Footer -->
<div style="background-color: #f8fafc; padding: 20px; text-align: center; border-top: 1px solid #e2e8f0;">
<p style="color: #64748b; margin: 0; font-size: 14px;">This message was sent from your portfolio contact form</p>
<p style="color: #94a3b8; margin: 5px 0 0 0; font-size: 12px;">prverse.dev</p>
</div>
</div>
</body>
</html>
`;
// Send email
await transporter.sendMail({
from: process.env.GMAIL_USER,
to: process.env.GMAIL_USER, // Send to yourself
subject: `New Contact: ${firstName} ${lastName}`,
html: htmlTemplate,
replyTo: email
});
res.status(200).json({ success: true, message: 'Email sent successfully' });
} catch (error) {
console.error('Email error:', error);
res.status(500).json({ error: 'Failed to send email' });
}
});
app.listen(PORT, () => {
console.log(`Email server running on http://localhost:${PORT}`);
});