Once I’ve written about contact forms for static sites, and I’ve implemented Netlify Forms for a while. The limit for Netlify Forms is that obvious that you have to host your site on Netlify with certain limitations (with a free plan). Bypass that limitation is also easy, switch to a more general accessible serverless function with powerful control.
Nowadays, there are so many serverless function providers, such as Firebase, AWS, IBM Cloud, Azure, Vercel… You can choose whichever you’re interested. Here I’m going to use Express with Node.js as a brief introduction.
Sending E-mails?
Once I’ve started building my contact form with serverless function, the first thought is to sending emails to me (or team) with services such as SendGrid. However, as I’m using Hotmail and it’s always trying to block emails from SendGrid’s public IPs… The same to other email providers, I can rarely get messages during testing. Then Slack saved me…
Setup Slack app
For posting messages to a specific channel or posting a direct message in Slack workspace, you need to create a Slack app first (without distribution, just use it in your workspace is fine).
Just visit https://api.slack.com/apps/ to create an App with detailed configurations and install it in your workspace.
For posting messages with a serverless function, we just need to set up an “Incoming Webhooks” and get the webhook URL. For my case, I just authorised the following permissions:
- Post messages to specific channels in Slack
- Post messages to direct message conversation
Sending messages via serverless function
Once we got our webhook URL, we need to POST messages to that URL and then messages will pop in our Slack app.
The following JavaScript code is running on Heroku with the Express framework:
const router = require('express').Router()
const axios = require('axios')
const prettier = require('prettier')
router.get('/', async (req, res) => {
res.status(405).json('Method Not Allowed')
})
router.post('/', async (req, res) => {
const postData = req.body
if (postData.content) {
try {
const message = "```"
+ prettier.format(JSON.stringify(postData), { semi: false, parser: 'json' })
+ "```\n"
const slackRes = await axios.post(process.env.SLACK_WEBHOOK_URL, {
text: message,
mrkdwn: true // Slack markdown style
})
if (slackRes.data === 'ok') {
res.status(200).json('success')
} else {
res.status(500).end()
}
} catch (err) {
console.log(err)
res.status(500).json(err)
}
} else {
res.status(400).json("Bad Request!")
}
})
module.exports = router
I just formatted all the message contents into block code, see Slack docs for more formatting options.
Okay, that’s all for the serverless function. Setup a URL endpoint to this serverless function, and test it or start using it in your contact form…