knight 4dbb0b9180 Initial commit: 23 docker stacks for GitOps deployment
Stacks included:
- Infrastructure: traefik, authentik, gitea, registry, watchtower, dockge
- Monitoring: smokeping, changedetection
- Apps: ghost, gollum, wallabag, radicale, invidious, xbackbone, filebrowser, syncthing, zerotier
- Custom: obsidian-tools, memento, perilous, ramz, bookclub, brain

🤖 Generated with Claude Code
2025-12-31 13:29:43 -05:00

52 lines
1.3 KiB
JavaScript

const express = require('express');
const nodemailer = require('nodemailer');
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
if (process.env.TRUST_PROXY === 'true') {
app.set('trust proxy', true);
}
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: parseInt(process.env.SMTP_PORT || '465'),
secure: process.env.SMTP_SECURE === 'true',
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});
app.post('/submit', async (req, res) => {
const { secret, ...formData } = req.body;
if (secret !== process.env.SECRET_PHRASE) {
return res.status(403).send('Invalid secret phrase');
}
try {
await transporter.sendMail({
from: process.env.MAIL_FROM,
to: process.env.MAIL_TO,
subject: 'New Form Submission',
text: Object.entries(formData)
.map(([key, value]) => `${key}: ${value}`)
.join('\n')
});
res.redirect(process.env.THANK_YOU_URL || '/thanks.html');
} catch (error) {
console.error('Mail error:', error);
res.status(500).send('Failed to send email');
}
});
const port = parseInt(process.env.BIND_PORT || '3000');
const host = process.env.BIND_HOST || '0.0.0.0';
app.listen(port, host, () => {
console.log(`Form mailer listening on ${host}:${port}`);
});