import logging import django from django import forms from django.conf import settings from django.contrib.sites.models import Site from django.utils.encoding import force_bytes from django.utils.translation import gettext_lazy as _ from django_contact_form.forms import ContactForm from django_recaptcha.fields import ReCaptchaField from django_recaptcha.widgets import ReCaptchaV3 from pykismet3 import Akismet, AkismetServerError logger = logging.getLogger(__name__) class BaseContactForm(ContactForm): message_subject = forms.CharField( max_length=100, widget=forms.TextInput(attrs={"class": "required"}), label=_("Message subject"), ) email = forms.EmailField( widget=forms.TextInput(attrs={"class": "required"}), label=_("E-mail"), ) name = forms.CharField( widget=forms.TextInput(attrs={"class": "required"}), label=_("Name"), ) body = forms.CharField( widget=forms.Textarea(attrs={"class": "required"}), label=_("Your message"), ) captcha = ReCaptchaField(widget=ReCaptchaV3) def subject(self): # Strip all linebreaks from the subject string. subject = "".join(self.cleaned_data["message_subject"].splitlines()) return "[Contact form] " + subject def message(self): return "From: {name} <{email}>\n\n{body}".format(**self.cleaned_data) def clean_body(self): """ Check spam against Akismet. Backported from django-contact-form pre-1.0; 1.0 dropped built-in Akismet support. """ if "body" in self.cleaned_data and getattr(settings, "AKISMET_API_KEY", None): try: akismet_api = Akismet( api_key=settings.AKISMET_API_KEY, blog_url="http://%s/" % Site.objects.get_current().domain, user_agent="Django {}.{}.{}".format(*django.VERSION), ) akismet_data = { "user_ip": self.request.META.get("REMOTE_ADDR", ""), "user_agent": self.request.headers.get("user-agent", ""), "referrer": self.request.headers.get("referer", ""), "comment_content": force_bytes(self.cleaned_data["body"]), "comment_author": self.cleaned_data.get("name", ""), "comment_author_email": self.cleaned_data.get("email", ""), "comment_type": "contact-form", } if getattr(settings, "AKISMET_TESTING", None): # Adding test argument to the request in order to # tell akismet that they should ignore the request # so that test runs affect the heuristics akismet_data["is_test"] = 1 if akismet_api.check(akismet_data): raise forms.ValidationError("Akismet thinks this message is spam") except AkismetServerError: logger.error("Akismet server error") return self.cleaned_data["body"] class FoundationContactForm(BaseContactForm): recipient_list = ["dsf-board@googlegroups.com"]