def mail_review_request(review_request, from_user=None, changedesc=None,
                        close_type=None):
    # If the review request is not yet public or has been discarded, don't send
    # any mail. Relax the "discarded" rule when e-mails are sent on closing
    # review requests.
    if (not review_request.public or
        (not close_type and review_request.status == 'D')):
        return

    if not from_user:
        from_user = review_request.submitter

    summary = _ensure_unicode(review_request.summary)
    subject = "Review Request %d: %s" % (review_request.display_id,
                                         summary)
    reply_message_id = None

    if review_request.email_message_id:
        # Fancy quoted "replies"
        subject = "Re: " + subject
        reply_message_id = review_request.email_message_id
        extra_recipients = review_request.participants
    else:
        extra_recipients = None

    extra_context = {}

    if close_type:
        changedesc = review_request.changedescs.filter(public=True).latest()

    limit_recipients_to = None

    if changedesc:
        extra_context['change_text'] = changedesc.text
        extra_context['change_rich_text'] = changedesc.rich_text
        extra_context['changes'] = changedesc.fields_changed

        fields_changed = changedesc.fields_changed
        changed_field_names = set(fields_changed.keys())

        if (changed_field_names and
            changed_field_names.issubset(['target_people', 'target_groups'])):
            # If the only changes are to the target reviewers, try to send a
            # much more targeted e-mail (rather than sending it out to
            # everyone, only send it to new people).
            limit_recipients_to = set()

            if 'target_people' in changed_field_names:
                user_pks = [
                    item[2]
                    for item in fields_changed['target_people']['added']
                ]

                limit_recipients_to.update(User.objects.filter(
                    pk__in=user_pks))

            if 'target_groups' in changed_field_names:
                group_pks = [
                    item[2]
                    for item in fields_changed['target_groups']['added']
                ]

                limit_recipients_to.update(Group.objects.filter(
                    pk__in=group_pks))

    to_field, cc_field = build_recipients(from_user, review_request,
                                          extra_recipients,
                                          limit_recipients_to)

    extra_filter_kwargs = {}

    if close_type:
        signal = review_request_closed
        extra_filter_kwargs['close_type'] = close_type
    else:
        signal = review_request_published

    to_field, cc_field = filter_email_recipients_from_hooks(
        to_field, cc_field, signal, review_request=review_request,
        user=from_user, **extra_filter_kwargs)

    review_request.time_emailed = timezone.now()
    review_request.email_message_id = \
        send_review_mail(from_user, review_request, subject,
                         reply_message_id, to_field, cc_field,
                         'notifications/review_request_email.txt',
                         'notifications/review_request_email.html',
                         extra_context)
    review_request.save()
Send an e-mail representing the supplied review request.
dataset/ETHPy150Open reviewboard/reviewboard/reviewboard/notifications/email.py/mail_review_request