开发者

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/')
    ...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜