DEV Community

Cover image for How I Designed A Smart Contact-Me Form

Posted on • Updated on

How I Designed A Smart Contact-Me Form

This is not a coding tutorial, but a very high level overview of my implementation. Nonetheless, I’ve shared links to my github code and various references inline. The contact-me form is on my website (scroll to the end).

The Problem

I wanted a practical contact-me form for my website so I could be notified when somebody left me a message. I also wanted to reply back to the user so they have my contact info as well.

The Solution

For notification, I decided to have a Slack Incoming Webhook. I would create a Slack channel and messages sent to me from my website would show up here. For the reply-back, I decided to send an email to the user only if they shared an existing/ valid email address.
Solution diagram

The Brainstorming

  • I initially had a NodeJS backend + Mongodb Atlas cluster to save message details (name, email, message) directly from the website. But this data was not of any use really. I just wanted to be notified and send a response back to the user.
  • To check if email is existing, python has a good library - validate_email. NodeJS didn’t really have a lot of ‘obvious’ options, and some had to be done manually (by sending an actual email to verify, which I didn’t want).
  • I didn’t want a server running at all times, since this feature would be sparingly used. Azure Functions was a good choice as I needed it to run (read as “cost me”) only when triggered by an HTTP request.
  • I also wanted to perform steps in sequence, and I wanted a way to store the state of my previous step (is email valid or not) and it made sense to use Azure Durable Functions for this.
  • Since Python libraries had a lot of my requirements covered, I chose Python over NodeJS.

The Implementation

  • Setup Azure Functions
    • I started with a quickstart Azure Functions (Python) project on my local VS Code as given on the Azure docs. I then published this demo to my Az account, and tested the example using Postman and the Az function URL. I now only had to swap out the examples with my own implementations.
    • Az Durable Functions has 3 types of functions (now 4 types) - Client (this kicks off the orchestrator), Orchestrator (manages different tasks or activities), and an Activity (what you’re really trying to do). The quickstart-demo gives you these.
    • Since I had 3 main activities to do, I created 3 Activity functions; one each to - send slack notification (notifySlackChannel file in repo), check if email is valid (isEmailExists) and send email (sendEmail). VS Code Az Functions plugin has quick-actions to create these. Then plug these new activities into the demo code, replacing the calls to Hello with your new 3 activities.
    • I started by getting my request body as payload and then passing this payload {user, email, message} into the Az Durable Functions.
  • Slack Notification - see sendEmail
    • Create a Slack account, and create a channel where you want your messages.
    • Create a Slack app, enable and create an incoming webhook. You will get a slack URL which you can use to POST messages by sending a payload to it; like { text: “your message comes here” }.
    • I also added formatting to my messages by using Slack’s Block kit UI. It’s pretty neat because all you have to do is send some additional JSON objects (for a button, etc) to the payload data. Rest remains the same. Sweet.
  • Check if email is valid - see isEmailExists
    • This is a simple python code that checks if the given email exists
  • Send email - see sendEmail
    • Get output of previous operation - isEmailExists. If this value is True, only then go ahead with this step.
    • This was a simple implementation, almost as given in their examples.
  • Environment variables
    • Best to not check-in config with code, and to use environment variables instead.
    • Az funcs allow you to add variables as configuration which can be used by your code.


  • The python smtplib (for sending emails) works fine on local, but when you deploy code to Az functions, Az does not pass the emails through. You need to use a SMTP relay services (SendGrid, Mailjet) to get this done on Azure.
  • Passing parameters from HTTP request to Az function is not very intuitive.
  • Debugging on Az functions after deployment is a pain. Use instead of print() (python) or console.log (JS).
  • The running logs on Az functions are not consistent and do not show/ run at times. Az portal has to be refreshed.
  • I had trouble with SendGrid. Looks like others have too. For me, they asked for way too many details (organization, address, reason to use this service, etc) on account creation and I wanted to be vague since I was only setting up for a dev project. They did not let me use SendGrid and forced me to create a ticket with support to justify how I wanted to use SendGrid for sending emails. Rude. Screw that. Mailjet was way easier to set up and their free account gives more emails (Mailjet allows 200, as compared to SendGrids 100 emails per day).

Top comments (0)