humanai-web/mailer/mailer.mjs

83 lines
2.2 KiB
JavaScript
Raw Permalink Normal View History

import express from 'express';
import nodemailer from 'nodemailer';
const app = express();
app.use(express.json());
// Rate limiter: max 5 requests/min per IP
const rateLimiter = new Map();
function checkRateLimit(ip) {
const now = Date.now();
const window = 60_000;
const max = 5;
const entry = rateLimiter.get(ip) ?? { count: 0, start: now };
if (now - entry.start > window) {
entry.count = 0;
entry.start = now;
}
entry.count++;
rateLimiter.set(ip, entry);
return entry.count <= max;
}
// Prune rate limiter every 5 minutes
setInterval(() => {
const cutoff = Date.now() - 60_000;
for (const [ip, entry] of rateLimiter) {
if (entry.start < cutoff) rateLimiter.delete(ip);
}
}, 300_000);
const transporter = nodemailer.createTransport({
host: 'smtp.fastmail.com',
port: 465,
secure: true,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
app.post('/api/contact', async (req, res) => {
const ip =
(req.headers['x-forwarded-for'] ?? '').split(',')[0].trim() ||
req.socket.remoteAddress;
if (!checkRateLimit(ip)) {
return res.status(429).json({ error: 'Too many requests' });
}
const { name, email, message, company } = req.body ?? {};
if (!name || typeof name !== 'string' || !name.trim()) {
return res.status(400).json({ error: 'name required' });
}
if (!email || typeof email !== 'string' || !email.includes('@')) {
return res.status(400).json({ error: 'valid email required' });
}
if (!message || typeof message !== 'string' || message.trim().length < 5) {
return res.status(400).json({ error: 'message too short' });
}
// Honeypot
if (company) {
return res.json({ ok: true });
}
try {
await transporter.sendMail({
from: 'oskar@gethumanai.com',
to: 'oskar@gethumanai.com',
replyTo: email,
subject: `Kontakt od ${name.trim()}`,
text: `Imię: ${name.trim()}\nEmail: ${email}\n\n${message.trim()}`,
});
res.json({ ok: true });
} catch (err) {
console.error('SMTP error:', err);
res.status(502).json({ error: 'mail delivery failed' });
}
});
app.listen(3000, () => console.log('mailer listening on :3000'));