You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.4 KiB
JavaScript

const koa = require('koa')
const koaRouter = require('@koa/router')
const bodyParser = require('koa-bodyparser')
const nodemailer = require('nodemailer')
const cors = require('koa-cors')
const proxyaddr = require('proxy-addr')
const { RateLimiterMemory } = require('rate-limiter-flexible')
const app = new koa()
app.proxy = true;
app.use(cors({ methods: 'POST' }))
app.use(bodyParser())
const router = new koaRouter()
const { contacts, mailConfig, rateConfig } = require(process.env.CONTACT_CONFIG || './config.json')
if (!contacts || !mailConfig || !rateConfig) {
throw new Error("Incomplete config")
}
const rateLimit = new RateLimiterMemory(rateConfig)
const transport = nodemailer.createTransport(mailConfig)
transport.verify()
.then(() => console.log(`Email transport ready`))
.catch((err) => {
console.error('Cannot verify email transport');
console.error(err);
process.exit(1);
})
router.post('/api/contact/:id', async (ctx) => {
const { params: { id }, request, response } = ctx
// check if we have an ID
if (!contacts[id]) {
response.status = 400
response.body = {
error: `Invalid contact id "${id}"`
}
return
}
// check for request properties
const { name, email, phone, message } = request.body
if (!name || !email || !message) {
ctx.status = 400
ctx.body = {
status: 'error',
message: 'invalid request'
}
return
}
// check rate limit
const source = proxyaddr(request, 'loopback')
try {
// only counting as 1 point per request
await rateLimit.consume(source, 1)
} catch (err) {
ctx.status = 429
ctx.set('Retry-After', err.msBeforeNext / 1000)
ctx.body = {
status: 'ratelimit',
message: 'Too many messages, play nice friend'
}
return
}
const contact = contacts[id]
const emailBody =
`You have received a message via ${contact.site} from ${name}:
Contact info:
- Name: ${name}
- Email: ${email}
- Phone: ${phone || 'None supplied'}
Message:
${message}
`
console.log(`Received new message:\n${JSON.stringify({ name, email, phone, message, ip: source }, null, 2)}`)
await transport.sendMail({
from: `tempest.dev Mailer <${mailConfig.from || mailConfig.auth.user}>`,
to: contact.address,
subject: contact.subject,
text: emailBody
})
ctx.status = 200
ctx.body = {
status: 'Message sent'
}
})
app
.use(router.routes())
.use(router.allowedMethods())
.listen(process.env.PORT || 3000)