def get_email_addresses_for_group(group, review_request_id=None): """Build a list of e-mail addresses for the group. Args: group (reviewboard.reviews.models.Group): The review group to build the e-mail addresses for. Returns: list: A list of properly formatted e-mail addresses for all users in the review group. """ addresses = [] if group.mailing_list: if ',' not in group.mailing_list: # The mailing list field has only one e-mail address in it, # so we can just use that and the group's display name. addresses = [ build_email_address(full_name=group.display_name, email=group.mailing_list) ] else: # The mailing list field has multiple e-mail addresses in it. # We don't know which one should have the group's display name # attached to it, so just return their custom list as-is. addresses = group.mailing_list.split(',') if not (group.mailing_list and group.email_list_only): users_q = Q(is_active=True) local_site = group.local_site if local_site: users_q = users_q & (Q(local_site=local_site) | Q(local_site_admins=local_site)) users = group.users.filter(users_q).select_related('profile') if review_request_id: users = users.extra( select={ 'visibility': """ SELECT accounts_reviewrequestvisit.visibility FROM accounts_reviewrequestvisit WHERE accounts_reviewrequestvisit.review_request_id = %s AND accounts_reviewrequestvisit.user_id = reviews_group_users.user_id """ % review_request_id }) addresses.extend([ build_email_address_for_user(u) for u in users if (u.should_send_email() and ( not review_request_id or u.visibility != ReviewRequestVisit.MUTED)) ]) return addresses
def get_email_addresses_for_group(group, review_request_id=None): """Build a list of e-mail addresses for the group. Args: group (reviewboard.reviews.models.Group): The review group to build the e-mail addresses for. Returns: list: A list of properly formatted e-mail addresses for all users in the review group. """ addresses = [] if group.mailing_list: if ',' not in group.mailing_list: # The mailing list field has only one e-mail address in it, # so we can just use that and the group's display name. addresses = [build_email_address(full_name=group.display_name, email=group.mailing_list)] else: # The mailing list field has multiple e-mail addresses in it. # We don't know which one should have the group's display name # attached to it, so just return their custom list as-is. addresses = group.mailing_list.split(',') if not (group.mailing_list and group.email_list_only): users_q = Q(is_active=True) local_site = group.local_site if local_site: users_q = users_q & (Q(local_site=local_site) | Q(local_site_admins=local_site)) users = group.users.filter(users_q).select_related('profile') if review_request_id: users = users.extra(select={ 'visibility': """ SELECT accounts_reviewrequestvisit.visibility FROM accounts_reviewrequestvisit WHERE accounts_reviewrequestvisit.review_request_id = %s AND accounts_reviewrequestvisit.user_id = reviews_group_users.user_id """ % review_request_id }) addresses.extend([ build_email_address_for_user(u) for u in users if (u.should_send_email() and (not review_request_id or u.visibility != ReviewRequestVisit.MUTED)) ]) return addresses
def mail_new_user(user): """Send an e-mail to administrators for newly registered users. Args: user (django.contrib.auth.models.User): The user to send an e-mail about. """ current_site = Site.objects.get_current() siteconfig = SiteConfiguration.objects.get_current() domain_method = siteconfig.get("site_domain_method") subject = "New Review Board user registration for %s" % user.username from_email = build_email_address_for_user(user) context = { 'domain': current_site.domain, 'domain_method': domain_method, 'user': user, 'user_url': reverse('admin:auth_user_change', args=(user.id, )) } text_message = render_to_string('notifications/new_user_email.txt', context) html_message = render_to_string('notifications/new_user_email.html', context) message = EmailMessage(subject=subject.strip(), text_body=text_message, html_body=html_message, from_email=settings.SERVER_EMAIL, sender=settings.SERVER_EMAIL, to=[ build_email_address(full_name=admin[0], email=admin[1]) for admin in settings.ADMINS ]) try: message.send() except Exception as e: logging.error( "Error sending e-mail notification with subject '%s' on " "behalf of '%s' to admin: %s", subject.strip(), from_email, e, exc_info=1)
def mail_new_user(user): """Send an e-mail to administrators for newly registered users. Args: user (django.contrib.auth.models.User): The user to send an e-mail about. """ current_site = Site.objects.get_current() siteconfig = SiteConfiguration.objects.get_current() domain_method = siteconfig.get("site_domain_method") subject = "New Review Board user registration for %s" % user.username from_email = build_email_address_for_user(user) context = { 'domain': current_site.domain, 'domain_method': domain_method, 'user': user, 'user_url': reverse('admin:auth_user_change', args=(user.id,)) } text_message = render_to_string('notifications/new_user_email.txt', context) html_message = render_to_string('notifications/new_user_email.html', context) message = EmailMessage( subject=subject.strip(), text_body=text_message, html_body=html_message, from_email=settings.SERVER_EMAIL, sender=settings.SERVER_EMAIL, to=[ build_email_address(full_name=admin[0], email=admin[1]) for admin in settings.ADMINS ]) try: message.send() except Exception as e: logging.error("Error sending e-mail notification with subject '%s' on " "behalf of '%s' to admin: %s", subject.strip(), from_email, e, exc_info=1)
def test_build_email_address_without_full_name(self): """Testing build_email_address without full name""" self.assertEqual(build_email_address(email='*****@*****.**'), '*****@*****.**')
def test_build_email_address_with_full_name(self): """Testing build_email_address with full name""" self.assertEqual( build_email_address(email='*****@*****.**', full_name='Test User'), 'Test User <*****@*****.**>')
def send_review_mail(user, review_request, subject, in_reply_to, to_field, cc_field, text_template_name, html_template_name, context=None, extra_headers=None): """Format and send an e-mail out. Args: user (django.contrib.auth.models.User): The user who is sending the e-mail. review_request (reviewboard.reviews.models.ReviewRequest): The review request that the e-mail is about. subject (unicode): The subject of the e-mail address. in_reply_to (unicode): The e-mail message ID for threading. to_field (list): The recipients to send the e-mail to. This should be a list of :py:class:`Users <django.contrib.auth.models.User>` and :py:class:`Groups <reviewboard.reviews.models.Group>`. cc_field (list): The addresses to be CC'ed on the e-mail. This should be a list of :py:class:`Users <django.contrib.auth.models.User>` and :py:class:`Groups <reviewboard.reviews.models.Group>`. text_template_name (unicode): The name for the text e-mail template. html_template_name (unicode): The name for the HTML e-mail template. context (dict): Optional extra context to provide to the template. extra_headers (dict): Either a dict or :py:class:`~django.utils.datastructures.MultiValueDict` providing additional headers to send with the e-mail. Returns: unicode: The resulting e-mail message ID. """ current_site = Site.objects.get_current() local_site = review_request.local_site from_email = build_email_address_for_user(user) to_field = recipients_to_addresses(to_field, review_request.id) cc_field = recipients_to_addresses(cc_field, review_request.id) - to_field if not user.should_send_own_updates(): user_email = build_email_address_for_user(user) to_field.discard(user_email) cc_field.discard(user_email) if not to_field and not cc_field: # Nothing to send. return siteconfig = current_site.config.get() domain_method = siteconfig.get("site_domain_method") if not context: context = {} context['user'] = user context['domain'] = current_site.domain context['domain_method'] = domain_method context['review_request'] = review_request if review_request.local_site: context['local_site_name'] = review_request.local_site.name text_body = render_to_string(text_template_name, context) html_body = render_to_string(html_template_name, context) base_url = get_server_url(local_site=local_site) headers = MultiValueDict({ 'X-ReviewBoard-URL': [base_url], 'X-ReviewRequest-URL': [urljoin(base_url, review_request.get_absolute_url())], 'X-ReviewGroup': [ ', '.join(group.name for group in review_request.target_groups.all()) ], }) if extra_headers: if not isinstance(extra_headers, MultiValueDict): extra_headers = MultiValueDict( (key, [value]) for (key, value) in six.iteritems(extra_headers)) headers.update(extra_headers) if review_request.repository: headers['X-ReviewRequest-Repository'] = review_request.repository.name latest_diffset = review_request.get_latest_diffset() if latest_diffset: modified_files = set() for filediff in latest_diffset.files.all(): if filediff.deleted or filediff.copied or filediff.moved: modified_files.add(filediff.source_file) if filediff.is_new or filediff.copied or filediff.moved: modified_files.add(filediff.dest_file) for filename in modified_files: headers.appendlist('X-ReviewBoard-Diff-For', filename) subject = subject.strip() to_field = list(to_field) cc_field = list(cc_field) if settings.DEFAULT_FROM_EMAIL: sender = build_email_address(full_name=user.get_full_name(), email=settings.DEFAULT_FROM_EMAIL) else: sender = None message = EmailMessage(subject=subject, text_body=text_body.encode('utf-8'), html_body=html_body.encode('utf-8'), from_email=from_email, sender=sender, to=to_field, cc=cc_field, in_reply_to=in_reply_to, headers=headers) try: message.send() except Exception: logging.exception( "Error sending e-mail notification with subject " "'%s' on behalf of '%s' to '%s'", subject, from_email, ','.join(to_field + cc_field)) return message.message_id
def test_build_email_address_with_full_name(self): """Testing build_email_address with full name""" self.assertEqual(build_email_address(email='*****@*****.**', full_name='Test User'), 'Test User <*****@*****.**>')
def send_review_mail(user, review_request, subject, in_reply_to, to_field, cc_field, text_template_name, html_template_name, context=None, extra_headers=None): """Format and send an e-mail out. Args: user (django.contrib.auth.models.User): The user who is sending the e-mail. review_request (reviewboard.reviews.models.ReviewRequest): The review request that the e-mail is about. subject (unicode): The subject of the e-mail address. in_reply_to (unicode): The e-mail message ID for threading. to_field (list): The recipients to send the e-mail to. This should be a list of :py:class:`Users <django.contrib.auth.models.User>` and :py:class:`Groups <reviewboard.reviews.models.Group>`. cc_field (list): The addresses to be CC'ed on the e-mail. This should be a list of :py:class:`Users <django.contrib.auth.models.User>` and :py:class:`Groups <reviewboard.reviews.models.Group>`. text_template_name (unicode): The name for the text e-mail template. html_template_name (unicode): The name for the HTML e-mail template. context (dict): Optional extra context to provide to the template. extra_headers (dict): Either a dict or :py:class:`~django.utils.datastructures.MultiValueDict` providing additional headers to send with the e-mail. Returns: unicode: The resulting e-mail message ID. """ current_site = Site.objects.get_current() local_site = review_request.local_site from_email = build_email_address_for_user(user) to_field = recipients_to_addresses(to_field, review_request.id) cc_field = recipients_to_addresses(cc_field, review_request.id) - to_field if not user.should_send_own_updates(): user_email = build_email_address_for_user(user) to_field.discard(user_email) cc_field.discard(user_email) if not to_field and not cc_field: # Nothing to send. return siteconfig = current_site.config.get() domain_method = siteconfig.get("site_domain_method") if not context: context = {} context['user'] = user context['domain'] = current_site.domain context['domain_method'] = domain_method context['review_request'] = review_request if review_request.local_site: context['local_site_name'] = review_request.local_site.name text_body = render_to_string(text_template_name, context) html_body = render_to_string(html_template_name, context) base_url = get_server_url(local_site=local_site) headers = MultiValueDict({ 'X-ReviewBoard-URL': [base_url], 'X-ReviewRequest-URL': [urljoin(base_url, review_request.get_absolute_url())], 'X-ReviewGroup': [', '.join(group.name for group in review_request.target_groups.all())], }) if extra_headers: if not isinstance(extra_headers, MultiValueDict): extra_headers = MultiValueDict( (key, [value]) for (key, value) in six.iteritems(extra_headers) ) headers.update(extra_headers) if review_request.repository: headers['X-ReviewRequest-Repository'] = review_request.repository.name latest_diffset = review_request.get_latest_diffset() if latest_diffset: modified_files = set() for filediff in latest_diffset.files.all(): if filediff.deleted or filediff.copied or filediff.moved: modified_files.add(filediff.source_file) if filediff.is_new or filediff.copied or filediff.moved: modified_files.add(filediff.dest_file) for filename in modified_files: headers.appendlist('X-ReviewBoard-Diff-For', filename) subject = subject.strip() to_field = list(to_field) cc_field = list(cc_field) if settings.DEFAULT_FROM_EMAIL: sender = build_email_address(full_name=user.get_full_name(), email=settings.DEFAULT_FROM_EMAIL) else: sender = None message = EmailMessage(subject=subject, text_body=text_body.encode('utf-8'), html_body=html_body.encode('utf-8'), from_email=from_email, sender=sender, to=to_field, cc=cc_field, in_reply_to=in_reply_to, headers=headers) try: message.send() except Exception: logging.exception("Error sending e-mail notification with subject " "'%s' on behalf of '%s' to '%s'", subject, from_email, ','.join(to_field + cc_field)) return message.message_id