Spam-resistant contact form

Submitting the form now returns a 302 mailto: redirect, which should
open the user's email client with a pre-composed email. In case it
doesn't work, the example form view now renders text content where
{{ section.href }} should be mentioned as an alternative.

Of course, publishing an email address on the internet will still lead
to spam, but at least Django won't be the one sending it.
main
Jaap Joris Vens 2022-12-25 01:10:41 +01:00
rodzic 347ee7ac3b
commit 1fda2f40c1
4 zmienionych plików z 25 dodań i 23 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
from urllib.parse import quote
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.core.mail import EmailMessage
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from . import registry from . import registry
@ -112,24 +113,19 @@ class SectionForm(forms.ModelForm):
class ContactForm(forms.Form): class ContactForm(forms.Form):
sender = forms.EmailField(label=_("Your email address")) """
spam_protection = forms.CharField(label=_("Your message"), widget=forms.Textarea()) Spam-resistant contact form.
message = forms.CharField( """
label=_("Your message"), widget=forms.Textarea(), initial="Hi there!"
body = forms.CharField(
label=_("Your message"), widget=forms.Textarea(), required=False
) )
def save(self): def save(self, address):
body = self.cleaned_data.get("spam_protection") """
if len(body.split()) < 7: Return a mailto: link.
return """
spamcheck = self.cleaned_data.get("message")
if spamcheck != "Hi there!":
return
email = EmailMessage( subject = quote(settings.CONTACT_FORM_EMAIL_SUBJECT, safe="")
to=settings.DEFAULT_TO_EMAIL, body = quote(self.cleaned_data.get("body"), safe="")
body=body, return f"mailto:{address}?subject={subject}&body={body}"
subject=_("Contact form"),
headers={"Reply-To": self.cleaned_data.get("sender")},
)
email.send()

Wyświetl plik

@ -107,6 +107,7 @@ class PageView(detail.DetailView):
view = registry.get_view(section, request) view = registry.get_view(section, request)
form = view.get_form(method="post") form = view.get_form(method="post")
if form.is_valid(): if form.is_valid():
view.object = section
return view.form_valid(form) return view.form_valid(form)
section.invalid_form = form section.invalid_form = form

Wyświetl plik

@ -7,9 +7,9 @@ PROJECT_NAME = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
DEBUG = "runserver" in sys.argv DEBUG = "runserver" in sys.argv
KEYFILE = f"/tmp/{PROJECT_NAME}.secret" KEYFILE = f"/tmp/{PROJECT_NAME}.secret"
ADMINS = [("JJ Vens", "jj@rtts.eu")] ADMINS = [("Jaap Joris Vens", "jj@rtts.eu")]
DEFAULT_FROM_EMAIL = "noreply@rtts.eu" DEFAULT_FROM_EMAIL = "noreply@rtts.eu"
DEFAULT_TO_EMAIL = ["jj@rtts.eu"] CONTACT_FORM_EMAIL_SUBJECT = "Contact form"
ALLOWED_HOSTS = ["*"] ALLOWED_HOSTS = ["*"]
ROOT_URLCONF = PROJECT_NAME + ".urls" ROOT_URLCONF = PROJECT_NAME + ".urls"
WSGI_APPLICATION = PROJECT_NAME + ".wsgi.application" WSGI_APPLICATION = PROJECT_NAME + ".wsgi.application"

Wyświetl plik

@ -1,6 +1,7 @@
from cms.decorators import section_view from cms.decorators import section_view
from cms.forms import ContactForm from cms.forms import ContactForm
from cms.views import SectionFormView, SectionView from cms.views import SectionFormView, SectionView
from django.http import HttpResponse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -28,7 +29,11 @@ class Video(SectionView):
@section_view @section_view
class Contact(SectionFormView): class Contact(SectionFormView):
verbose_name = _("Contact") verbose_name = _("Contact")
fields = [] fields = ["content", "href"]
form_class = ContactForm form_class = ContactForm
success_url = "/thanks/"
template_name = "contact.html" template_name = "contact.html"
def form_valid(self, form):
response = HttpResponse(status=302)
response["Location"] = form.save(self.object.href)
return response