diff --git a/mails/forms.py b/mails/forms.py index 9e8b9fbeb840877dbb04aaf6a869e715396e8cf7..a034d1a7573f8c52fe8ef83a26aa57914fe7077f 100644 --- a/mails/forms.py +++ b/mails/forms.py @@ -17,6 +17,7 @@ class EmailTemplateForm(forms.Form): def __init__(self, *args, **kwargs): self.mail_code = kwargs.pop('mail_code') + self.mail_fields = None super().__init__(*args) # Gather data @@ -27,19 +28,25 @@ class EmailTemplateForm(forms.Form): self.mail_data = json.loads(open(json_location).read()) # Object - self.object = kwargs.get(self.mail_data.get('context_object')) - recipient = self.object - for attr in self.mail_data.get('to_address').split('.'): - recipient = getattr(recipient, attr) - if inspect.ismethod(recipient): - recipient = recipient() - self.recipient = recipient + self.object = kwargs.get(self.mail_data.get('context_object', ''), None) + self.recipient = None + if self.object: + recipient = self.object + for attr in self.mail_data.get('to_address').split('.'): + recipient = getattr(recipient, attr) + if inspect.ismethod(recipient): + recipient = recipient() + self.recipient = recipient + + if not self.recipient: + self.fields['extra_recipient'].label = "Send this email to" + self.fields['extra_recipient'].required = True # Set the data as initials self.fields['text'].initial = self.mail_template self.fields['subject'].initial = self.mail_data['subject'] - def send(self): + def save_data(self): # Get text and html message = self.cleaned_data['text'] html_template = loader.get_template('email/general.html') @@ -47,7 +54,7 @@ class EmailTemplateForm(forms.Form): # Get recipients list. Try to send through BCC to prevent privacy issues! bcc_list = [] - if self.mail_data.get('bcc_to'): + if self.mail_data.get('bcc_to') and self.object: bcc_to = self.object for attr in self.mail_data.get('bcc_to').split('.'): bcc_to = getattr(bcc_to, attr) @@ -57,8 +64,12 @@ class EmailTemplateForm(forms.Form): else: bcc_list = bcc_to - if self.cleaned_data.get('extra_recipient'): + if self.cleaned_data.get('extra_recipient') and self.recipient: bcc_list.append(self.cleaned_data.get('extra_recipient')) + elif self.cleaned_data.get('extra_recipient') and not self.recipient: + self.recipient = [self.cleaned_data.get('extra_recipient')] + elif not self.recipient: + self.add_error('extra_recipient', 'Please fill the bcc field to send the mail.') # Check the send list if isinstance(self.recipient, list): @@ -82,14 +93,28 @@ class EmailTemplateForm(forms.Form): elif isinstance(recipient, str): _recipients.append(recipient) + self.mail_fields = { + 'subject': self.cleaned_data['subject'], + 'message': message, + 'html_message': html_message, + 'recipients': _recipients, + 'bcc_list': bcc_list, + } + + def clean(self): + data = super().clean() + self.save_data() + return data + + def send(self): # Send the mail email = EmailMultiAlternatives( - self.cleaned_data['subject'], - message, + self.mail_fields['subject'], + self.mail_fields['message'], '%s <%s>' % (self.mail_data.get('from_address_name', 'SciPost'), self.mail_data.get('from_address', 'no-reply@scipost.org')), # From - _recipients, # To - bcc=bcc_list, + self.mail_fields['recipients'], # To + bcc=self.mail_fields['bcc_list'], reply_to=[self.mail_data.get('from_address', 'no-reply@scipost.org')]) - email.attach_alternative(html_message, 'text/html') + email.attach_alternative(self.mail_fields['html_message'], 'text/html') email.send(fail_silently=False) diff --git a/mails/templates/mail_templates/partners_followup_mail.json b/mails/templates/mail_templates/partners_followup_mail.json new file mode 100644 index 0000000000000000000000000000000000000000..efb95bbc8882bb10b321d44ed84cb72bcede49a0 --- /dev/null +++ b/mails/templates/mail_templates/partners_followup_mail.json @@ -0,0 +1,7 @@ +{ + "subject": "SciPost: Supporting Partners Board", + "to_address": "email", + "from_address_name": "SciPost Supporting Partners", + "from_address": "partners@scipost.org", + "context_object": "contact" +} diff --git a/mails/templates/mail_templates/partners_followup_mail.txt b/mails/templates/mail_templates/partners_followup_mail.txt new file mode 100644 index 0000000000000000000000000000000000000000..136e2d33581487b6d14af5c99648f52eb3bc06a0 --- /dev/null +++ b/mails/templates/mail_templates/partners_followup_mail.txt @@ -0,0 +1,17 @@ +Dear {{ contact.get_title_display }} {{ contact.last_name }}, + +Recently we contacted you about the SciPost Supporting Partners Board. We would like to know if you and your institution are interested in joining the Supporting Partners Board. + +It is greatly appreciated if you could take a few minutes to read through this document and let us know whether your institution would consider joining. + +It would be a privilege to welcome you as members of our Supporting Partners Board. Support takes the form of a small financial commitment, collectively pooled to enable SciPost to perform all its publication-related activities, maintain its online portal and implement its long-term development plan. + +Your support at this time is crucially required to make our initiative sustainable, and to help make it possible for the community to reap all the benefits deriving form its viable implementation. + +I will be happy to provide any required further details. If you are interested, you can simply get in touch via this address (partners@scipost.org). I sincerely hope that SciPost will be able to count on your support. + +If you not the right person in your organization to contact about this topic, please let us know. + +On behalf of the SciPost Foundation, +Prof. dr Jean-Sébastien Caux +J.S.Caux@uva.nl diff --git a/mails/templates/mail_templates/partners_initial_mail.json b/mails/templates/mail_templates/partners_initial_mail.json new file mode 100644 index 0000000000000000000000000000000000000000..efb95bbc8882bb10b321d44ed84cb72bcede49a0 --- /dev/null +++ b/mails/templates/mail_templates/partners_initial_mail.json @@ -0,0 +1,7 @@ +{ + "subject": "SciPost: Supporting Partners Board", + "to_address": "email", + "from_address_name": "SciPost Supporting Partners", + "from_address": "partners@scipost.org", + "context_object": "contact" +} diff --git a/mails/templates/mail_templates/partners_initial_mail.txt b/mails/templates/mail_templates/partners_initial_mail.txt new file mode 100644 index 0000000000000000000000000000000000000000..739744c472126c31c27bc3de64d89b93bfa1a8c6 --- /dev/null +++ b/mails/templates/mail_templates/partners_initial_mail.txt @@ -0,0 +1,31 @@ +Dear {{ contact.get_title_display }} {{ contact.last_name }}, + +You might by now have heard of SciPost, a recently-launched initiative aiming to bring disruptive change to current academic publishing practices. + +In summary, SciPost is a publication portal managed by professional scientists, offering (among others) high-quality Open Access journals with innovative forms of refereeing, and a means of commenting on all existing literature. SciPost is established as a not-for-profit foundation devoted to serving the interests of the international scientific community. +The site is anchored at https://scipost.org. Many further details about SciPost, its principles, ideals and implementation can be found at https://scipost.org/about and https://scipost.org/FAQ. + +Crucially, as explained on our Partners page at https://scipost.org/partners, SciPost follows a completely different funding model than traditional publishers, and provides a cost-slashing alternative to existing platforms. SciPost charges neither subscription fees, nor article processing charges; its activities are instead to be collectively financed through a Supporting Partners Board, formed by a worldwide consortium of institutions and organizations which directly or indirectly benefit from SciPost’s activities. + +Support takes the form of a small financial commitment, collectively pooled to enable SciPost to perform all its publication-related activities, maintain its online portal and implement its long-term development plan. + +In the agreement template, which you can find online at https://scipost.org/static/scipost/SPB/SciPost_Supporting_Partner_Agreement.pdf, you will find many more specific details about our operations, requirements and funding strategy. I would greatly appreciate if you took a few minutes to read through this document. + +It would be a privilege to welcome you as members of our Supporting Partners Board. I am hereby contacting you to enquire whether your institution would consider joining. Your support at this time is crucially required to make our initiative sustainable, and to help make it possible for the community to reap all the benefits deriving form its viable implementation. + +I will be happy to provide any required further details. If you are interested, you can simply get in touch via this address (partners@scipost.org). I sincerely hope that SciPost will be able to count on your support. + +On behalf of the SciPost Foundation, +Prof. dr Jean-Sébastien Caux +J.S.Caux@uva.nl +http://jscaux.org +--------------------------------------------- +Institute for Theoretical Physics +University of Amsterdam +Science Park 904 +1098 XH Amsterdam +The Netherlands +--------------------------------------------- +tel.: +31 (0)20 5255775 +fax: +31 (0)20 5255778 +--------------------------------------------- diff --git a/mails/views.py b/mails/views.py index 04dce36dd4b9f3166e16b80893443a590158d338..f7fedc01ded99d81c6f90b0d33f17e8489024ca9 100644 --- a/mails/views.py +++ b/mails/views.py @@ -10,6 +10,10 @@ class MailEditingSubView(object): self.template_name = kwargs.get('template', 'mails/mail_form.html') self.mail_form = EmailTemplateForm(request.POST or None, mail_code=mail_code, **kwargs) + @property + def recipients_string(self): + return ', '.join(getattr(self.mail_form, 'mail_fields', {}).get('recipients', [''])) + def is_valid(self): return self.mail_form.is_valid() diff --git a/partners/forms.py b/partners/forms.py index 87322b2d67118443949252cdcdfd3d7e6c3d8faf..18a2df7814561a220e886717e019b8b1279a8866 100644 --- a/partners/forms.py +++ b/partners/forms.py @@ -458,26 +458,6 @@ class ProspectiveContactForm(forms.ModelForm): widgets = {'prospartner': forms.HiddenInput()} -class EmailProspectivePartnerContactForm(forms.Form): - email_subject = forms.CharField(widget=forms.Textarea(), - initial='Supporting Partners Board') - message = forms.CharField(widget=forms.Textarea(), required=False) - include_SPB_summary = forms.BooleanField( - required=False, initial=True, - label='include SPB summary with message') - - def __init__(self, *args, **kwargs): - super(EmailProspectivePartnerContactForm, self).__init__(*args, **kwargs) - self.fields['email_subject'].widget.attrs.update( - {'rows': 1}) - self.fields['message'].widget.attrs.update( - {'placeholder': 'Write your message in this box (optional).'}) - - -class EmailProspectivePartnerGenericForm(EmailProspectivePartnerContactForm): - email = forms.EmailField(label='Generic address for emailing') - - class ProspectivePartnerEventForm(forms.ModelForm): class Meta: model = ProspectivePartnerEvent diff --git a/partners/templates/partners/_prospective_partner_card.html b/partners/templates/partners/_prospective_partner_card.html index 28f587665c6f72da23ad1600889cd8ff2c17065e..5ab2d85a1d11e9292d97d516f9fac472b24f7288 100644 --- a/partners/templates/partners/_prospective_partner_card.html +++ b/partners/templates/partners/_prospective_partner_card.html @@ -15,7 +15,10 @@ <p>{{ pp.get_status_display }}</p> </div> <div class="col-md-7"> - <a href="{% url 'partners:email_prospartner_generic' prospartner_id=pp.id %}">Compose email to a generic address</a> + <ul> + <li><a href="{% url 'partners:email_prospartner_generic' prospartner_id=pp.id %}">Compose email to a generic address</a></li> + <li><a href="{% url 'partners:email_prospartner_generic' prospartner_id=pp.id mail='followup' %}">Compose follow-up email to a generic address</a></li> + </ul> <h3>Contacts:</h3> <a class="d-inline-block mb-2" href="{% url 'partners:add_prospartner_contact' prospartner_id=pp.id %}">Add a contact</a> <table class="table"> @@ -31,7 +34,12 @@ <td>{{ contact.role }}</td> <td>{{ contact.get_title_display }} {{ contact.first_name }} {{ contact.last_name }}</td> <td>{{ contact.email }}</td> - <td><a href="{% url 'partners:email_prospartner_contact' contact_id=contact.id %}">Compose email</a></td> + <td> + <ul> + <li><a href="{% url 'partners:email_prospartner_contact' contact_id=contact.id %}">Compose email</a> + <li><a href="{% url 'partners:email_prospartner_contact' contact_id=contact.id mail='followup' %}">Compose follow-up email</a> + </ul> + </td> </tr> {% empty %} <tr> diff --git a/partners/urls.py b/partners/urls.py index f376c8de27594f1f53fa970b3d4b201c62518d90..b7d4e86380e830a36c026b713008e9b3349a29cb 100644 --- a/partners/urls.py +++ b/partners/urls.py @@ -13,6 +13,8 @@ urlpatterns = [ name='add_prospective_partner'), url(r'^prospects/contacts/(?P<contact_id>[0-9]+)/email$', views.email_prospartner_contact, name='email_prospartner_contact'), + url(r'^prospects/contacts/(?P<contact_id>[0-9]+)/email/(?P<mail>followup)$', + views.email_prospartner_contact, name='email_prospartner_contact'), url(r'^prospects/(?P<prospartner_id>[0-9]+)/contacts/add$', views.add_prospartner_contact, name='add_prospartner_contact'), @@ -20,6 +22,8 @@ urlpatterns = [ views.promote_prospartner, name='promote_prospartner'), url(r'^prospects/(?P<prospartner_id>[0-9]+)/email_generic', views.email_prospartner_generic, name='email_prospartner_generic'), + url(r'^prospects/(?P<prospartner_id>[0-9]+)/email_generic/(?P<mail>followup)', + views.email_prospartner_generic, name='email_prospartner_generic'), url(r'^prospects/(?P<prospartner_id>[0-9]+)/events/add$', views.add_prospartner_event, name='add_prospartner_event'), diff --git a/partners/views.py b/partners/views.py index 1a94818df5390b13a87b613425656fcfd2f2b4be..0acab83ef34b1bc6fcc097ad37f0c589cb0e87f9 100644 --- a/partners/views.py +++ b/partners/views.py @@ -10,6 +10,8 @@ from django.utils import timezone from guardian.decorators import permission_required +from mails.views import MailEditingSubView + from .constants import PROSPECTIVE_PARTNER_REQUESTED,\ PROSPECTIVE_PARTNER_APPROACHED, PROSPECTIVE_PARTNER_ADDED,\ PROSPECTIVE_PARTNER_EVENT_REQUESTED, PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT @@ -17,13 +19,12 @@ from .models import Partner, ProspectivePartner, ProspectiveContact, ContactRequ ProspectivePartnerEvent, MembershipAgreement, Contact, Institution,\ PartnersAttachment from .forms import ProspectivePartnerForm, ProspectiveContactForm,\ - EmailProspectivePartnerContactForm, PromoteToPartnerForm,\ + PromoteToPartnerForm,\ ProspectivePartnerEventForm, MembershipQueryForm,\ PartnerForm, ContactForm, ContactFormset, ContactModelFormset,\ NewContactForm, InstitutionForm, ActivationForm, PartnerEventForm,\ MembershipAgreementForm, RequestContactForm, RequestContactFormSet,\ - ProcessRequestContactForm, PartnersAttachmentFormSet, PartnersAttachmentForm,\ - EmailProspectivePartnerGenericForm + ProcessRequestContactForm, PartnersAttachmentFormSet, PartnersAttachmentForm from .utils import PartnerUtils @@ -261,10 +262,15 @@ def add_prospartner_contact(request, prospartner_id): @permission_required('scipost.can_email_prospartner_contact', return_403=True) @transaction.atomic -def email_prospartner_contact(request, contact_id): +def email_prospartner_contact(request, contact_id, mail=None): contact = get_object_or_404(ProspectiveContact, pk=contact_id) - form = EmailProspectivePartnerContactForm(request.POST or None) - if form.is_valid(): + + if mail == 'followup': + code = 'partners_followup_mail' + else: + code = 'partners_initial_mail' + mail_request = MailEditingSubView(request, mail_code=code, contact=contact) + if mail_request.is_valid(): comments = 'Email sent to %s.' % str(contact) prospartnerevent = ProspectivePartnerEvent( prospartner=contact.prospartner, @@ -277,25 +283,26 @@ def email_prospartner_contact(request, contact_id): PROSPECTIVE_PARTNER_ADDED]: contact.prospartner.status = PROSPECTIVE_PARTNER_APPROACHED contact.prospartner.save() - PartnerUtils.load({'contact': contact, - 'email_subject': form.cleaned_data['email_subject'], - 'message': form.cleaned_data['message'], - 'include_SPB_summary': form.cleaned_data['include_SPB_summary']}) - PartnerUtils.email_prospartner_contact() - messages.success(request, 'Email successfully sent') + messages.success(request, 'Email successfully sent.') + mail_request.send() return redirect(reverse('partners:dashboard')) - context = {'contact': contact, 'form': form} - return render(request, 'partners/email_prospartner_contact.html', context) + else: + return mail_request.return_render() @permission_required('scipost.can_email_prospartner_contact', return_403=True) @transaction.atomic -def email_prospartner_generic(request, prospartner_id): +def email_prospartner_generic(request, prospartner_id, mail=None): prospartner = get_object_or_404(ProspectivePartner, pk=prospartner_id) - form = EmailProspectivePartnerGenericForm(request.POST or None) - if form.is_valid(): - comments = 'Email sent to %s.' % form.cleaned_data['email'] + + if mail == 'followup': + code = 'partners_followup_mail' + else: + code = 'partners_initial_mail' + mail_request = MailEditingSubView(request, mail_code=code) + if mail_request.is_valid(): + comments = 'Email sent to %s.' % str(mail_request.recipients_string) prospartnerevent = ProspectivePartnerEvent( prospartner=prospartner, event=PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT, @@ -307,17 +314,12 @@ def email_prospartner_generic(request, prospartner_id): PROSPECTIVE_PARTNER_ADDED]: prospartner.status = PROSPECTIVE_PARTNER_APPROACHED prospartner.save() - PartnerUtils.load({'institution_name': prospartner.institution_name, - 'email': form.cleaned_data['email'], - 'email_subject': form.cleaned_data['email_subject'], - 'message': form.cleaned_data['message'], - 'include_SPB_summary': form.cleaned_data['include_SPB_summary']}) - - PartnerUtils.email_prospartner_generic() - messages.success(request, 'Email successfully sent') + + messages.success(request, 'Email successfully sent.') + mail_request.send() return redirect(reverse('partners:dashboard')) - context = {'prospartner': prospartner, 'form': form} - return render(request, 'partners/email_prospartner_generic.html', context) + else: + return mail_request.return_render() @permission_required('scipost.can_manage_SPB', return_403=True)