bgneal@51: """
bgneal@51: Forms for the email_list application.
bgneal@51: 
bgneal@51: """
bgneal@51: from django import forms
bgneal@51: from django.conf import settings
bgneal@51: from django.core.urlresolvers import reverse
bgneal@53: from django.core.mail import send_mail, send_mass_mail
bgneal@51: from django.template.loader import render_to_string
bgneal@51: 
bgneal@51: from email_list.models import Subscriber
bgneal@51: 
bgneal@51: 
bgneal@51: SUBSCRIBE_OPTS = [('sub', 'Subscribe'), ('unsub', 'Unsubscribe')]
bgneal@51: 
bgneal@51: ALREADY_SUBSCRIBED = "This email address is already subscribed."
bgneal@51: NOT_SUBSCRIBED = "This email address is not on our list."
bgneal@51: 
bgneal@51: 
bgneal@51: class SubscriberForm(forms.Form):
bgneal@101:     name = forms.CharField(required=False,
bgneal@101:             widget=forms.TextInput(attrs={
bgneal@101:                     'class': 'form-control',
bgneal@101:                     'placeholder': 'Your name (optional)'}))
bgneal@101:     email = forms.EmailField(widget=forms.TextInput(attrs={
bgneal@101:                     'class': 'form-control',
bgneal@101:                     'type': 'email',
bgneal@101:                     'placeholder': 'Your email address'}))
bgneal@101:     location = forms.CharField(required=False,
bgneal@101:             widget=forms.TextInput(attrs={
bgneal@101:                      'class': 'form-control',
bgneal@101:                      'placeholder': 'City, State (optional)'}))
bgneal@101:     option = forms.ChoiceField(choices=SUBSCRIBE_OPTS,
bgneal@101:             widget=forms.Select(attrs={'class': 'form-control'}))
bgneal@51: 
bgneal@51:     def clean(self):
bgneal@51:         """
bgneal@51:         This method ensures the appropriate action can be carried out and raises
bgneal@51:         a validation error if not.
bgneal@51: 
bgneal@51:         """
bgneal@101:         cleaned_data = super(SubscriberForm, self).clean()
bgneal@101:         email = cleaned_data.get('email')
bgneal@101:         option = cleaned_data.get('option')
bgneal@51: 
bgneal@101:         if not email or not option:
bgneal@101:             return cleaned_data
bgneal@101: 
bgneal@101:         if option == 'sub':
bgneal@51:             # is the user already subscribed (active)?
bgneal@51:             try:
bgneal@51:                 subscriber = Subscriber.objects.get(email=email)
bgneal@51:             except Subscriber.DoesNotExist:
bgneal@51:                 subscriber = Subscriber(email=email,
bgneal@101:                         name=cleaned_data['name'],
bgneal@101:                         location=cleaned_data['location'])
bgneal@51:             else:
bgneal@51:                 if subscriber.is_active():
bgneal@51:                     raise forms.ValidationError(ALREADY_SUBSCRIBED)
bgneal@51:         else:
bgneal@51:             # is the user already unsubscribed or not subscribed?
bgneal@51:             try:
bgneal@51:                 subscriber = Subscriber.objects.get(email=email)
bgneal@51:             except Subscriber.DoesNotExist:
bgneal@51:                 raise forms.ValidationError(NOT_SUBSCRIBED)
bgneal@51: 
bgneal@51:         # save the subscriber away for a future process() call
bgneal@51:         self.subscriber = subscriber
bgneal@51: 
bgneal@101:         return cleaned_data
bgneal@51: 
bgneal@51:     def is_subscribe(self):
bgneal@51:         """
bgneal@51:         This function can be called after an is_valid() call to determine if the
bgneal@51:         request was for a subscribe or unsubscribe.
bgneal@51: 
bgneal@51:         """
bgneal@51:         return self.cleaned_data['option'] == 'sub'
bgneal@51: 
bgneal@51:     def process(self):
bgneal@51:         """
bgneal@51:         Call this function if is_valid() returns True. It carries out the user's
bgneal@101:         subscription request.
bgneal@51: 
bgneal@51:         """
bgneal@51:         if self.is_subscribe():
bgneal@51:             self.subscriber.set_pending()
bgneal@51:         else:
bgneal@51:             self.subscriber.set_leaving()
bgneal@51: 
bgneal@51:         self.subscriber.save()
bgneal@51:         send_email(self.subscriber)
bgneal@51: 
bgneal@51: 
bgneal@53: class AdminEmailForm(forms.Form):
bgneal@53:     subject = forms.CharField(max_length=255, required=True, label='Subject:',
bgneal@53:         widget=forms.TextInput(attrs={'class': 'vTextField required',
bgneal@53:             'size': '120'}))
bgneal@53:     message = forms.CharField(label='Message:',
bgneal@53:         widget=forms.Textarea(attrs={'class': 'vLargeTextField required'}))
bgneal@53: 
bgneal@53:     def __init__(self, *args, **kwargs):
bgneal@53:         initial = kwargs.pop('initial', {})
bgneal@53:         if 'subject' not in initial:
bgneal@53:             initial['subject'] = '[%s] ' % settings.BAND_CONFIG['BAND_NAME']
bgneal@53:             kwargs['initial'] = initial
bgneal@53: 
bgneal@53:         super(AdminEmailForm, self).__init__(*args, **kwargs)
bgneal@53: 
bgneal@53:     def save(self):
bgneal@53:         """
bgneal@53:         Call this function if is_valid() to send the mass email.
bgneal@53:         Returns the number of mails sent.
bgneal@53: 
bgneal@53:         """
bgneal@53:         subject = self.cleaned_data['subject']
bgneal@53:         message = self.cleaned_data['message']
bgneal@53:         return send_mail_to_subscribers(subject, message)
bgneal@53: 
bgneal@53: 
bgneal@51: def send_email(subscriber):
bgneal@51:     """
bgneal@51:     This function sends out the appropriate email for the given subscriber.
bgneal@51: 
bgneal@51:     """
bgneal@51:     config = settings.BAND_CONFIG
bgneal@51:     band = config['BAND_NAME']
bgneal@51:     from_email = config['BAND_EMAIL']
bgneal@51: 
bgneal@51:     url = "http://%s%s" % (config['BAND_DOMAIN'],
bgneal@51:             reverse('email_list-confirm', kwargs={'key': subscriber.key}))
bgneal@51: 
bgneal@51:     if subscriber.is_pending():
bgneal@51:         email_template = 'email_list/email_subscribe.txt'
bgneal@51:     else:
bgneal@51:         email_template = 'email_list/email_unsubscribe.txt'
bgneal@51: 
bgneal@51:     msg = render_to_string(email_template, {
bgneal@101:         'band': band,
bgneal@101:         'url': url,
bgneal@51:         'band_domain': config['BAND_DOMAIN'],
bgneal@51:         })
bgneal@51: 
bgneal@51:     subject = "[%s] Mailing List Confirmation" % band
bgneal@51: 
bgneal@51:     send_mail(subject, msg, from_email, [subscriber.email])
bgneal@53: 
bgneal@53: 
bgneal@53: def send_mail_to_subscribers(subject, message):
bgneal@53:     """
bgneal@53:     Send an email to each mailing list subscriber with the given subject and
bgneal@53:     message.
bgneal@53:     Returns the number of messages sent.
bgneal@53: 
bgneal@53:     """
bgneal@53:     config = settings.BAND_CONFIG
bgneal@53:     unsubscribe_url = "http://%s%s" % (config['BAND_DOMAIN'],
bgneal@53:               reverse('email_list-main'))
bgneal@53: 
bgneal@53:     msg = render_to_string('email_list/mailing_list.txt', {
bgneal@53:         'band': config['BAND_NAME'],
bgneal@53:         'unsubscribe_url': unsubscribe_url,
bgneal@53:         'message': message,
bgneal@53:         })
bgneal@53: 
bgneal@53:     mail_data = [(subject, msg, config['BAND_EMAIL'], [subscriber]) for
bgneal@53:             subscriber in Subscriber.objects.values_list('email', flat=True)]
bgneal@53: 
bgneal@53:     send_mass_mail(mail_data)
bgneal@53:     return len(mail_data)