Feedback Form
Tags: python, html, github, programming
Published: 2022-03-10 19:32:36

# Feedback Form

---

## Introduction
In this post I'll show you the code for a feedback form which when someone fills it in, it sends the feedback to your email. It also has a feature that it adds a cookie to the device so you can only fill in the form once an hour.

---

## Structure
Your files and folder needs to be structured like below:
```
-- main.py
-- app.py
-- functions.py
-- templates
   |__ index.html
-- .env
```

---

## Code
### `main.py`
```py
from app import app

if __name__ == "__main__":
  app.run(host="0.0.0.0", port=8080)
```

### `app.py`
```py
from flask import Flask, render_template, redirect, request
from functions import send_mail, getcookie, addcookie, delcookies
import datetime
import os
import pytz

app = Flask(__name__, template_folder="templates")
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
utc = pytz.UTC

@app.route("/")
def index():
  return render_template("index.html")

@app.route("/submitform", methods=["POST", "GET"])
def submitform():
  if request.method == "POST":
    lastdone = getcookie("lastdone")
    if lastdone != False:
      timenow = datetime.datetime.now()
      lastdone = lastdone.replace(tzinfo=utc)
      timenow = timenow.replace(tzinfo=utc)
      onehour = datetime.timedelta(hours=1)
      lastdone = lastdone + onehour
      if lastdone > timenow:
        return "You can do the form at most once every hour!"
      delcookies()
    title = request.form["title"]
    email = request.form["email"]
    description = request.form["description"]
    send_mail(title, email, description)
    addcookie("lastdone", datetime.datetime.now())
    return "done!"
  else:
    return redirect("/")
```

### `functions.py`
```py
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
import ssl
from flask import session

def send_mail(title, email, description):  
    context = ssl.create_default_context()
    MAILPASS = os.getenv("MAIL_PASSWORD")
    MAIL = os.getenv("MAIL")
    html = f"""
    <h1>{title}</h1>
    <p>{description}</p>
    <p>From {email}</p>
    """
    message = MIMEMultipart("alternative")
    message["Subject"] = "Feedback Form"
    part2 = MIMEText(html, "html")
    message.attach(part2)
    try:
      sendermail = MAIL
      password = MAILPASS
      gmail_server = smtplib.SMTP('smtp.gmail.com', 587)
      gmail_server.starttls(context=context)
      gmail_server.login(sendermail, password)
      message["From"] = sendermail
      message["To"] = sendermail
      gmail_server.sendmail(sendermail, sendermail, message.as_string())
      return True
    except:
      return "Verification email not sent, due to some issues."
      gmail_server.quit()

def addcookie(key, value):
  session[key] = value

def delcookies():
  session.clear()

def getcookie(key):
  try:
    if (x := session.get(key)):
      return x
    else:
      return False
  except:
    return False
```

### `templates/index.html`
```html
<!DOCTYPE html>
<html lang="en-GB">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Feedback Form</title>
  </head>
  <body>
    <h1>Feedback Form</h1>
    <form method="POST" action="/submitform">
      <input placeholder="title" name="title" autocomplete="off" required><br>
      <input type="email" placeholder="email" name="email" autocomplete="off" required><br>
      <textarea name="description" rows="4" cols="50" placeholder="description">
  </textarea>
      <button class="login-form-button">submit</button>
    </form>
  </body>
</html>
```

### `.env`
Before this code will work properly, you have to replace `[mail]` with the mail you want to receive the emails on, replace `[password]` with that mail's password, and replace `[secret_key]` with the secret key you want your Flask app to have.
```
MAIL=[mail]
MAIL_PASSWORD=[password]
SECRET_KEY=[secret_key]
```

---

## Conclusion
After putting all of this code together, you will have a fully functional feedback form!
Thanks for reading and if you want to view the code together, check it out [here](https://github.com/VulcanWM/feedback-form)!