def send_email_preview_accepted(course_run): """ Send email for preview approved to publisher and project coordinator. Arguments: course_run (Object): CourseRun object """ txt_template = 'publisher/email/course_run/preview_accepted.txt' html_template = 'publisher/email/course_run/preview_accepted.html' course = course_run.course publisher_user = course.publisher try: if is_email_notification_enabled(publisher_user): course_key = CourseKey.from_string(course_run.lms_course_id) subject = _('Publication requested: {course_name} {run_number}').format( # pylint: disable=no-member course_name=course.title, run_number=course_key.run) project_coordinator = course.project_coordinator to_addresses = [publisher_user.email] if is_email_notification_enabled(project_coordinator): to_addresses.append(project_coordinator.email) from_address = settings.PUBLISHER_FROM_EMAIL page_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course_run.id}) course_page_path = reverse('publisher:publisher_course_detail', kwargs={'pk': course_run.course.id}) context = { 'course_name': course.title, 'run_number': course_key.run, 'publisher_role_name': PublisherUserRole.Publisher, 'course_team': course.course_team_admin, 'org_name': course.organizations.all().first().name, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=page_path ), 'course_page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=course_page_path ) } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives( subject, plain_content, from_address, to=[from_address], bcc=to_addresses ) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except message = 'Failed to send email notifications for preview approved of course-run [{id}].'.format( id=course_run.id ) logger.exception(message) raise Exception(message)
def send_email_preview_accepted(course_run): """ Send email for preview approved to publisher and project coordinator. Arguments: course_run (Object): CourseRun object """ txt_template = 'publisher/email/course_run/preview_accepted.txt' html_template = 'publisher/email/course_run/preview_accepted.html' run_name = '{pacing_type}: {start_date}'.format( pacing_type=course_run.get_pacing_type_display(), start_date=course_run.start.strftime("%B %d, %Y")) subject = _('Preview for {run_name} has been approved').format( run_name=run_name) # pylint: disable=no-member publisher_user = course_run.course.publisher try: if is_email_notification_enabled(publisher_user): project_coordinator = course_run.course.project_coordinator to_addresses = [publisher_user.email] if is_email_notification_enabled(project_coordinator): to_addresses.append(project_coordinator.email) from_address = settings.PUBLISHER_FROM_EMAIL page_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course_run.id}) context = { 'course_name': run_name, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=page_path) } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to=[from_address], bcc=to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except message = 'Failed to send email notifications for preview approved of course-run [{id}].'.format( id=course_run.id) logger.exception(message) raise Exception(message)
def test_is_email_notification_enabled(self): """ Test email notification enabled/disabled for the user.""" user_attribute = factories.UserAttributeFactory(user=self.user) # Verify email notifications are enabled for user with associated attributes, # but no explicit value set for the enable_email_notification attribute assert is_email_notification_enabled(self.user) is True # Disabled email notification user_attribute.enable_email_notification = False user_attribute.save() # Verify that email notifications are disabled for the user assert is_email_notification_enabled(self.user) is False
def test_is_email_notification_enabled(self): """ Test email notification enabled/disabled for the user.""" user_attribute = factories.UserAttributeFactory(user=self.user) # Verify email notifications are enabled for user with associated attributes, # but no explicit value set for the enable_email_notification attribute self.assertEqual(is_email_notification_enabled(self.user), True) # Disabled email notification user_attribute.enable_email_notification = False user_attribute.save() # pylint: disable=no-member # Verify that email notifications are disabled for the user self.assertEqual(is_email_notification_enabled(self.user), False)
def test_is_email_notification_enabled(self): """ Test email notification enabled/disabled for the user.""" user_attribute = factories.UserAttributeFactory(user=self.user) # Verify email notifications are enabled for user with associated attributes, # but no explicit value set for the enable_email_notification attribute self.assertEqual(is_email_notification_enabled(self.user), True) # Disabled email notification user_attribute.enable_email_notification = False user_attribute.save() # pylint: disable=no-member # Verify that email notifications are disabled for the user self.assertEqual(is_email_notification_enabled(self.user), False)
def test_email_notification_enabled_by_default(self): """ Test email notification is enabled for the user by default.""" self.assertFalse(hasattr(self.user, 'attributes')) # Verify email notifications are enabled for user without associated attributes self.assertEqual(is_email_notification_enabled(self.user), True)
def test_email_notification_enabled_by_default(self): """ Test email notification is enabled for the user by default.""" assert not hasattr(self.user, 'attributes') # Verify email notifications are enabled for user without associated attributes assert is_email_notification_enabled(self.user) is True
def test_email_notification_enabled_by_default(self): """ Test email notification is enabled for the user by default.""" self.assertFalse(hasattr(self.user, 'attributes')) # Verify email notifications are enabled for user without associated attributes self.assertEqual(is_email_notification_enabled(self.user), True)
def publisher(request): return { 'is_email_notification_enabled': is_email_notification_enabled(request.user), 'publisher_url': publisher_url(request.user), }
def test_publisher(self): request = RequestFactory().get('/') request.user = UserFactory() self.assertDictEqual( publisher(request), { 'is_email_notification_enabled': is_email_notification_enabled(request.user) })
def send_email_preview_page_is_available(course_run, site): """ Send email for course preview available to course team. Arguments: course_run (Object): CourseRun object site (Site): Current site """ txt_template = 'publisher/email/course_run/preview_available.txt' html_template = 'publisher/email/course_run/preview_available.html' course_team_user = course_run.course.course_team_admin try: if is_email_notification_enabled(course_team_user): course_key = CourseKey.from_string(course_run.lms_course_id) subject = _( 'Review requested: Preview for {course_name} {run_number}' ).format( # pylint: disable=no-member course_name=course_run.course.title, run_number=course_key.run) to_addresses = [course_team_user.email] from_address = settings.PUBLISHER_FROM_EMAIL project_coordinator = course_run.course.project_coordinator context = { 'sender_role': PublisherUserRole.Publisher, 'recipient_name': course_team_user.get_full_name() or course_team_user.username, 'course_run': course_run, 'course_run_key': course_key, 'course_run_publisher_url': 'https://{host}{path}'.format( host=site.domain.strip('/'), path=course_run.get_absolute_url()), 'contact_us_email': project_coordinator.email if project_coordinator else '', 'platform_name': settings.PLATFORM_NAME } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to=to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except error_message = 'Failed to send email notifications for preview available of course-run {run_id}'.format( run_id=course_run.id) logger.exception(error_message) raise Exception(error_message)
def test_publisher(self): """ Validate that publisher context processor returns expected result. """ request = RequestFactory().get('/') request.user = UserFactory() self.assertDictEqual( publisher(request), { 'is_email_notification_enabled': is_email_notification_enabled(request.user) })
def send_email_decline_preview(comment, course_run, preview_url): """ Send the emails for a comment for decline preview. Arguments: comment (Comment): Comment object course_run (CourseRun): course-run object preview_url (url): preview_url """ try: object_path = reverse('publisher:publisher_course_run_detail', args=[course_run.id]) course_key = CourseKey.from_string(course_run.lms_course_id) course_name = '{title} {run_number}'.format( title=course_run.course.title, run_number=course_key.run) # Translators: subject_desc will be Preview Decline for course run, # 'title' will be the value of course title. subject = _('Preview declined: {course_name}').format( # pylint: disable=no-member course_name=course_name) recipient_user = course_run.course.publisher if is_email_notification_enabled(recipient_user): to_addresses = [recipient_user.email] from_address = settings.PUBLISHER_FROM_EMAIL context = { 'comment': comment, 'team_name': 'course team', 'page_url': 'https://{host}{path}'.format( host=comment.site.domain.strip('/'), path=object_path), 'preview_url': preview_url, 'course_name': course_name, 'recipient_name': recipient_user.get_full_name() or recipient_user.username } txt_template = 'publisher/email/decline_preview.txt' html_template = 'publisher/email/decline_preview.html' template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except message = 'Failed to send email notifications for preview decline for course run [{id}].'.format( id=course_run.id) log.exception(message) raise Exception(message)
def get_group_users_emails(self): """ Returns the list of users emails with enable email notifications against a course group. By default if attribute value does not exists then user will be eligible for emails. """ users_list = get_users_with_perms(self) emails = [user.email for user in users_list if is_email_notification_enabled(user)] return emails
def send_email_for_course_creation(course, course_run, site): """ Send the emails for a course creation. Arguments: course (Course): Course object course_run (CourseRun): CourseRun object site (Site): Current site """ txt_template = 'publisher/email/course_created.txt' html_template = 'publisher/email/course_created.html' subject = _('Studio URL requested: {title}').format(title=course.title) # pylint: disable=no-member project_coordinator = course.project_coordinator course_team = course.course_team_admin if is_email_notification_enabled(project_coordinator): try: to_addresses = [project_coordinator.email] from_address = settings.PUBLISHER_FROM_EMAIL context = { 'course_title': course.title, 'date': course_run.created.strftime("%B %d, %Y"), 'time': course_run.created.strftime("%H:%M:%S"), 'course_team_name': course_team.get_full_name(), 'project_coordinator_name': project_coordinator.get_full_name(), 'dashboard_url': 'https://{host}{path}'.format( host=site.domain.strip('/'), path=reverse('publisher:publisher_dashboard')), 'from_address': from_address, 'contact_us_email': project_coordinator.email } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to=to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except logger.exception( 'Failed to send email notifications for creation of course [%s]', course_run.course.id)
def get_course_users_emails(self): """ Returns the list of users emails with enable email notifications against a course. By default if attribute value does not exists then user will be eligible for emails. """ users_list_roles = [obj.user for obj in self.course_user_roles.all()] user_emails = [user.email for user in users_list_roles if is_email_notification_enabled(user)] return user_emails
def test_publisher(self): """ Validate that publisher context processor returns expected result. """ request = RequestFactory().get('/') request.user = UserFactory() expected = { 'is_email_notification_enabled': is_email_notification_enabled(request.user), 'is_on_new_pub_fe': False, 'publisher_url': None } self.assertDictEqual(publisher(request), expected)
def send_email_to_publisher(course_run, user): """ Send email to publisher when course-run is marked as reviewed. Arguments: course_run (Object): CourseRun object user (Object): User object """ txt_template = 'publisher/email/course_run/mark_as_reviewed.txt' html_template = 'publisher/email/course_run/mark_as_reviewed.html' course_key = CourseKey.from_string(course_run.lms_course_id) subject = _('Review complete: {course_name} {run_number}').format( # pylint: disable=no-member course_name=course_run.course.title, run_number=course_key.run ) recipient_user = course_run.course.publisher user_role = course_run.course.course_user_roles.get(user=user) sender_team = 'course team' if user_role.role == PublisherUserRole.MarketingReviewer: sender_team = 'marketing team' try: if is_email_notification_enabled(recipient_user): project_coordinator = course_run.course.project_coordinator to_addresses = [recipient_user.email] from_address = settings.PUBLISHER_FROM_EMAIL page_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course_run.id}) context = { 'recipient_name': recipient_user.full_name or recipient_user.username if recipient_user else '', 'sender_name': user.full_name or user.username, 'course_name': course_run.course.title, 'run_number': course_key.run, 'org_name': course_run.course.organizations.all().first().name, 'sender_team': sender_team, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=page_path ) } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives( subject, plain_content, from_address, to_addresses ) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except logger.exception('Failed to send email notifications for mark as reviewed of course-run %s', course_run.id)
def send_course_run_published_email(course_run): """ Send email when course run is published by publisher. Arguments: course_run (Object): CourseRun object """ txt_template = 'publisher/email/course_run/published.txt' html_template = 'publisher/email/course_run/published.html' course_team_user = course_run.course.course_team_admin try: if is_email_notification_enabled(course_team_user): course_key = CourseKey.from_string(course_run.lms_course_id) subject = _('Publication complete: About page for {course_name} {run_number}').format( # pylint: disable=no-member course_name=course_run.course.title, run_number=course_key.run ) to_addresses = [course_team_user.email] from_address = settings.PUBLISHER_FROM_EMAIL project_coordinator = course_run.course.project_coordinator page_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course_run.id}) course_page_path = reverse('publisher:publisher_course_detail', kwargs={'pk': course_run.course.id}) context = { 'sender_role': PublisherUserRole.Publisher, 'course_name': course_run.course.title, 'preview_url': course_run.preview_url, 'course_run_number': course_key.run, 'recipient_name': course_team_user.get_full_name() or course_team_user.username, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=page_path ), 'course_page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=course_page_path ), 'platform_name': settings.PLATFORM_NAME, } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives( subject, plain_content, from_address, to=to_addresses ) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except error_message = 'Failed to send email notifications for course published of course-run [{run_id}]'.format( run_id=course_run.id ) logger.exception(error_message) raise Exception(error_message)
def get_group_users_emails(self): """ Returns the list of users emails with enable email notifications against a course group. By default if attribute value does not exists then user will be eligible for emails. """ users_list = get_users_with_perms(self) emails = [ user.email for user in users_list if is_email_notification_enabled(user) ] return emails
def send_email_to_publisher(course_run, user): """ Send email to publisher when course-run is marked as reviewed. Arguments: course_run (Object): CourseRun object user (Object): User object """ txt_template = 'publisher/email/course_run/mark_as_reviewed.txt' html_template = 'publisher/email/course_run/mark_as_reviewed.html' run_name = '{pacing_type}: {start_date}'.format( pacing_type=course_run.get_pacing_type_display(), start_date=course_run.start.strftime("%B %d, %Y")) subject = _('Changes to {run_name} has been marked as reviewed').format( run_name=run_name) # pylint: disable=no-member recipient_user = course_run.course.publisher try: if is_email_notification_enabled(recipient_user): project_coordinator = course_run.course.project_coordinator to_addresses = [recipient_user.email] from_address = settings.PUBLISHER_FROM_EMAIL page_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course_run.id}) context = { 'recipient_name': recipient_user.full_name or recipient_user.username if recipient_user else '', 'sender_name': user.full_name or user.username, 'course_name': run_name, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=page_path) } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send() except Exception: # pylint: disable=broad-except logger.exception( 'Failed to send email notifications for mark as reviewed of course-run %s', course_run.id)
def send_course_workflow_email(course, user, subject, txt_template, html_template, page_path, course_name=None): """ Send email for course workflow state change. Arguments: course (Object): Course object user (Object): User object subject (String): Email subject txt_template: (String): Email text template path html_template: (String): Email html template path page_path: (URL): Detail page url course_name: (String): Custom course name, by default None """ recipient_user = course.marketing_reviewer user_role = course.course_user_roles.get(user=user) if user_role.role == PublisherUserRole.MarketingReviewer: recipient_user = course.course_team_admin if is_email_notification_enabled(recipient_user): project_coordinator = course.project_coordinator to_addresses = [recipient_user.email] from_address = settings.PUBLISHER_FROM_EMAIL context = { 'recipient_name': recipient_user.full_name or recipient_user.username if recipient_user else '', 'sender_name': user.full_name or user.username, 'course_name': course_name if course_name else course.title, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'page_url': 'https://{host}{path}'.format( host=Site.objects.get_current().domain.strip('/'), path=page_path) } template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send()
def send_course_workflow_email(course, user, subject, txt_template, html_template, context, recipient_user, site): """ Send email for course workflow state change. Arguments: course (Object): Course object user (Object): User object subject (String): Email subject txt_template: (String): Email text template path html_template: (String): Email html template path context: (Dict): Email template context recipient_user: (Object): User object site (Site): Current site """ if is_email_notification_enabled(recipient_user): project_coordinator = course.project_coordinator to_addresses = [recipient_user.email] from_address = settings.PUBLISHER_FROM_EMAIL course_page_path = reverse('publisher:publisher_course_detail', kwargs={'pk': course.id}) context.update({ 'recipient_name': recipient_user.full_name or recipient_user.username if recipient_user else '', 'sender_name': user.full_name or user.username, 'org_name': course.organizations.all().first().name, 'contact_us_email': project_coordinator.email if project_coordinator else '', 'course_page_url': 'https://{host}{path}'.format(host=site.domain.strip('/'), path=course_page_path) }) template = get_template(txt_template) plain_content = template.render(context) template = get_template(html_template) html_content = template.render(context) email_msg = EmailMultiAlternatives(subject, plain_content, from_address, to_addresses) email_msg.attach_alternative(html_content, 'text/html') email_msg.send()
def send_email(template_name, subject, to_users, recipient_name, course_run=None, course=None, context=None, project_coordinator=None): """ Send an email template out to the given users with some standard context variables. Arguments: template_name (str): path to template without filename extension subject (str): subject line for the email to_users (list(Object)): a list of User objects to send the email to, if they have notifications enabled recipient_name (str): a string to use to greet the user (use a team name if multiple users) course_run (Object): CourseRun object course (Object): Course object context (dict): additional context for the template project_coordinator (Object): optional optimization if you have the PC User already, to prevent a lookup """ course = course or course_run.course partner = course.partner org = course.authoring_organizations.first() project_coordinator = project_coordinator or get_project_coordinator(org) if not project_coordinator: log_missing_project_coordinator(course.key, org, template_name) return publisher_url = partner.publisher_url if not publisher_url: logger.info( _('Not sending notification email for template {template} because no publisher URL is defined ' 'for partner {partner}').format(template=template_name, partner=partner.short_code)) return studio_url = partner.studio_url if not studio_url: logger.info( _('Not sending notification email for template {template} because no studio URL is defined ' 'for partner {partner}').format(template=template_name, partner=partner.short_code)) return base_context = {} if course_run: run_studio_url = urljoin(studio_url, 'course/{}'.format(course_run.key)) review_url = urljoin(publisher_url, 'courses/{}'.format(course.uuid)) base_context.update({ 'course_name': course_run.title, 'course_key': course_run.key, 'course_run_number': CourseKey.from_string(course_run.key).run, 'recipient_name': recipient_name, 'platform_name': settings.PLATFORM_NAME, 'org_name': org.name, 'contact_us_email': project_coordinator.email, 'course_page_url': review_url, 'studio_url': run_studio_url, 'preview_url': course_run.marketing_url, }) elif course: base_context.update({ 'course_name': course.title, 'course_key': course.key, 'recipient_name': recipient_name, 'platform_name': settings.PLATFORM_NAME, 'org_name': org.name, 'contact_us_email': project_coordinator.email, }) if context: base_context.update(context) txt_template = template_name + '.txt' html_template = template_name + '.html' template = get_template(txt_template) plain_content = template.render(base_context) template = get_template(html_template) html_content = template.render(base_context) to_addresses = [ u.email for u in to_users if is_email_notification_enabled(u) ] if not to_addresses: return email_msg = EmailMultiAlternatives(subject, plain_content, settings.PUBLISHER_FROM_EMAIL, to_addresses) email_msg.attach_alternative(html_content, 'text/html') try: email_msg.send() except Exception: # pylint: disable=broad-except logger.exception( 'Failed to send email notification for template %s, with subject "%s"', template_name, subject)
def publisher(request): return {"is_email_notification_enabled": is_email_notification_enabled(request.user)}
def test_publisher(self): request = RequestFactory().get('/') request.user = UserFactory() self.assertDictEqual( publisher(request), {'is_email_notification_enabled': is_email_notification_enabled(request.user)} )