If you have a classic, static HTML site in a shared hosting service and you want to let your users reach you with a simple contact form, there is no need to install WordPress! Just upload the following Python CGI script protected by reCAPTCHA v2 into your public_html/
directory (or wherever you store your HTML files) as contact.py
.
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Simple contact form with reCAPTCHA for shared hostings.
|
|
"""
|
|
|
|
from email.message import EmailMessage
|
|
import json
|
|
import os
|
|
import urllib.parse
|
|
import urllib.request
|
|
import smtplib
|
|
import sys
|
|
|
|
SMTP_SERVER = "smtp.yoursite.com"
|
|
SMTP_PORT = 465
|
|
# SMTP credentials.
|
|
SMTP_USER = "admin@yoursite.com"
|
|
SMTP_PASSWORD = "your-password-123"
|
|
# Where to send the messages.
|
|
SMTP_RECIPIENT = "admin@yoursite.com"
|
|
|
|
# Your reCAPTCHA keys. Make sure to change these in production.
|
|
# Use the following keys in localhost.
|
|
PUBLIC_KEY = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
|
|
SECRET_KEY = "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"
|
|
|
|
# Change this as needed.
|
|
FORM_HTML_CODE = """\
|
|
<form method="post">
|
|
<label for="name">Name</label>:<br /><input name="name" type="text" /><br />
|
|
<label for="email">Email</label>:<br /><input name="email" type="email" /><br />
|
|
<label for="message">Message</label>:<br /><textarea name="message"></textarea><br />
|
|
<div class="g-recaptcha" data-sitekey="{public_key}"></div><br />
|
|
<button type="submit">Submit</button>
|
|
</form>\
|
|
"""
|
|
|
|
def send_email(user_name, user_email, user_message):
|
|
email = EmailMessage()
|
|
email["From"] = SMTP_USER
|
|
email["To"] = SMTP_RECIPIENT
|
|
email["Subject"] = "Contact Form"
|
|
email.set_content(
|
|
f"Name: {user_name}\nEmail: {user_email}\n\n{user_message}"
|
|
)
|
|
smtp = smtplib.SMTP_SSL(SMTP_SERVER, port=SMTP_PORT)
|
|
# Or if TLS is used:
|
|
# smtp = SMTP("smtp.example.com", port=587)
|
|
# smtp.starttls()
|
|
# If you want to use other email providers, see
|
|
# https://pythonassets.com/categories/smtp/
|
|
smtp.login(SMTP_USER, SMTP_PASSWORD)
|
|
smtp.sendmail(SMTP_USER, SMTP_RECIPIENT, email.as_string())
|
|
smtp.quit()
|
|
|
|
|
|
def body():
|
|
if os.getenv("REQUEST_METHOD") == "GET":
|
|
# Display the form.
|
|
print(FORM_HTML_CODE.format(public_key=PUBLIC_KEY))
|
|
else:
|
|
# Validate input and send email.
|
|
form_input = dict(urllib.parse.parse_qsl(sys.stdin.read()))
|
|
required_fields = ("name", "email", "message", "g-recaptcha-response")
|
|
for field in required_fields:
|
|
if field not in form_input:
|
|
print("All fields are required.")
|
|
return
|
|
# Verify reCAPTCHA.
|
|
data = urllib.parse.urlencode({
|
|
"secret": SECRET_KEY,
|
|
"response": form_input["g-recaptcha-response"],
|
|
"remote-ip": os.getenv("REMOTE_ADDR")
|
|
})
|
|
req = urllib.request.Request(
|
|
"https://www.google.com/recaptcha/api/siteverify",
|
|
data.encode(),
|
|
method="POST"
|
|
)
|
|
resp = urllib.request.urlopen(req)
|
|
success = json.load(resp)["success"]
|
|
if not success:
|
|
print("Captcha failed. Try again.")
|
|
return
|
|
send_email(
|
|
form_input["name"],
|
|
form_input["email"],
|
|
form_input["message"]
|
|
)
|
|
print("Message sent! We'll be in touch soon!")
|
|
|
|
|
|
def main():
|
|
# Headers.
|
|
print("Content-Type: text/html")
|
|
# This new line is required and part of the headers.
|
|
print()
|
|
# HTML code.
|
|
print("""\
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Contact Form</title>
|
|
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
|
|
<script src='https://www.google.com/recaptcha/api.js?v=6'></script>
|
|
</head>
|
|
<body>
|
|
<h3>Contact Form</h3>\
|
|
""")
|
|
body()
|
|
print("</body></html>")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
Of course, you might want to throw some CSS into that form. Before uploading, make sure to change the SMTP_*
constants and your reCAPTCHA's PUBLIC_KEY
and SECRET_KEY
(lines 15-26) accordingly.
Google has currently three supported versions for reCAPTCHA: v2, v3 and Enterprise. This form works with reCAPTCHA v2, for which you can generate a couple of keys from https://www.google.com/recaptcha/admin.
You might want to test the script in localhost before uploading it to your production site. If so, use the following test server:
from http.server import CGIHTTPRequestHandler, HTTPServer
class Handler(CGIHTTPRequestHandler):
cgi_directories = ["/"]
httpd = HTTPServer(("", 8000), Handler)
httpd.serve_forever()
This will execute CGI scripts within the current working directory. Save the code as cgiserver.py
and run:
Then visit http://localhost:8000/contact.py and try the form out. You still need to configure the SMTP_*
constants when running in development, although you might keep reCAPTCHA's test keys.
After uploading contact.py
to your shared hosting, if you get a 500 Internal Server Error, ensure that:
The contact.py
file is executable in the hosting machine. Using a FTP client, change permissions to 755
or run chmod 755 contact.py
via SSH.
Line endings are LF
instead of CR
(macOS) or CRLF
(Windows) in contact.py
(you can change these in your code editor), since your script probably runs on a Linux distribution.
If you still have problems, you might want to take a look at the errors.log
file or run ./contact.py
within a SSH session to see what happens.