Skip to content

Commit

Permalink
feat: integrate websmtp mailer
Browse files Browse the repository at this point in the history
  • Loading branch information
zeim839 committed Jan 18, 2024
1 parent 0c3d573 commit 0fc7f8b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 83 deletions.
129 changes: 65 additions & 64 deletions routes/contact.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
const express = require('express')
const router = express.Router()
const nodemailer = require('nodemailer')
const config = require('../utils/config')
const FormData = require('form-data')
const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args))

const transport = (config.smtp == null) ? null : nodemailer.createTransport(config.smtp)
const axios = require('axios').default

// Regex to validate an email address
const validateAddress = (req, res, next) => {
Expand Down Expand Up @@ -57,7 +54,7 @@ const validateContactForm = async (req, res, next) => {
}

if (typeof req.body.Token !== 'string') {
return res.status(400).send({ error: 'Expected captcha token.' })
return res.status(400).send({ error: 'Bad captcha token. Please refresh the page and try again.' })
}

// Sanitise HTML
Expand All @@ -81,77 +78,81 @@ const validateTurnstile = async (req, res, next) => {
formData.append('response', token)
formData.append('remoteip', ip)

const ftc = await fetch(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
{
method: 'POST',
body: formData
}
)
try {
const response = await axios.post(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
formData)

// Compare to true in case response is undefined.
const valid = await ftc.json()
if (!valid.success) {
if (response.status === 200 && typeof response.data !== 'undefined' && response.data.success) {
next()
} else {
return res.status(401).send({ error: 'Bad CAPTCHA Response' })
}
} catch (error) {
return res.status(401).send({ error: 'Bad CAPTCHA Response' })
}

next()
}

// Contact form message submission route
router.post('/', validateContactForm, validateTurnstile,
validateAddress, async (req, res) => {
if (transport == null) {
return res.status(400).send({ error: 'SMTP has not been configured' })
}

const message = {
FirstName: req.body.FirstName,
LastName: req.body.LastName,
Email: req.body.Email,
Message: req.body.Message
firstName: req.body.FirstName,
lastName: req.body.LastName,
email: req.body.Email,
message: req.body.Message
}

// Send confirmation receipt to sender
let info = await transport.sendMail({
subject: 'Your message was received',
text: `Dear ${message.FirstName} ${message.LastName},
Thank you for contacting the UF Open Source Club, this is an automated email confirming receipt of your message.
A club representative will be in touch soon.
Kindly,
UF OSC`,
from: '[email protected]',
to: req.body.Email
})

if (info.rejected.length !== 0) {
return req.status(400).send({ error: 'Message was rejected by server. Please try again later.' })
try {
// Send message receipt to sender.
const toSender = await axios.post(config.smtp_host, {
from: '[email protected]',
to: [message.email],
subject: '[UF OSC] Your message has been received',
body: `Thank you for contacting the UF OSC team, your message has been received.<br />
A representative will reach out within 24-48 hours.<br />
<br />
Sincerely,<br />
UF Open Source Club Team`
})

if (toSender.status !== 200) {
return res.status(400).send({
error: 'Your message could not be sent. Please try again later.'
})
}

// Send copy of message to admin.
const toAdmin = await axios.post(config.smtp_host, {
from: '[email protected]',
to: [config.admin_email],
subject: '[UF OSC] New Message from Website',
body: `You've received a new message via the OSC website contact form.<br />
<br />
First Name: ${message.firstName}<br />
Last Name: ${message.lastName}<br />
Email Address: ${message.email}<br />
<br />
### BEGIN MESSAGE ###<br />
${message.message}
<br />### END MESSAGE ###<br />
<br />
Please respond by composing a new email to ${message.email}. Replies to this message will not be delivered.
`
})

if (toAdmin.status !== 200) {
return res.status(400).send({
error: 'Your message could not be sent. Please try again later.'
})
}

return res.status(200).send('Success')
} catch (error) {
return res.status(400).send({
error: 'Your message could not be sent. Please try again later.'
})
}

// Send message confirmation receipt to UF OSC admin
info = await transport.sendMail({
subject: 'New Message from Website',
text: `${message.FirstName} ${message.LastName} sent a message via your website's contact form.
A copy of the message is attached below:
--- BEGIN MESSAGE ---
${message.Message}
--- END MESSAGE ---
You can reach this user via their email address: ${message.Email}
or by replying to this email.
`,
from: '[email protected]',
to: config.admin_email
})

if (info.rejected.length !== 0) {
return req.status(400).send({ error: 'Message was rejected by server. Please try again later,' })
}

return res.status(200).send('Success')
})

module.exports = router
22 changes: 3 additions & 19 deletions utils/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const config = {
},
cache_interval: process.env.CACHE_INTERVAL * 60 * 1000 || 10 * 1000,
secret: 'jLJhDQMYtXjCwQmu',
smtp: null,
smtp_host: process.env.SMTP_HOST || 'http://localhost:30000/mail/send',
admin_email: process.env.ADMIN_EMAIL,
captcha_secret: '1x0000000000000000000000000000000AA'
},
Expand All @@ -36,15 +36,7 @@ const config = {
},
cache_interval: process.env.CACHE_INTERVAL * 60 * 1000 || 15 * 60 * 1000,
secret: process.env.SECRET,
smtp: {
host: process.env.SMTP_HOST || 'smtp-relay.sendinblue.com',
port: process.env.SMTP_PORT || 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
},
smtp_host: process.env.SMTP_HOST || 'http://localhost:30000/mail/send',
admin_email: process.env.ADMIN_EMAIL,
captcha_secret: process.env.CAPTCHA_SECRET
},
Expand All @@ -58,15 +50,7 @@ const config = {
},
cache_interval: process.env.CACHE_INTERVAL * 60 * 1000 || 15 * 60 * 1000,
secret: process.env.SECRET,
smtp: {
host: process.env.SMPT_HOST || 'smtp-relay.sendinblue.com',
port: process.env.SMPT_PORT || 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMPT_PASS
}
},
smtp_host: process.env.SMTP_HOST,
admin_email: process.env.ADMIN_EMAIL,
captcha_secret: process.env.CAPTCHA_SECRET
}
Expand Down

0 comments on commit 0fc7f8b

Please sign in to comment.