Proper technique for a contact form?
I have a contact form at shantiyoga.ca/contact
With the view
def contact(request):
template = 'contact.html'
form = ContactForm(request.POST or None)
if form.is_valid(): # All validation rules pass
开发者_StackOverflow社区
subject = form.cleaned_data['subject']
message = "%s\n\n%s" % (form.cleaned_data['message'], form.cleaned_data['sender'])
cc_myself = form.cleaned_data['cc_myself']
recipients = ['contact@shantiyoga.ca']
sender = form.cleaned_data['sender']
if cc_myself:
recipients.append(sender)
headers = {'Reply-To': form.cleaned_data['sender']}
from django.core.mail import send_mail
send_mail(subject,message,sender,recipients,headers)
return redirect('/thanks/')
return render_to_response(template, {'form': form, 'current':'contact'}, context_instance=RequestContext(request))
Which works fairly well. I'm not terribly sophisticated with Django and my Python skills are not quite up to snuff, so please bear with me if I step through this in a basic fashion.
I would like to clarify that there is no way for the form recipient (contact@shantiyoga.ca) to receive the contact form from the value of the email field (user entered). It will always be sent by the authenticated email in my settings.py, which at this point is my personal email?
A user fills out the contact form and hits submit, an email is sent to contact@shantiyoga.ca from my personal email, and if the user decides to cc themself, a copy of the email is sent to them, also from my personal email.
This is not ideal, should I create an email like contactform@shantiyoga.ca for my settings.py to send the email from?
Also, the headers = {'Reply-To': form.cleaned_data['sender']}
does not appear to be doing anything and I can't seem to find documentation describing its proper usage, has anyone had success using this technique?
Thank you for your time, Noah
I would like to clarify that there is no way for the form recipient (contact@shantiyoga.ca) to receive the contact form from the value of the email field (user entered). It will always be sent by the authenticated email in my settings.py, which at this point is my personal email?
You're setting the sender of the email to sender
but using EMAIL_HOST, correct? If this is the case, be careful that your SMTP account will let you send email from users other than your domain. Normally, providing you have an authenticated account on that server, you'll be able to set the From:
field to whatever you like.
So in short, this email will hit your inbox appearing to be from the sender
variable. So when you hit reply, you'll be able to email them back, which is I think what you want. However, it will be sent using the SMTP server whose authentication details you provide. There is a disconnect between being able to send email (SMTP) and being able to receive it, which I think has got you confused.
I've never tried it, but to add extra headers I believe you need to use the EmailMessage object. According to the docs, you would:
e = EmailMessage(headers={'Reply-To':...
e.send()
Be careful doing this; specifically, be careful to strip out newlines in the reply to field. I do not know if the default clean
methods would do this.
Finally, there isn't much wrong with your django/python at all. The only thing I'd say, by way of awareness, is not to use this:
return redirect('/thanks/')
but instead:
return HttpResponseRedirect(reverse('myapp.views.method',args=tuple,kwargs=dict))
This gives you the ability to not hardcode urls into your application. The reverse
method will look them up from urls.py
for you, so you can move your application around/change urls and it will still work.
Here is signature of send_mail
from django documentation:
send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None)
As you can see it does not have headers
argument.
You will need to use EmailMessage object directly.
It would also be nice to remove email-formatting from view. I would write everything something more like this:
from django.core.mail.message import EmailMessage
from django.conf import settings
class ContactsEmailMessage(EmailMessage):
def __init__(self, sender, subject, message, cc_myself):
super(ContactEmailMessage, self).__init__(
subject=subject,
body=self._get_message(self, sender, message),
from=settings.DEFAULT_FROM_EMAIL,
to=settings.CONTACT_RECIPIENTS,
headers=self._get_headers(sender),
cc=(sender, ) if cc_myself else None
)
def _format_message(self, sender, message):
return "%s\n\n%s" % (sender, message)
def _get_headers(self, sender):
return {
'reply-to': sender
}
Now you can write clean and easy to read view:
from myproject.mail.message import ContactsEmailMessage, BadHeaderError
from django.core.exceptions import SuspiciousOperation
def contact(request):
...
form = ContactForm(request.POST or None)
if form.is_valid(): # All validation rules pass
try:
message = ContactsEmailMessage(**form.cleaned_data)
message.send()
except BadHeaderError:
# django will raise this error if user will try to pass suspicious new-line
# characters to "sender" or other fields. This is safe-guard from
# header injections
raise SuspiciousOperation()
return redirect('/thanks/')
...
精彩评论