Build your own contact form and a private inbox for your website

Blog


author small image Siva Kishore G
Posted : 08 Mar 2022
Modified : 06 Jun 2022
Expert Developers

Introduction

Privacy is the top concern nowadays. Search engines & browsers track your activity, cell phones track your location and your ISP tracks your internet traffic.. the list is almost endless. Ever since that Snowden episode, more and more companies are security concerned. There exists a private search engine called "duck duck go" which is relatively new and their goal is to promote security and privacy.

Sometimes, you may want to keep the communication that goes around you or in your company private. Well, this is an attempt to create a process for the data that flows from your website to you.

Email at work

Most of the time, the contact form on your website sends the data to you via an email. Contact form, ninja forms, gravity forms etc, all these wordpress plugins do that exactly.

But if you are really privacy concerned, you might be itching to develop your own system. If you are that, then let's go!

Any other advantages?

Email providers are pretty good at filtering spam but sometimes can get too aggressive or too lenient. If your website is how you get leads, and if they go to spam, it's not good.. is it? Create your own spam filter. Filter the emails by unwanted emails or unwanted keywords.

Prerequisites

  1. Node JS
  2. Express
  3. Express-handlebars
  4. Database (MongoDB / DynamoDB / MySQL)
  5. Spam filtering techniques
  6. Server rate limiting (NGINX)

Use case : Digital Marketing

Digital marketing companies host many websites for their clients. I've seen first hand how many other companies submit their sales pitch via a contact form on the clients' website. An unwanted situation and as a developer you can track and mitigate these unwanted problems!

Design database

Both relational and nonrelational databases excel in various ways. It all depends on how we architecture each data field (column in case of mySQL).

Date received
Sender
Subject
Message excerpt
Full message
Message Status (Read / Unread / Trashed / Spam)
Mechanism for cleaning trash after 30 days
Attachments (Optional)

After setting up the database, we need to do the queries like these and the database should be designed while keeping these in mind.

  • Query by sender & sort by Date received and is not a spam / Trashed
  • Query by Date received in descending order and is not a spam / Trashed
  • Query by Message status where it is read / unread / spam / trashed

Design UIs

We need to design two UIs.

  1. One for the user to enter the data (contact-us form) and an admin inbox. I've discussed a simple way of form submission here. Below is the code for a simple contact-us form. If you want the form to have an attachment such as image or pdf etc, see the form upload logic here

    Contact form
    View code
    <div class="container">
    <div class='row'>
    <div class="col-md-5 mx-auto">
      <form onsubmit="event.preventDefault();submitMessage(this)">
        <div class="p-4 border shadow-sm rounded bg-white">
          <h3 class="text-muted text-center mt-1 mb-4">Contact Us</h3>
          <div class="form-floating mb-3">
            <input type="text" class="form-control" name="firstname" id="firstname"  required>
            <label for="firstname">First Name <span class="text-danger">*</span></label>
          </div>
          <div class="form-floating mb-3">
            <input type="text" class="form-control" name="lastname" id="lastname"  required>
            <label for="lastname">Last Name <span class="text-danger">*</span></label>
          </div>
          <div class="form-floating mb-3">
            <input type="text" class="form-control" name="phone" id="phone"  required>
            <label for="phone">Phone <span class="text-danger">*</span></label>
          </div>
          <div class="form-floating mb-3">
            <input type="email" class="form-control" name="email" id="email"  required>
            <label for="email">Email address <span class="text-danger">*</span></label>
          </div>
          <div class="form-floating mb-4">
            <textarea style="resize:none;height:120px;" class="form-control" id="message" name="message"></textarea>
            <label for="message">Message <span class="text-danger">*</span></label>
          </div>
          <button class="w-100 btn-success btn">Submit</button>
        </div>
      </form>
    </div>
    </div>
    </div>
    
  2. This is a three panel inbox template. Not a fully mobile responsive design though. Because you might want to implement this in a react or vue app or simple html.

    Contact form
    View code
    .letterAvatar {
      vertical-align: middle;
      display: inline-block;
      background: #8773d5;
      text-align: center;
    }
    .avatar-lg {
      width: 48px;
      height: 48px;
      line-height: 48px;
      font-size: 18px;
      border-radius: 24px;
    }
    .avatar-sm {
      width: 32px;
      height: 32px;
      line-height: 32px;
      font-size: 16px;
      border-radius: 24px;
    }
    .extra-rounded-links {
      color:#3b3b3b;
      text-decoration:none;
      border-radius:16px;
    }
    .extra-rounded-links i {
      color:#aeaeae
    }
    .extra-rounded-links.active i ,
    .extra-rounded-links.active {
      color:#a870ce
    }
    .extra-rounded-links.active .badge{
      background : #a870ce
    }
    .text-semi-muted {
      color : #b2b2b2
    }
    <div class="px-4 py-2">
      <div class="container-fluid">
        <div class="row g-2">
          <div class="col-lg-3 col-md-3 col-sm-3 col-xs-12">
            <div class="border-end min-vh-100">
              <h1 class="p-3 border-bottom">Messages</h1>
              <div class="m-2">
                <a class="d-block p-3 my-1 extra-rounded-links active" href="#"><i class="fa-solid fa-inbox me-2"></i> Inbox <span style="float:right" class='badge'>3</span></a>
                <a class="d-block p-3 my-1 extra-rounded-links" href="#"><i class="fa-solid fa-star me-2"></i> Starred</a>
                <a class="d-block p-3 my-1 extra-rounded-links" href="#"><i class="fa-solid fa-trash me-2"></i> Trash</a>
                <a class="d-block p-3 my-1 extra-rounded-links" href="#"><i class="fa-solid fa-spaghetti-monster-flying me-2"></i> spam</a>
              </div>
            </div>
          </div>
          <div class="col-lg-9 col-md-9 col-sm-9 col-xs-12">
            <div class="container-fluid">
              <div class="d-flex align-items-center justify-content-between p-2">
                <div>
                  <div class="input-group">
                    <input type="text" class="form-control" placeholder="Search">
                    <span class="input-group-text bg-white no-border"><i class="fa-solid fa-magnifying-glass"></i></span>
                  </div>
                </div>
                <div class="d-flex justify-content-end align-items-center">
                  <div class="text-end mx-5"><i class="fa-solid fa-bell"></i></div>
                  <div class="text-end">
                    <div class="d-flex align-items-center">
                      <div>
                        <h6 class="m-0 p-0">Siva Kishore G</h6>
                        <p class="m-0 p-0 text-muted">
                          <small>admin@mywebsite.com</small>
                        </p>
                      </div>
                      <div class="mx-3">
                        <img class="bg-info rounded-circle" src="/static_files/images/author_small.jpg" style="max-height:42px" />
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="row">
                <div class="col-lg-4 col-md-4 col-sm-3 col-xs-12">
                  <div class="p-3 bg-light rounded h-100">
    
                    <div class="mb-2 bg-white p-2 rounded">
                      <div><span class="letterAvatar avatar-sm">JL</span> John luxemborg</div>
                      <p class="text-muted m-2">
                        <small>Lorem Ipsum is simply dummy</small>
                      </p>
                    </div>
                    <div class="mb-2 bg-white p-2 rounded">
                      <div><span class="letterAvatar avatar-sm">JL</span> John luxemborg</div>
                      <p class="text-muted m-2">
                        <small>Lorem Ipsum is simply dummy</small>
                      </p>
                    </div>
                    <div class="mb-2 bg-white p-2 rounded">
                      <div><span class="letterAvatar avatar-sm">JL</span> John luxemborg</div>
                      <p class="text-muted m-2">
                        <small>Lorem Ipsum is simply dummy</small>
                      </p>
                    </div>
    
                  </div>
                </div>
                <div class="col-lg-8 col-md-8 col-sm-9 col-xs-12 min-vh-100">
                  <div class="py-3 px-1 border-top border-bottom">
                    <div class='d-flex text-semi-muted'>
                      <div class="me-4"><i title="trash" class="fa-solid fa-trash"></i></div>
                      <div class="me-4"><i title="Mark as spam"  class="fa-solid fa-circle-info"></i></div>
                      <div class="me-4"><i title="Archive"  class="fa-solid fa-box-archive"></i></div>
                      <div class="me-4"><i title="Mark as unread"  class="fa-solid fa-envelope"></i></div>
                      <div class="me-4"><i title="Starred message"  class="fa-solid fa-star"></i></div>
                    </div>
                  </div>
                  <div>
                    <div class="py-3">
                      <span class='badge bg-info'><i class="fa-solid fa-envelope me-2"></i> Inbox</span>
                    </div>
                    <h2 class="pb-4">You got a new notification from your website</h2>
                    <div class='d-flex justify-content-between'>
                      <div>
                        <span class="letterAvatar avatar-lg">SG</span>
                        <span class="ms-2"><strong>Siva Kishore G</strong></span>
                      </div>
                      <div>
                        <span>April 13 2022, 12:30 (Today)</span>
                      </div>
                    </div>
                    <div class="my-4">
                      <p class="p-2">
                        Hi there, Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to
                        make a type specimen book.
                      </p>
    
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

Pre filter

Use techniques such as honey pot, recaptcha and solving the code works as prefiltering the spam. If everything is ok, then only allow form submission.

* Please post a comment if you would like me to do a blog on this

Post filter

Once the message is received, check the message's email against a known spam email database (Search online). Run the content through spam keywords such as "100% free", "Work from home", "Get started now" etc (Search online).



Post a comment

I promise, I keep it clean *

Comments

Alert SVG Cookie Consent

This website uses cookies and similar technologies, to enhance your browsing experience and provide personalized recommendations. By continuing to use our website, you agree to our Privacy policy.