def test_before_personalization_filter(self): def personalize(event): edc = event.data["context"] event.data["html"] = event.data["html"].replace("PHP", "Python") edc["SUBSCRIBER_SALUTATION"] = "Dear Ms. Jane Doe" provideHandler(personalize, [IBeforePersonalizationEvent]) try: receiver = { "email": "*****@*****.**", "fullname": "John Doe", "firstname": "John", "lastname": "Doe", "salutation": "Dear Mr.", # "nl_language": "de", } html = """ <h1>PHP ist toll!</h1> {{SUBSCRIBER_SALUTATION}} """ issue_data_fetcher = IIssueDataFetcher(self.newsletter.issue) issue_data = issue_data_fetcher.personalize(receiver, html) self.assertIn("Dear Ms. Jane Doe", issue_data) finally: getGlobalSiteManager().unregisterHandler( personalize, [IBeforePersonalizationEvent])
def test_placeholder_month_year(self): receiver = { "email": "*****@*****.**", "fullname": "John Doe", "firstname": "John", "lastname": "Doe", "salutation": "Dear Mr.", } html = """ <h1>Plone ist toll!</h1> {{ SUBSCRIBER_SALUTATION }} {{ month }}/{{ year }} """ now = datetime.now() effective_date = datetime(year=now.year, month=now.month, day=now.day + 2) self.newsletter.issue.effective_date = effective_date self.assertNotEqual( self.newsletter.issue.modified(), self.newsletter.issue.effective() ) issue_data_fetcher = IIssueDataFetcher(self.newsletter.issue) issue_data = issue_data_fetcher.personalize(receiver, html) self.assertIn( "{0}/{1}".format( self.newsletter.issue.effective().month(), self.newsletter.issue.effective().year(), ), issue_data, )
def test_before_personalization_filter(self): def _personalize(event): edc = event.data['context'] event.data['html'] = event.data['html'].replace('PHP', 'Python') edc['SUBSCRIBER_SALUTATION'] = 'Dear Ms. Jane Doe' provideHandler(_personalize, [IBeforePersonalizationEvent]) try: receiver = { 'email': '*****@*****.**', 'fullname': 'John Doe', 'firstname': 'John', 'lastname': 'Doe', 'salutation': 'Dear Mr.', 'nl_language': 'de' } html = ''' <h1>PHP ist toll!</h1> {{SUBSCRIBER_SALUTATION}} ''' issue_data_fetcher = IIssueDataFetcher(self.newsletter.issue) issue_data = issue_data_fetcher._personalize(receiver, html) self.assertIn('Dear Ms. Jane Doe', issue_data) finally: getGlobalSiteManager().unregisterHandler( _personalize, [IBeforePersonalizationEvent])
def test_fetching_issue_data(self): receiver = { "email": "*****@*****.**", "fullname": "John Doe", "firstname": "John", "lastname": "Doe", "salutation": "Dear Mr.", } html = """ <h1></h1> {{SUBSCRIBER_SALUTATION}} """ issue_data_fetcher = IIssueDataFetcher(self.newsletter.issue) issue_data = issue_data_fetcher.personalize(receiver, html) self.assertIn("Dear Mr. John Doe", issue_data)
def get_preview(self): """ Return the rendered HTML version with all placeholder, for admin preview. """ test_receiver = { 'email': '*****@*****.**', 'fullname': 'John Doe', 'firstname': 'John', 'lastname': 'Doe', 'salutation': 'Dear Mr.', 'nl_language': 'de', 'uid': 'xyz', } issuedatafetcher = IIssueDataFetcher(self.context) preview_html = issuedatafetcher.preview_html(disable_filter=True, receiver=test_receiver) return preview_html
def get_preview(self): """Return the rendered HTML version with all placeholder, for admin preview. """ test_receiver = { "email": "*****@*****.**", "fullname": "John Doe", "firstname": "John", "lastname": "Doe", "salutation": "Dear Mr.", "nl_language": "de", "uid": "xyz", } issuedatafetcher = IIssueDataFetcher(self.context) preview_html = issuedatafetcher.preview_html( disable_filter=True, receiver=test_receiver ) return preview_html
def get_preview(self): """ Return the rendered HTML version with all placeholder, for admin preview. """ test_receiver = { 'email': '*****@*****.**', 'fullname': 'John Doe', 'firstname': 'John', 'lastname': 'Doe', 'salutation': 'Dear Mr.', 'nl_language': 'de', 'uid': 'xyz', } issuedatafetcher = IIssueDataFetcher(self.context) preview_html = issuedatafetcher.preview_html( disable_filter=True, receiver=test_receiver) return preview_html
def test_placeholder_calendar_week(self): receiver = { "email": "*****@*****.**", "fullname": "John Doe", "firstname": "John", "lastname": "Doe", "salutation": "Dear Mr.", } html = """ <h1>Plone ist toll!</h1> {{ SUBSCRIBER_SALUTATION }} {{ calendar_week }} """ now = datetime.now() effective_date = now + timedelta(2) self.newsletter.issue.effective_date = effective_date self.assertNotEqual(self.newsletter.issue.modified(), self.newsletter.issue.effective()) issue_data_fetcher = IIssueDataFetcher(self.newsletter.issue) issue_data = issue_data_fetcher.personalize(receiver, html) self.assertIn(self.newsletter.issue.effective().strftime("%V"), issue_data)
def send(self): """Sends the newsletter, sending might be queued for async send out.""" # check for workflow current_state = api.content.get_state(obj=self.context) if not self.is_test and current_state != "sending": raise ValueError("Executed send in wrong review state!") # get hold of the parent Newsletter object# enl = self.context.get_newsletter() sender_name = self.request.get("sender_name") or enl.sender_name sender_email = self.request.get("sender_email") or enl.sender_email # get Plone email_charset # charset = get_email_charset() receivers = self._get_recipients() # determine MailHost first (build-in vs. external) delivery_service_name = "mailhost" # XXX enl.delivery_dervice if delivery_service_name == "mailhost": self.mail_host = api.portal.get_tool("MailHost") else: self.mail_host = getUtility(IMailHost, name=delivery_service_name) log.info('Using mail delivery service "%r"' % self.mail_host) send_counter = 0 send_error_counter = 0 issue_data_fetcher = IIssueDataFetcher(self.context) # get issue subject an rendered output data issue_data = issue_data_fetcher() # import pdb; pdb.set_trace() # NOQA: E702 for receiver in receivers: personalized_html = issue_data_fetcher.personalize( receiver, issue_data["body_html"]) # get plain text version personalized_plaintext = issue_data_fetcher.create_plaintext_message( personalized_html) m = Message( html=personalized_html, text=personalized_plaintext, subject=issue_data["subject"], mail_from=(sender_name, sender_email), mail_to=(receiver["fullname"], receiver["email"]), ) m.transformer.local_loader = LocalLoader() m.transform( images_inline=True, load_images=True, base_url=self.context.absolute_url(), cssutils_logging_level=logging.ERROR, ) send_status = { "successful": None, "error": None, "datetime": datetime.now(), } msg_string = "" try: msg_string = m.as_string() except Exception as e: # noqa send_status["successful"] = False send_status["error"] = e log.exception( 'Building newsletter email for "%s" failed, with error "%s"!' % (receiver["email"], e)) send_error_counter += 1 continue if "HTTPLoaderError" in msg_string: log.exception("Transform message failed: {0}".format( m.as_string())) try: self.mail_host.send(msg_string, immediate=True) send_status["successful"] = True log.info('Send newsletter to "%s"' % receiver["email"]) send_counter += 1 except Exception as e: # noqa send_status["successful"] = False send_status["error"] = e log.exception( 'Sending newsletter to "%s" failed, with error "%s"!' % (receiver["email"], e)) send_error_counter += 1 finally: receiver["status"] = send_status # Add information to annotations status_adapter = ISendStatus(self.context) if status_adapter: status_adapter.add_records(receivers) log.info( "Newsletter was sent to (%s) receivers. (%s) errors occurred!" % (send_counter, send_error_counter)) # change status only for a 'regular' send operation (not 'is_test') if not self.is_test: self.request["enlwf_guard"] = True api.content.transition(obj=self.context, transition="sending_completed") self.request["enlwf_guard"] = False self.context.setEffectiveDate(datetime.now()) self.context.reindexObject(idxs=["effective"]) msg_type = "info" additional_warning = "" if send_error_counter: msg_type = "warn" additional_warning = _( "\nPlease check the log files, for more details!") api.portal.show_message( message=_( "Newsletter was sent to ({0}) receivers. ({1}) errors occurred!{2}" .format(send_counter, send_error_counter, additional_warning)), request=self.request, type=msg_type, )
def get_public_body(self): """Return the rendered HTML version without placeholders.""" issuedatafetcher = IIssueDataFetcher(self.context) preview_html = issuedatafetcher.preview_html() return preview_html
def get_public_body(self): """ Return the rendered HTML version without placeholders. """ issuedatafetcher = IIssueDataFetcher(self.context) preview_html = issuedatafetcher.preview_html() return preview_html
def send(self, recipients=[]): """Sends the newsletter. An optional list of dicts (keys=fullname|mail) can be passed in for sending a newsletter out addresses != subscribers. """ # preparations request = self.REQUEST test = hasattr(request, 'test') current_state = api.content.get_state(obj=self) # check for workflow if not (test or recipients) and current_state != 'sending': raise ValueError('Executed send in wrong review state!') # get hold of the parent Newsletter object# enl = self.getNewsletter() # get sender name sender_name = request.get('sender_name') if not sender_name: sender_name = enl.getSenderName() # don't use Header() with a str and a charset arg, even if # it is correct this would generate a encoded header and mail # server may not support utf-8 encoded header from_header = Header(safe_unicode(sender_name)) # get sender e-mail sender_email = request.get('sender_email') if not sender_email: sender_email = enl.getSenderEmail() from_header.append(u'<%s>' % safe_unicode(sender_email)) # determine MailHost first (build-in vs. external) deliveryServiceName = enl.getDeliveryService() if deliveryServiceName == 'mailhost': mail_host = getToolByName(enl, 'MailHost') else: mail_host = getUtility(IMailHost, name=deliveryServiceName) log.info('Using mail delivery service "%r"' % mail_host) send_counter = 0 send_error_counter = 0 charset = get_email_charset() if not recipients: receivers = self._send_recipients() issue_data_fetcher = IIssueDataFetcher(self) for receiver in receivers: # get complete issue data issue_data = issue_data_fetcher(receiver) # create multipart mail outer = MIMEMultipart('alternative') outer['To'] = Header(u'<%s>' % safe_unicode(receiver['email'])) outer['From'] = from_header outer['Subject'] = issue_data['subject_header'] outer.epilogue = '' # Attach text part text_part = MIMEText(issue_data['body_plain'], 'plain', charset) # Attach html part with images html_part = MIMEMultipart('related') html_text = MIMEText(issue_data['body_html'], 'html', charset) html_part.attach(html_text) # Add images to the message for image in issue_data['images_to_attach']: html_part.attach(image) outer.attach(text_part) outer.attach(html_part) try: mail_host.send(outer.as_string()) log.info('Send newsletter to "%s"' % receiver['email']) send_counter += 1 except Exception, e: # noqa log.exception( 'Sending newsletter to "%s" failed, with error "%s"!' % (receiver['email'], e)) send_error_counter += 1
def send(self): """Sends the newsletter, sending might be queued for async send out. """ # check for workflow current_state = api.content.get_state(obj=self.context) if not self.is_test and current_state != 'sending': raise ValueError('Executed send in wrong review state!') # get hold of the parent Newsletter object# enl = self.context.get_newsletter() sender_name = self.request.get('sender_name') or enl.sender_name sender_email = self.request.get('sender_email') or enl.sender_email # get Plone email_charset # charset = get_email_charset() receivers = self._get_recipients() # determine MailHost first (build-in vs. external) delivery_service_name = 'mailhost' # XXX enl.delivery_dervice if delivery_service_name == 'mailhost': self.mail_host = api.portal.get_tool('MailHost') else: self.mail_host = getUtility(IMailHost, name=delivery_service_name) log.info('Using mail delivery service "%r"' % self.mail_host) send_counter = 0 send_error_counter = 0 issue_data_fetcher = IIssueDataFetcher(self.context) # get issue data issue_data = issue_data_fetcher() for receiver in receivers: send_status = { 'successful': None, 'error': None, 'datetime': datetime.now(), } try: personalized_html = issue_data_fetcher.personalize( receiver, issue_data['body_html'] ) # get plain text version personalized_plaintext = issue_data_fetcher.create_plaintext_message( personalized_html ) m = emails.Message( html=personalized_html, text=personalized_plaintext, subject=issue_data['subject'], mail_from=(sender_name, sender_email), mail_to=(receiver['fullname'], receiver['email']), ) m.transform( images_inline=True, base_url=self.context.absolute_url(), cssutils_logging_level=logging.ERROR, ) message_string = m.as_string() if 'HTTPLoaderError' in message_string: log.exception(u"Transform message failed: {0}".format(message_string)) try: self.mail_host.send(message_string, immediate=True) send_status['successful'] = True log.info('Send newsletter to "%s"' % receiver['email']) send_counter += 1 except Exception as e: # noqa send_status['successful'] = False send_status['error'] = e log.exception( 'Sending newsletter to "%s" failed, with error "%s"!' % (receiver['email'], e) ) send_error_counter += 1 except Exception as e: send_status['successful'] = False send_status['error'] = e log.exception( 'Sending newsletter failed, with error "{0}"!'.format(e) ) send_error_counter += 1 finally: receiver['status'] = send_status if not self.is_test: # Add information to annotations status_adapter = ISendStatus(self.context) if status_adapter: status_adapter.add_records(receivers) log.info( 'Newsletter was sent to (%s) receivers. (%s) errors occurred!' % (send_counter, send_error_counter) ) # change status only for a 'regular' send operation (not 'is_test') if not self.is_test: self.request['enlwf_guard'] = True api.content.transition(obj=self.context, transition='sending_completed') self.request['enlwf_guard'] = False self.context.setEffectiveDate(DateTime()) self.context.reindexObject(idxs=['effective']) msg_type = "info" additional_warning = "" if send_error_counter: msg_type = "warn" additional_warning = _( "\nPlease check the log files, for more details!" ) api.portal.show_message( message=_( 'Newsletter was sent to ({0}) receivers. ({1}) errors occurred!{2}'.format( send_counter, send_error_counter, additional_warning ) ), request=self.request, type=msg_type, )