Ejemplo n.º 1
0
    def test_recipients_to_addresses_with_groups_with_members(self):
        """Testing generating addresses from recipients that are groups with
        no mailing list addresses
        """
        group1 = Group.objects.create(name='group1')
        group2 = Group.objects.create(name='group2')

        user1 = User.objects.create_user(username='******',
                                         first_name='User',
                                         last_name='One',
                                         email='*****@*****.**')
        user2 = User.objects.create_user(username='******',
                                         first_name='User',
                                         last_name='Two',
                                         email='*****@*****.**')

        group1.users = [user1]
        group2.users = [user2]

        addresses = recipients_to_addresses([group1, group2])

        expected_addresses = set([
            build_email_address_for_user(user1),
            build_email_address_for_user(user2),
        ])

        self.assertEqual(addresses, expected_addresses)
Ejemplo n.º 2
0
    def test_recipients_to_addresses_with_groups_with_members(self):
        """Testing generating addresses from recipients that are groups with
        no mailing list addresses
        """
        group1 = Group.objects.create(name='group1')
        group2 = Group.objects.create(name='group2')

        user1 = User.objects.create_user(username='******', first_name='User',
                                         last_name='One',
                                         email='*****@*****.**')
        user2 = User.objects.create_user(username='******', first_name='User',
                                         last_name='Two',
                                         email='*****@*****.**')

        group1.users = [user1]
        group2.users = [user2]

        addresses = recipients_to_addresses([group1, group2])

        expected_addresses = set([
            build_email_address_for_user(user1),
            build_email_address_for_user(user2),
        ])

        self.assertEqual(addresses, expected_addresses)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    def test_review_request_published_email_hook(self):
        """Testing ReviewRequestPublishedEmailHook"""
        class DummyHook(ReviewRequestPublishedEmailHook):
            def get_to_field(self, to_field, review_request, user):
                return set([user])

            def get_cc_field(self, cc_field, review_request, user):
                return set([user])

        hook = DummyHook(self.extension)

        self.spy_on(hook.get_to_field)
        self.spy_on(hook.get_cc_field)

        review_request = self.create_review_request()
        admin = User.objects.get(username='******')

        call_kwargs = {
            'user': admin,
            'review_request': review_request,
        }

        with self.siteconfig_settings({'mail_send_review_mail': True}):
            review_request.publish(admin)

        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].to,
                         [build_email_address_for_user(admin)])
        self.assertTrue(hook.get_to_field.called)
        self.assertTrue(hook.get_to_field.called_with(**call_kwargs))
        self.assertTrue(hook.get_cc_field.called)
        self.assertTrue(hook.get_cc_field.called_with(**call_kwargs))
Ejemplo n.º 5
0
    def test_recipients_to_addresses_groups_local_site_inactive_members(self):
        """Testing generating addresses from recipients that are groups in
        local sites that have inactive members
        """
        local_site1 = LocalSite.objects.create(name='local-site1')
        local_site2 = LocalSite.objects.create(name='local-site2')

        group1 = self.create_review_group('group1', local_site=local_site1)
        group2 = self.create_review_group('group2', local_site=local_site2)

        user1 = User.objects.create_user(username='******',
                                         first_name='User',
                                         last_name='One',
                                         email='*****@*****.**')
        user2 = User.objects.create(username='******',
                                    first_name='User',
                                    last_name='Two',
                                    is_active=False,
                                    email='*****@*****.**')

        local_site1.users = [user1]
        local_site2.users = [user2]

        group1.users = [user1]
        group2.users = [user2]

        addresses = recipients_to_addresses([group1, group2])
        self.assertEqual(len(addresses), 1)
        self.assertEqual(addresses, set([build_email_address_for_user(user1)]))
Ejemplo n.º 6
0
    def test_recipients_to_addresses_groups_local_site_inactive_members(self):
        """Testing generating addresses from recipients that are groups in
        local sites that have inactive members
        """
        local_site1 = LocalSite.objects.create(name='local-site1')
        local_site2 = LocalSite.objects.create(name='local-site2')

        group1 = self.create_review_group('group1', local_site=local_site1)
        group2 = self.create_review_group('group2', local_site=local_site2)

        user1 = User.objects.create_user(username='******', first_name='User',
                                         last_name='One',
                                         email='*****@*****.**')
        user2 = User.objects.create(username='******', first_name='User',
                                    last_name='Two', is_active=False,
                                    email='*****@*****.**')

        local_site1.users = [user1]
        local_site2.users = [user2]

        group1.users = [user1]
        group2.users = [user2]

        addresses = recipients_to_addresses([group1, group2])
        self.assertEqual(len(addresses), 1)
        self.assertEqual(addresses, set([build_email_address_for_user(user1)]))
Ejemplo n.º 7
0
    def test_recipients_to_addresses_with_groups_and_users(self):
        """Testing generating addresses from recipients that are users and
        groups with mailing list addresses
        """
        groups = [
            Group(name='group1', display_name='Group One',
                  mailing_list='*****@*****.**'),
            Group(name='group2', display_name='Group Two',
                  mailing_list='*****@*****.**'),
        ]

        users = list(User.objects.filter(username__in=['doc', 'grumpy']).all())

        addresses = recipients_to_addresses(groups + users)
        self.assertEqual(len(addresses), 4)

        user_addresses = [
            build_email_address_for_user(u)
            for u in users
        ]

        group_addresses = sum(
            (
                get_email_addresses_for_group(group)
                for group in groups
            ),
            [])

        self.assertEqual(addresses,
                         set(user_addresses + group_addresses))
Ejemplo n.º 8
0
    def test_build_email_address_for_user(self):
        """Testing build_email_address_for_user"""
        user = User.objects.create(username='******',
                                   first_name='Test',
                                   last_name='User',
                                   email='*****@*****.**')

        self.assertEqual(build_email_address_for_user(user),
                         'Test User <*****@*****.**>')
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
    def test_build_email_address_for_user(self):
        """Testing build_email_address_for_user"""
        user = User.objects.create(username='******',
                                   first_name='Test',
                                   last_name='User',
                                   email='*****@*****.**')

        self.assertEqual(build_email_address_for_user(user),
                         'Test User <*****@*****.**>')
Ejemplo n.º 11
0
    def test_recipients_to_addresses_with_users(self):
        """Testing generating addresses from recipients with user recipients
        """
        users = list(User.objects.filter(username__in=['doc', 'grumpy']))

        addresses = recipients_to_addresses(users)
        self.assertEqual(len(addresses), 2)

        expected_addresses = set(
            build_email_address_for_user(u) for u in users)

        self.assertEqual(addresses, expected_addresses)
Ejemplo n.º 12
0
    def test_recipients_to_addresses_with_users(self):
        """Testing generating addresses from recipients with user recipients
        """
        users = list(User.objects.filter(username__in=['doc', 'grumpy']))

        addresses = recipients_to_addresses(users)
        self.assertEqual(len(addresses), 2)

        expected_addresses = set(
            build_email_address_for_user(u)
            for u in users
        )

        self.assertEqual(addresses, expected_addresses)
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
    def test_recipients_to_addresses_with_groups_inactive_members(self):
        """Testing generating addresses form recipients that are groups with
        inactive members
        """
        group1 = self.create_review_group('group1')
        group2 = self.create_review_group('group2')

        user1 = User.objects.create_user(username='******', first_name='User',
                                         last_name='One',
                                         email='*****@*****.**')
        user2 = User.objects.create(username='******', first_name='User',
                                    last_name='Two', is_active=False,
                                    email='*****@*****.**')

        group1.users = [user1]
        group2.users = [user2]

        addresses = recipients_to_addresses([group1, group2])
        self.assertEqual(len(addresses), 1)
        self.assertEqual(addresses, set([build_email_address_for_user(user1)]))
Ejemplo n.º 16
0
def recipients_to_addresses(recipients, review_request_id=None):
    """Return the set of e-mail addresses for the recipients.

    Args:
        recipients (list):
            A list of :py:class:`Users <django.contrib.auth.models.User>` and
            :py:class:`Groups <reviewboard.reviews.models.Group>`.

    Returns:
        set: The e-mail addresses for all recipients.
    """
    addresses = set()

    for recipient in recipients:
        assert isinstance(recipient, User) or isinstance(recipient, Group)

        if isinstance(recipient, User):
            addresses.add(build_email_address_for_user(recipient))
        else:
            addresses.update(get_email_addresses_for_group(recipient,
                                                           review_request_id))

    return addresses
Ejemplo n.º 17
0
    def test_recipients_to_addresses_with_groups_inactive_members(self):
        """Testing generating addresses form recipients that are groups with
        inactive members
        """
        group1 = self.create_review_group('group1')
        group2 = self.create_review_group('group2')

        user1 = User.objects.create_user(username='******',
                                         first_name='User',
                                         last_name='One',
                                         email='*****@*****.**')
        user2 = User.objects.create(username='******',
                                    first_name='User',
                                    last_name='Two',
                                    is_active=False,
                                    email='*****@*****.**')

        group1.users = [user1]
        group2.users = [user2]

        addresses = recipients_to_addresses([group1, group2])
        self.assertEqual(len(addresses), 1)
        self.assertEqual(addresses, set([build_email_address_for_user(user1)]))
Ejemplo n.º 18
0
def recipients_to_addresses(recipients, review_request_id=None):
    """Return the set of e-mail addresses for the recipients.

    Args:
        recipients (list):
            A list of :py:class:`Users <django.contrib.auth.models.User>` and
            :py:class:`Groups <reviewboard.reviews.models.Group>`.

    Returns:
        set: The e-mail addresses for all recipients.
    """
    addresses = set()

    for recipient in recipients:
        assert isinstance(recipient, User) or isinstance(recipient, Group)

        if isinstance(recipient, User):
            addresses.add(build_email_address_for_user(recipient))
        else:
            addresses.update(
                get_email_addresses_for_group(recipient, review_request_id))

    return addresses
Ejemplo n.º 19
0
def mail_password_changed(user):
    """Send an e-mail when a user's password changes.

    Args:
        user (django.contrib.auth.model.User):
            The user whose password changed.
    """
    api_token_url = ('%s#api-tokens' %
                     build_server_url(reverse('user-preferences')))
    server_url = get_server_url()

    context = {
        'api_token_url': api_token_url,
        'has_api_tokens': user.webapi_tokens.exists(),
        'server_url': server_url,
        'user': user,
    }

    user_email = build_email_address_for_user(user)
    text_body = render_to_string('notifications/password_changed.txt', context)
    html_body = render_to_string('notifications/password_changed.html',
                                 context)

    message = EmailMessage(
        subject='Password changed for user "%s" on %s' % server_url,
        text_body=text_body,
        html_body=html_body,
        from_email=settings.SERVER_EMAIL,
        sender=settings.SERVER_EMAIL,
        to=user_email,
    )

    try:
        message.send()
    except Exception as e:
        logging.exception('Failed to send password changed email to %s: %s',
                          user.username, e)
Ejemplo n.º 20
0
    def test_recipients_to_addresses_with_groups_and_users(self):
        """Testing generating addresses from recipients that are users and
        groups with mailing list addresses
        """
        groups = [
            Group(name='group1',
                  display_name='Group One',
                  mailing_list='*****@*****.**'),
            Group(name='group2',
                  display_name='Group Two',
                  mailing_list='*****@*****.**'),
        ]

        users = list(User.objects.filter(username__in=['doc', 'grumpy']).all())

        addresses = recipients_to_addresses(groups + users)
        self.assertEqual(len(addresses), 4)

        user_addresses = [build_email_address_for_user(u) for u in users]

        group_addresses = sum(
            (get_email_addresses_for_group(group) for group in groups), [])

        self.assertEqual(addresses, set(user_addresses + group_addresses))
Ejemplo n.º 21
0
def mail_webapi_token(webapi_token, op):
    """Send an e-mail about an API token update.

    This will inform the user about a newly-created, updated, or deleted
    token.

    Args:
        webapi_token (reviewboard.webapi.models.WebAPIToken):
            The API token the e-mail is about.

        op (unicode):
            The operation the email is about. This is one of
            ``created``, ``updated``, or ``deleted``.

    Raises:
        ValueError:
            The provided ``op`` argument was invalid.
    """
    if op == 'created':
        subject = 'New Review Board API token created'
        template_name = 'notifications/api_token_created'
    elif op == 'updated':
        subject = 'Review Board API token updated'
        template_name = 'notifications/api_token_updated'
    elif op == 'deleted':
        subject = 'Review Board API token deleted'
        template_name = 'notifications/api_token_deleted'
    else:
        raise ValueError('Unexpected op "%s" passed to mail_webapi_token.' %
                         op)

    current_site = Site.objects.get_current()
    siteconfig = SiteConfiguration.objects.get_current()
    domain_method = siteconfig.get('site_domain_method')
    user = webapi_token.user
    user_email = build_email_address_for_user(user)

    context = {
        'api_token': webapi_token,
        'domain': current_site.domain,
        'domain_method': domain_method,
        'partial_token': '%s...' % webapi_token.token[:10],
        'user': user,
    }

    text_message = render_to_string('%s.txt' % template_name, context)
    html_message = render_to_string('%s.html' % template_name, context)

    message = EmailMessage(subject=subject,
                           text_body=text_message,
                           html_body=html_message,
                           from_email=settings.SERVER_EMAIL,
                           sender=settings.SERVER_EMAIL,
                           to=[user_email])

    try:
        message.send()
    except Exception as e:
        logging.exception(
            "Error sending API Token e-mail with subject '%s' "
            "from '%s' to '%s': %s", subject, settings.SERVER_EMAIL,
            user_email, e)
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
def mail_webapi_token(webapi_token, op):
    """Send an e-mail about an API token update.

    This will inform the user about a newly-created, updated, or deleted
    token.

    Args:
        webapi_token (reviewboard.webapi.models.WebAPIToken):
            The API token the e-mail is about.

        op (unicode):
            The operation the email is about. This is one of
            ``created``, ``updated``, or ``deleted``.

    Raises:
        ValueError:
            The provided ``op`` argument was invalid.
    """
    if op == 'created':
        subject = 'New Review Board API token created'
        template_name = 'notifications/api_token_created'
    elif op == 'updated':
        subject = 'Review Board API token updated'
        template_name = 'notifications/api_token_updated'
    elif op == 'deleted':
        subject = 'Review Board API token deleted'
        template_name = 'notifications/api_token_deleted'
    else:
        raise ValueError('Unexpected op "%s" passed to mail_webapi_token.'
                         % op)

    current_site = Site.objects.get_current()
    siteconfig = SiteConfiguration.objects.get_current()
    domain_method = siteconfig.get('site_domain_method')
    user = webapi_token.user
    user_email = build_email_address_for_user(user)

    context = {
        'api_token': webapi_token,
        'domain': current_site.domain,
        'domain_method': domain_method,
        'partial_token': '%s...' % webapi_token.token[:10],
        'user': user,
    }

    text_message = render_to_string('%s.txt' % template_name, context)
    html_message = render_to_string('%s.html' % template_name, context)

    message = EmailMessage(
        subject=subject,
        text_body=text_message,
        html_body=html_message,
        from_email=settings.SERVER_EMAIL,
        sender=settings.SERVER_EMAIL,
        to=[user_email])

    try:
        message.send()
    except Exception as e:
        logging.exception("Error sending API Token e-mail with subject '%s' "
                          "from '%s' to '%s': %s",
                          subject, settings.SERVER_EMAIL, user_email, e)