plain-support
Captcha...
Security considerations
Most support forms allow you to type in an email address. Be careful, because anybody can pretend to be anybody else at this point. Converations either need to continue over email (which confirms they have access to the email account), or include a verification step (emailing a code to the email address, for example).
1from plain.auth import get_user_model
2from plain.mail import TemplateEmail
3from plain.models.forms import ModelForm
4from plain.runtime import settings
5
6from .models import SupportFormEntry
7
8
9class SupportForm(ModelForm):
10 """
11 The form is the customization point for users.
12 So any behavior modifications should be possible here.
13 """
14
15 class Meta:
16 model = SupportFormEntry
17 fields = ["name", "email", "message"]
18
19 def __init__(self, user, form_slug, *args, **kwargs):
20 super().__init__(*args, **kwargs)
21 self.user = user # User provided directly by authed request
22 self.form_slug = form_slug
23 if self.user:
24 self.fields["email"].initial = user.email
25
26 def find_user(self):
27 # If the user isn't logged in (typical in an iframe, depending on session cookie settings),
28 # we can still try to look them up by email
29 # to associate the entry with them.
30 #
31 # Note that since they aren't logged in, this doesn't necessarily
32 # confirm that this wasn't an impersonation attempt.
33 # Subsequent conversations over email will confirm that they have access to the email.
34 email = self.cleaned_data.get("email")
35 if not email:
36 return None
37 UserModel = get_user_model()
38 try:
39 return UserModel.objects.get(email=email)
40 except UserModel.DoesNotExist:
41 return
42
43 def save(self, commit=True):
44 instance = super().save(commit=False)
45 instance.user = self.user or self.find_user()
46 instance.form_slug = self.form_slug
47 if commit:
48 instance.save()
49 return instance
50
51 def notify(self, instance):
52 """
53 Notify the support team of a new support form entry.
54
55 Sends an immediate email by default.
56 """
57 email = TemplateEmail(
58 template="support_form_entry",
59 subject=f"Support request from {instance.name}",
60 to=[settings.SUPPORT_EMAIL],
61 reply_to=[instance.email],
62 context={
63 "support_form_entry": instance,
64 },
65 )
66 email.send()