# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

"""Task handlers for email notifications of issue changes.

Email notificatons are sent when an issue changes, an issue that is blocking
another issue changes, or a bulk edit is done.  The users notified include
the project-wide mailing list, issue owners, cc'd users, starrers,
also-notify addresses, and users who have saved queries with email notification
set.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import json
import logging
import os

import ezt

from google.appengine.api import mail
from google.appengine.runtime import apiproxy_errors

import settings
from features import autolink
from features import notify_helpers
from features import notify_reasons
from framework import authdata
from framework import emailfmt
from framework import exceptions
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import jsonfeed
from framework import monorailrequest
from framework import permissions
from framework import template_helpers
from framework import urls
from tracker import tracker_bizobj
from tracker import tracker_helpers
from tracker import tracker_views
from proto import tracker_pb2


class NotifyIssueChangeTask(notify_helpers.NotifyTaskBase):
  """JSON servlet that notifies appropriate users after an issue change."""

  _EMAIL_TEMPLATE = 'tracker/issue-change-notification-email.ezt'
  _LINK_ONLY_EMAIL_TEMPLATE = (
      'tracker/issue-change-notification-email-link-only.ezt')

  def HandleRequest(self, mr):
    """Process the task to notify users after an issue change.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """
    issue_id = mr.GetPositiveIntParam('issue_id')
    if not issue_id:
      return {
          'params': {},
          'notified': [],
          'message': 'Cannot proceed without a valid issue ID.',
      }
    commenter_id = mr.GetPositiveIntParam('commenter_id')
    seq_num = mr.seq
    omit_ids = [commenter_id]
    hostport = mr.GetParam('hostport')
    try:
      old_owner_id = mr.GetPositiveIntParam('old_owner_id')
    except Exception:
      old_owner_id = framework_constants.NO_USER_SPECIFIED
    send_email = bool(mr.GetIntParam('send_email'))
    comment_id = mr.GetPositiveIntParam('comment_id')
    params = dict(
        issue_id=issue_id, commenter_id=commenter_id,
        seq_num=seq_num, hostport=hostport, old_owner_id=old_owner_id,
        omit_ids=omit_ids, send_email=send_email, comment_id=comment_id)

    logging.info('issue change params are %r', params)
    # TODO(jrobbins): Re-enable the issue cache for notifications after
    # the stale issue defect (monorail:2514) is 100% resolved.
    issue = self.services.issue.GetIssue(mr.cnxn, issue_id, use_cache=False)
    project = self.services.project.GetProject(mr.cnxn, issue.project_id)
    config = self.services.config.GetProjectConfig(mr.cnxn, issue.project_id)

    if issue.is_spam:
      # Don't send email for spam issues.
      return {
          'params': params,
          'notified': [],
      }

    all_comments = self.services.issue.GetCommentsForIssue(
        mr.cnxn, issue.issue_id)
    if comment_id:
      logging.info('Looking up comment by comment_id')
      for c in all_comments:
        if c.id == comment_id:
          comment = c
          logging.info('Comment was found by comment_id')
          break
      else:
        raise ValueError('Comment %r was not found' % comment_id)
    else:
      logging.info('Looking up comment by seq_num')
      comment = all_comments[seq_num]

    # Only issues that any contributor could view sent to mailing lists.
    contributor_could_view = permissions.CanViewIssue(
        set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET,
        project, issue)
    starrer_ids = self.services.issue_star.LookupItemStarrers(
        mr.cnxn, issue.issue_id)
    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user,
        tracker_bizobj.UsersInvolvedInIssues([issue]), [old_owner_id],
        tracker_bizobj.UsersInvolvedInComment(comment),
        issue.cc_ids, issue.derived_cc_ids, starrer_ids, omit_ids)

    # Make followup tasks to send emails
    tasks = []
    if send_email:
      tasks = self._MakeEmailTasks(
          mr.cnxn, project, issue, config, old_owner_id, users_by_id,
          all_comments, comment, starrer_ids, contributor_could_view,
          hostport, omit_ids, mr.perms)

    notified = notify_helpers.AddAllEmailTasks(tasks)

    return {
        'params': params,
        'notified': notified,
        }

  def _MakeEmailTasks(
      self, cnxn, project, issue, config, old_owner_id,
      users_by_id, all_comments, comment, starrer_ids,
      contributor_could_view, hostport, omit_ids, perms):
    """Formulate emails to be sent."""
    detail_url = framework_helpers.IssueCommentURL(
        hostport, project, issue.local_id, seq_num=comment.sequence)

    # TODO(jrobbins): avoid the need to make a MonorailRequest object.
    mr = monorailrequest.MonorailRequest(self.services)
    mr.project_name = project.project_name
    mr.project = project
    mr.perms = perms

    # We do not autolink in the emails, so just use an empty
    # registry of autolink rules.
    # TODO(jrobbins): offer users an HTML email option w/ autolinks.
    autolinker = autolink.Autolink()
    was_created = ezt.boolean(comment.sequence == 0)

    email_data = {
        # Pass open_related and closed_related into this method and to
        # the issue view so that we can show it on new issue email.
        'issue': tracker_views.IssueView(issue, users_by_id, config),
        'summary': issue.summary,
        'comment': tracker_views.IssueCommentView(
            project.project_name, comment, users_by_id,
            autolinker, {}, mr, issue),
        'comment_text': comment.content,
        'detail_url': detail_url,
        'was_created': was_created,
        }

    # Generate three versions of email body: link-only is just the link,
    # non-members see some obscured email addresses, and members version has
    # all full email addresses exposed.
    body_link_only = self.link_only_email_template.GetResponse(
      {'detail_url': detail_url, 'was_created': was_created})
    body_for_non_members = self.email_template.GetResponse(email_data)
    framework_views.RevealAllEmails(users_by_id)
    email_data['comment'] = tracker_views.IssueCommentView(
        project.project_name, comment, users_by_id,
        autolinker, {}, mr, issue)
    body_for_members = self.email_template.GetResponse(email_data)

    logging.info('link-only body is:\n%r' % body_link_only)
    logging.info('body for non-members is:\n%r' % body_for_non_members)
    logging.info('body for members is:\n%r' % body_for_members)

    commenter_email = users_by_id[comment.user_id].email
    omit_addrs = set([commenter_email] +
                     [users_by_id[omit_id].email for omit_id in omit_ids])

    auth = authdata.AuthData.FromUserID(
        cnxn, comment.user_id, self.services)
    commenter_in_project = framework_bizobj.UserIsInProject(
        project, auth.effective_ids)
    noisy = tracker_helpers.IsNoisy(len(all_comments) - 1, len(starrer_ids))

    # Give each user a bullet-list of all the reasons that apply for that user.
    group_reason_list = notify_reasons.ComputeGroupReasonList(
        cnxn, self.services, project, issue, config, users_by_id,
        omit_addrs, contributor_could_view, noisy=noisy,
        starrer_ids=starrer_ids, old_owner_id=old_owner_id,
        commenter_in_project=commenter_in_project)

    commenter_view = users_by_id[comment.user_id]
    detail_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, issue.project_name, urls.ISSUE_DETAIL,
        id=issue.local_id)
    email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
        group_reason_list, issue, body_link_only, body_for_non_members,
        body_for_members, project, hostport, commenter_view, detail_url,
        seq_num=comment.sequence)

    return email_tasks

  def PostNotifyIssueChangeTask(self, **kwargs):
    return self.handler(**kwargs)


class NotifyBlockingChangeTask(notify_helpers.NotifyTaskBase):
  """JSON servlet that notifies appropriate users after a blocking change."""

  _EMAIL_TEMPLATE = 'tracker/issue-blocking-change-notification-email.ezt'
  _LINK_ONLY_EMAIL_TEMPLATE = (
      'tracker/issue-change-notification-email-link-only.ezt')

  def HandleRequest(self, mr):
    """Process the task to notify users after an issue blocking change.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """
    issue_id = mr.GetPositiveIntParam('issue_id')
    if not issue_id:
      return {
          'params': {},
          'notified': [],
          'message': 'Cannot proceed without a valid issue ID.',
      }
    commenter_id = mr.GetPositiveIntParam('commenter_id')
    omit_ids = [commenter_id]
    hostport = mr.GetParam('hostport')
    delta_blocker_iids = mr.GetIntListParam('delta_blocker_iids')
    send_email = bool(mr.GetIntParam('send_email'))
    params = dict(
        issue_id=issue_id, commenter_id=commenter_id,
        hostport=hostport, delta_blocker_iids=delta_blocker_iids,
        omit_ids=omit_ids, send_email=send_email)

    logging.info('blocking change params are %r', params)
    issue = self.services.issue.GetIssue(mr.cnxn, issue_id)
    if issue.is_spam:
      return {
        'params': params,
        'notified': [],
        }

    upstream_issues = self.services.issue.GetIssues(
        mr.cnxn, delta_blocker_iids)
    logging.info('updating ids %r', [up.local_id for up in upstream_issues])
    upstream_projects = tracker_helpers.GetAllIssueProjects(
        mr.cnxn, upstream_issues, self.services.project)
    upstream_configs = self.services.config.GetProjectConfigs(
        mr.cnxn, list(upstream_projects.keys()))

    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user, [commenter_id])
    commenter_view = users_by_id[commenter_id]

    tasks = []
    if send_email:
      for upstream_issue in upstream_issues:
        one_issue_email_tasks = self._ProcessUpstreamIssue(
            mr.cnxn, upstream_issue,
            upstream_projects[upstream_issue.project_id],
            upstream_configs[upstream_issue.project_id],
            issue, omit_ids, hostport, commenter_view)
        tasks.extend(one_issue_email_tasks)

    notified = notify_helpers.AddAllEmailTasks(tasks)

    return {
        'params': params,
        'notified': notified,
        }

  def _ProcessUpstreamIssue(
      self, cnxn, upstream_issue, upstream_project, upstream_config,
      issue, omit_ids, hostport, commenter_view):
    """Compute notifications for one upstream issue that is now blocking."""
    upstream_detail_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, upstream_issue.project_name, urls.ISSUE_DETAIL,
        id=upstream_issue.local_id)
    logging.info('upstream_detail_url = %r', upstream_detail_url)
    detail_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, issue.project_name, urls.ISSUE_DETAIL,
        id=issue.local_id)

    # Only issues that any contributor could view are sent to mailing lists.
    contributor_could_view = permissions.CanViewIssue(
        set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET,
        upstream_project, upstream_issue)

    # Now construct the e-mail to send

    # Note: we purposely do not notify users who starred an issue
    # about changes in blocking.
    users_by_id = framework_views.MakeAllUserViews(
        cnxn, self.services.user,
        tracker_bizobj.UsersInvolvedInIssues([upstream_issue]), omit_ids)

    is_blocking = upstream_issue.issue_id in issue.blocked_on_iids

    email_data = {
        'issue': tracker_views.IssueView(
            upstream_issue, users_by_id, upstream_config),
        'summary': upstream_issue.summary,
        'detail_url': upstream_detail_url,
        'is_blocking': ezt.boolean(is_blocking),
        'downstream_issue_ref': tracker_bizobj.FormatIssueRef(
            (None, issue.local_id)),
        'downstream_issue_url': detail_url,
        }

    # TODO(jrobbins): Generate two versions of email body: members
    # vesion has other member full email addresses exposed.  But, don't
    # expose too many as we iterate through upstream projects.
    body_link_only = self.link_only_email_template.GetResponse(
        {'detail_url': upstream_detail_url, 'was_created': ezt.boolean(False)})
    body = self.email_template.GetResponse(email_data)

    omit_addrs = {users_by_id[omit_id].email for omit_id in omit_ids}

    # Get the transitive set of owners and Cc'd users, and their UserView's.
    # Give each user a bullet-list of all the reasons that apply for that user.
    # Starrers are not notified of blocking changes to reduce noise.
    group_reason_list = notify_reasons.ComputeGroupReasonList(
        cnxn, self.services, upstream_project, upstream_issue,
        upstream_config, users_by_id, omit_addrs, contributor_could_view)
    one_issue_email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
        group_reason_list, upstream_issue, body_link_only, body, body,
        upstream_project, hostport, commenter_view, detail_url)

    return one_issue_email_tasks

  def PostNotifyBlockingChangeTask(self, **kwargs):
    return self.handler(**kwargs)


class NotifyBulkChangeTask(notify_helpers.NotifyTaskBase):
  """JSON servlet that notifies appropriate users after a bulk edit."""

  _EMAIL_TEMPLATE = 'tracker/issue-bulk-change-notification-email.ezt'

  def HandleRequest(self, mr):
    """Process the task to notify users after an issue blocking change.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """
    issue_ids = mr.GetIntListParam('issue_ids')
    hostport = mr.GetParam('hostport')
    if not issue_ids:
      return {
          'params': {},
          'notified': [],
          'message': 'Cannot proceed without a valid issue IDs.',
      }

    old_owner_ids = mr.GetIntListParam('old_owner_ids')
    comment_text = mr.GetParam('comment_text')
    commenter_id = mr.GetPositiveIntParam('commenter_id')
    amendments = mr.GetParam('amendments')
    send_email = bool(mr.GetIntParam('send_email'))
    params = dict(
        issue_ids=issue_ids, commenter_id=commenter_id, hostport=hostport,
        old_owner_ids=old_owner_ids, comment_text=comment_text,
        send_email=send_email, amendments=amendments)

    logging.info('bulk edit params are %r', params)
    issues = self.services.issue.GetIssues(mr.cnxn, issue_ids)
    # TODO(jrobbins): For cross-project bulk edits, prefetch all relevant
    # projects and configs and pass a dict of them to subroutines.  For
    # now, all issue must be in the same project.
    project_id = issues[0].project_id
    project = self.services.project.GetProject(mr.cnxn, project_id)
    config = self.services.config.GetProjectConfig(mr.cnxn, project_id)
    issues = [issue for issue in issues if not issue.is_spam]
    anon_perms = permissions.GetPermissions(None, set(), project)

    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user, [commenter_id])
    ids_in_issues = {}
    starrers = {}

    non_private_issues = []
    for issue, old_owner_id in zip(issues, old_owner_ids):
      # TODO(jrobbins): use issue_id consistently rather than local_id.
      starrers[issue.local_id] = self.services.issue_star.LookupItemStarrers(
          mr.cnxn, issue.issue_id)
      named_ids = set()  # users named in user-value fields that notify.
      for fd in config.field_defs:
        named_ids.update(notify_reasons.ComputeNamedUserIDsToNotify(
            issue.field_values, fd))
      direct, indirect = self.services.usergroup.ExpandAnyGroupEmailRecipients(
          mr.cnxn,
          list(issue.cc_ids) + list(issue.derived_cc_ids) +
          [issue.owner_id, old_owner_id, issue.derived_owner_id] +
          list(named_ids))
      ids_in_issues[issue.local_id] = set(starrers[issue.local_id])
      ids_in_issues[issue.local_id].update(direct)
      ids_in_issues[issue.local_id].update(indirect)
      ids_in_issue_needing_views = (
          ids_in_issues[issue.local_id] |
          tracker_bizobj.UsersInvolvedInIssues([issue]))
      new_ids_in_issue = [user_id for user_id in ids_in_issue_needing_views
                          if user_id not in users_by_id]
      users_by_id.update(
          framework_views.MakeAllUserViews(
              mr.cnxn, self.services.user, new_ids_in_issue))

      anon_can_view = permissions.CanViewIssue(
          set(), anon_perms, project, issue)
      if anon_can_view:
        non_private_issues.append(issue)

    commenter_view = users_by_id[commenter_id]
    omit_addrs = {commenter_view.email}

    tasks = []
    if send_email:
      email_tasks = self._BulkEditEmailTasks(
          mr.cnxn, issues, old_owner_ids, omit_addrs, project,
          non_private_issues, users_by_id, ids_in_issues, starrers,
          commenter_view, hostport, comment_text, amendments, config)
      tasks = email_tasks

    notified = notify_helpers.AddAllEmailTasks(tasks)
    return {
        'params': params,
        'notified': notified,
        }

  def _BulkEditEmailTasks(
      self, cnxn, issues, old_owner_ids, omit_addrs, project,
      non_private_issues, users_by_id, ids_in_issues, starrers,
      commenter_view, hostport, comment_text, amendments, config):
    """Generate Email PBs to notify interested users after a bulk edit."""
    # 1. Get the user IDs of everyone who could be notified,
    # and make all their user proxies. Also, build a dictionary
    # of all the users to notify and the issues that they are
    # interested in.  Also, build a dictionary of additional email
    # addresses to notify and the issues to notify them of.
    users_by_id = {}
    ids_to_notify_of_issue = {}
    additional_addrs_to_notify_of_issue = collections.defaultdict(list)

    users_to_queries = notify_reasons.GetNonOmittedSubscriptions(
        cnxn, self.services, [project.project_id], {})
    config = self.services.config.GetProjectConfig(
        cnxn, project.project_id)
    for issue, old_owner_id in zip(issues, old_owner_ids):
      issue_participants = set(
          [tracker_bizobj.GetOwnerId(issue), old_owner_id] +
          tracker_bizobj.GetCcIds(issue))
      # users named in user-value fields that notify.
      for fd in config.field_defs:
        issue_participants.update(
            notify_reasons.ComputeNamedUserIDsToNotify(issue.field_values, fd))
      for user_id in ids_in_issues[issue.local_id]:
        # TODO(jrobbins): implement batch GetUser() for speed.
        if not user_id:
          continue
        auth = authdata.AuthData.FromUserID(
            cnxn, user_id, self.services)
        if (auth.user_pb.notify_issue_change and
            not auth.effective_ids.isdisjoint(issue_participants)):
          ids_to_notify_of_issue.setdefault(user_id, []).append(issue)
        elif (auth.user_pb.notify_starred_issue_change and
              user_id in starrers[issue.local_id]):
          # Skip users who have starred issues that they can no longer view.
          starrer_perms = permissions.GetPermissions(
              auth.user_pb, auth.effective_ids, project)
          granted_perms = tracker_bizobj.GetGrantedPerms(
              issue, auth.effective_ids, config)
          starrer_can_view = permissions.CanViewIssue(
              auth.effective_ids, starrer_perms, project, issue,
              granted_perms=granted_perms)
          if starrer_can_view:
            ids_to_notify_of_issue.setdefault(user_id, []).append(issue)
        logging.info(
            'ids_to_notify_of_issue[%s] = %s',
            user_id,
            [i.local_id for i in ids_to_notify_of_issue.get(user_id, [])])

      # Find all subscribers that should be notified.
      subscribers_to_consider = notify_reasons.EvaluateSubscriptions(
          cnxn, issue, users_to_queries, self.services, config)
      for sub_id in subscribers_to_consider:
        auth = authdata.AuthData.FromUserID(cnxn, sub_id, self.services)
        sub_perms = permissions.GetPermissions(
            auth.user_pb, auth.effective_ids, project)
        granted_perms = tracker_bizobj.GetGrantedPerms(
            issue, auth.effective_ids, config)
        sub_can_view = permissions.CanViewIssue(
            auth.effective_ids, sub_perms, project, issue,
            granted_perms=granted_perms)
        if sub_can_view:
          ids_to_notify_of_issue.setdefault(sub_id, [])
          if issue not in ids_to_notify_of_issue[sub_id]:
            ids_to_notify_of_issue[sub_id].append(issue)

      if issue in non_private_issues:
        for notify_addr in issue.derived_notify_addrs:
          additional_addrs_to_notify_of_issue[notify_addr].append(issue)

    # 2. Compose an email specifically for each user, and one email to each
    # notify_addr with all the issues that it.
    # Start from non-members first, then members to reveal email addresses.
    email_tasks = []
    needed_user_view_ids = [uid for uid in ids_to_notify_of_issue
                            if uid not in users_by_id]
    users_by_id.update(framework_views.MakeAllUserViews(
        cnxn, self.services.user, needed_user_view_ids))
    member_ids_to_notify_of_issue = {}
    non_member_ids_to_notify_of_issue = {}
    member_additional_addrs = {}
    non_member_additional_addrs = {}
    addr_to_addrperm = {}  # {email_address: AddrPerm object}
    all_user_prefs = self.services.user.GetUsersPrefs(
        cnxn, ids_to_notify_of_issue)

    # TODO(jrobbins): Merge ids_to_notify_of_issue entries for linked accounts.

    for user_id in ids_to_notify_of_issue:
      if not user_id:
        continue  # Don't try to notify NO_USER_SPECIFIED
      if users_by_id[user_id].email in omit_addrs:
        logging.info('Omitting %s', user_id)
        continue
      user_issues = ids_to_notify_of_issue[user_id]
      if not user_issues:
        continue  # user's prefs indicate they don't want these notifications
      auth = authdata.AuthData.FromUserID(
          cnxn, user_id, self.services)
      is_member = bool(framework_bizobj.UserIsInProject(
          project, auth.effective_ids))
      if is_member:
        member_ids_to_notify_of_issue[user_id] = user_issues
      else:
        non_member_ids_to_notify_of_issue[user_id] = user_issues
      addr = users_by_id[user_id].email
      omit_addrs.add(addr)
      addr_to_addrperm[addr] = notify_reasons.AddrPerm(
          is_member, addr, users_by_id[user_id].user,
          notify_reasons.REPLY_NOT_ALLOWED, all_user_prefs[user_id])

    for addr, addr_issues in additional_addrs_to_notify_of_issue.items():
      auth = None
      try:
        auth = authdata.AuthData.FromEmail(cnxn, addr, self.services)
      except:  # pylint: disable=bare-except
        logging.warning('Cannot find user of email %s ', addr)
      if auth:
        is_member = bool(framework_bizobj.UserIsInProject(
            project, auth.effective_ids))
      else:
        is_member = False
      if is_member:
        member_additional_addrs[addr] = addr_issues
      else:
        non_member_additional_addrs[addr] = addr_issues
      omit_addrs.add(addr)
      addr_to_addrperm[addr] = notify_reasons.AddrPerm(
          is_member, addr, None, notify_reasons.REPLY_NOT_ALLOWED, None)

    for user_id, user_issues in non_member_ids_to_notify_of_issue.items():
      addr = users_by_id[user_id].email
      email = self._FormatBulkIssuesEmail(
          addr_to_addrperm[addr], user_issues, users_by_id,
          commenter_view, hostport, comment_text, amendments, config, project)
      email_tasks.append(email)
      logging.info('about to bulk notify non-member %s (%s) of %s',
                   users_by_id[user_id].email, user_id,
                   [issue.local_id for issue in user_issues])

    for addr, addr_issues in non_member_additional_addrs.items():
      email = self._FormatBulkIssuesEmail(
          addr_to_addrperm[addr], addr_issues, users_by_id, commenter_view,
          hostport, comment_text, amendments, config, project)
      email_tasks.append(email)
      logging.info('about to bulk notify non-member additional addr %s of %s',
                   addr, [addr_issue.local_id for addr_issue in addr_issues])

    framework_views.RevealAllEmails(users_by_id)
    commenter_view.RevealEmail()

    for user_id, user_issues in member_ids_to_notify_of_issue.items():
      addr = users_by_id[user_id].email
      email = self._FormatBulkIssuesEmail(
          addr_to_addrperm[addr], user_issues, users_by_id,
          commenter_view, hostport, comment_text, amendments, config, project)
      email_tasks.append(email)
      logging.info('about to bulk notify member %s (%s) of %s',
                   addr, user_id, [issue.local_id for issue in user_issues])

    for addr, addr_issues in member_additional_addrs.items():
      email = self._FormatBulkIssuesEmail(
          addr_to_addrperm[addr], addr_issues, users_by_id, commenter_view,
          hostport, comment_text, amendments, config, project)
      email_tasks.append(email)
      logging.info('about to bulk notify member additional addr %s of %s',
                   addr, [addr_issue.local_id for addr_issue in addr_issues])

    # 4. Add in the project's issue_notify_address.  This happens even if it
    # is the same as the commenter's email address (which would be an unusual
    # but valid project configuration).  Only issues that any contributor could
    # view are included in emails to the all-issue-activity mailing lists.
    if (project.issue_notify_address
        and project.issue_notify_address not in omit_addrs):
      non_private_issues_live = []
      for issue in issues:
        contributor_could_view = permissions.CanViewIssue(
            set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET,
            project, issue)
        if contributor_could_view:
          non_private_issues_live.append(issue)

      if non_private_issues_live:
        project_notify_addrperm = notify_reasons.AddrPerm(
            True, project.issue_notify_address, None,
            notify_reasons.REPLY_NOT_ALLOWED, None)
        email = self._FormatBulkIssuesEmail(
            project_notify_addrperm, non_private_issues_live,
            users_by_id, commenter_view, hostport, comment_text, amendments,
            config, project)
        email_tasks.append(email)
        omit_addrs.add(project.issue_notify_address)
        logging.info('about to bulk notify all-issues %s of %s',
                     project.issue_notify_address,
                     [issue.local_id for issue in non_private_issues])

    return email_tasks

  def _FormatBulkIssuesEmail(
      self, addr_perm, issues, users_by_id, commenter_view,
      hostport, comment_text, amendments, config, project):
    """Format an email to one user listing many issues."""

    from_addr = emailfmt.FormatFromAddr(
        project, commenter_view=commenter_view, reveal_addr=addr_perm.is_member,
        can_reply_to=False)

    subject, body = self._FormatBulkIssues(
        issues, users_by_id, commenter_view, hostport, comment_text,
        amendments, config, addr_perm)
    body = notify_helpers._TruncateBody(body)

    return dict(from_addr=from_addr, to=addr_perm.address, subject=subject,
                body=body)

  def _FormatBulkIssues(
      self, issues, users_by_id, commenter_view, hostport, comment_text,
      amendments, config, addr_perm):
    """Format a subject and body for a bulk issue edit."""
    project_name = issues[0].project_name

    any_link_only = False
    issue_views = []
    for issue in issues:
      # TODO(jrobbins): choose config from dict of prefetched configs.
      issue_view = tracker_views.IssueView(issue, users_by_id, config)
      issue_view.link_only = ezt.boolean(False)
      if addr_perm and notify_helpers.ShouldUseLinkOnly(addr_perm, issue):
        issue_view.link_only = ezt.boolean(True)
        any_link_only = True
      issue_views.append(issue_view)

    email_data = {
        'any_link_only': ezt.boolean(any_link_only),
        'hostport': hostport,
        'num_issues': len(issues),
        'issues': issue_views,
        'comment_text': comment_text,
        'commenter': commenter_view,
        'amendments': amendments,
    }

    if len(issues) == 1:
      # TODO(jrobbins): use compact email subject lines based on user pref.
      if addr_perm and notify_helpers.ShouldUseLinkOnly(addr_perm, issues[0]):
        subject = 'issue %s in %s' % (issues[0].local_id, project_name)
      else:
        subject = 'issue %s in %s: %s' % (
            issues[0].local_id, project_name, issues[0].summary)
      # TODO(jrobbins): Look up the sequence number instead and treat this
      # more like an individual change for email threading.  For now, just
      # add "Re:" because bulk edits are always replies.
      subject = 'Re: ' + subject
    else:
      subject = '%d issues changed in %s' % (len(issues), project_name)

    body = self.email_template.GetResponse(email_data)

    return subject, body

  def PostNotifyBulkChangeTask(self, **kwargs):
    return self.handler(**kwargs)


# For now, this class will not be used to send approval comment notifications
# TODO(jojwang): monorail:3588, it might make sense for this class to handle
# sending comment notifications for approval custom_subfield changes.
class NotifyApprovalChangeTask(notify_helpers.NotifyTaskBase):
  """JSON servlet that notifies appropriate users after an approval change."""

  _EMAIL_TEMPLATE = 'tracker/approval-change-notification-email.ezt'

  def HandleRequest(self, mr):
    """Process the task to notify users after an approval change.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """

    send_email = bool(mr.GetIntParam('send_email'))
    issue_id = mr.GetPositiveIntParam('issue_id')
    approval_id = mr.GetPositiveIntParam('approval_id')
    comment_id = mr.GetPositiveIntParam('comment_id')
    hostport = mr.GetParam('hostport')

    params = dict(
        temporary='',
        hostport=hostport,
        issue_id=issue_id
        )
    logging.info('approval change params are %r', params)

    issue, approval_value = self.services.issue.GetIssueApproval(
        mr.cnxn, issue_id, approval_id, use_cache=False)
    project = self.services.project.GetProject(mr.cnxn, issue.project_id)
    config = self.services.config.GetProjectConfig(mr.cnxn, issue.project_id)

    approval_fd = tracker_bizobj.FindFieldDefByID(approval_id, config)
    if approval_fd is None:
      raise exceptions.NoSuchFieldDefException()

    # GetCommentsForIssue will fill the sequence for all comments, while
    # other method for getting a single comment will not.
    # The comment sequence is especially useful for Approval issues with
    # many comment sections.
    comment = None
    all_comments = self.services.issue.GetCommentsForIssue(mr.cnxn, issue_id)
    for c in all_comments:
      if c.id == comment_id:
        comment = c
        break
    if not comment:
      raise exceptions.NoSuchCommentException()

    field_user_ids = set()
    relevant_fds = [fd for fd in config.field_defs if
                    not fd.approval_id or
                    fd.approval_id is approval_value.approval_id]
    for fd in relevant_fds:
      field_user_ids.update(
          notify_reasons.ComputeNamedUserIDsToNotify(issue.field_values, fd))
    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user, [issue.owner_id],
        approval_value.approver_ids,
        tracker_bizobj.UsersInvolvedInComment(comment),
        list(field_user_ids))

    tasks = []
    if send_email:
      tasks = self._MakeApprovalEmailTasks(
          hostport, issue, project, approval_value, approval_fd.field_name,
          comment, users_by_id, list(field_user_ids), mr.perms)

    notified = notify_helpers.AddAllEmailTasks(tasks)

    return {
        'params': params,
        'notified': notified,
        'tasks': tasks,
        }

  def _MakeApprovalEmailTasks(
      self, hostport, issue, project, approval_value, approval_name,
      comment, users_by_id, user_ids_from_fields, perms):
    """Formulate emails to be sent."""

    # TODO(jojwang): avoid need to make MonorailRequest and autolinker
    # for comment_view OR make make tracker_views._ParseTextRuns public
    # and only pass text_runs to email_data.
    mr = monorailrequest.MonorailRequest(self.services)
    mr.project_name = project.project_name
    mr.project = project
    mr.perms = perms
    autolinker = autolink.Autolink()

    approval_url = framework_helpers.IssueCommentURL(
        hostport, project, issue.local_id, seq_num=comment.sequence)

    comment_view = tracker_views.IssueCommentView(
        project.project_name, comment, users_by_id, autolinker, {}, mr, issue)
    domain_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, project.project_name, '/issues/')

    commenter_view = users_by_id[comment.user_id]
    email_data = {
        'domain_url': domain_url,
        'approval_url': approval_url,
        'comment': comment_view,
        'issue_local_id': issue.local_id,
        'summary': issue.summary,
        }
    subject = '%s Approval: %s (Issue %s)' % (
        approval_name, issue.summary, issue.local_id)
    email_body = self.email_template.GetResponse(email_data)
    body = notify_helpers._TruncateBody(email_body)

    recipient_ids = self._GetApprovalEmailRecipients(
        approval_value, comment, issue, user_ids_from_fields,
        omit_ids=[comment.user_id])
    direct, indirect = self.services.usergroup.ExpandAnyGroupEmailRecipients(
        mr.cnxn, recipient_ids)
    # group ids were found in recipient_ids.
    # Re-set recipient_ids to remove group_ids
    if indirect:
      recipient_ids = set(direct + indirect)
      users_by_id.update(framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, indirect))  # already contains direct

    # TODO(crbug.com/monorail/9104): Compute notify_reasons.AddrPerms based on
    # project settings and recipient permissions so `reply_to` can be accurately
    # set.

    email_tasks = []
    for rid in recipient_ids:
      from_addr = emailfmt.FormatFromAddr(
          project, commenter_view=commenter_view, can_reply_to=False)
      dest_email = users_by_id[rid].email

      refs = emailfmt.GetReferences(
          dest_email, subject, comment.sequence,
          '%s@%s' % (project.project_name, emailfmt.MailDomain()))
      reply_to = emailfmt.NoReplyAddress()
      email_tasks.append(
          dict(
              from_addr=from_addr,
              to=dest_email,
              subject=subject,
              body=body,
              reply_to=reply_to,
              references=refs))

    return email_tasks

  def _GetApprovalEmailRecipients(
      self, approval_value, comment, issue, user_ids_from_fields,
      omit_ids=None):
    # TODO(jojwang): monorail:3588, reorganize this, since now, comment_content
    # and approval amendments happen in the same comment.
    # NOTE: user_ids_from_fields are all the notify_on=ANY_COMMENT users.
    # However, these users will still be excluded from notifications
    # meant for approvers only eg. (status changed to REVIEW_REQUESTED).
    recipient_ids = []
    if comment.amendments:
      for amendment in comment.amendments:
        if amendment.custom_field_name == 'Status':
          if (approval_value.status is
              tracker_pb2.ApprovalStatus.REVIEW_REQUESTED):
            recipient_ids = approval_value.approver_ids
          else:
            recipient_ids.extend([issue.owner_id])
            recipient_ids.extend(user_ids_from_fields)

        elif amendment.custom_field_name == 'Approvers':
          recipient_ids.extend(approval_value.approver_ids)
          recipient_ids.append(issue.owner_id)
          recipient_ids.extend(user_ids_from_fields)
          recipient_ids.extend(amendment.removed_user_ids)
    else:
      # No amendments, just a comment.
      recipient_ids.extend(approval_value.approver_ids)
      recipient_ids.append(issue.owner_id)
      recipient_ids.extend(user_ids_from_fields)

    if omit_ids:
      recipient_ids = [rid for rid in recipient_ids if rid not in omit_ids]

    return list(set(recipient_ids))

  def PostNotifyApprovalChangeTask(self, **kwargs):
    return self.handler(**kwargs)


class NotifyRulesDeletedTask(notify_helpers.NotifyTaskBase):
  """JSON servlet that sends one email."""

  _EMAIL_TEMPLATE = 'project/rules-deleted-notification-email.ezt'

  def HandleRequest(self, mr):
    """Process the task to notify project owners after a filter rule
      has been deleted.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful for debugging.
    """
    project_id = mr.GetPositiveIntParam('project_id')
    rules = mr.GetListParam('filter_rules')
    hostport = mr.GetParam('hostport')

    params = dict(
        project_id=project_id,
        rules=rules,
        hostport=hostport,
        )
    logging.info('deleted filter rules params are %r', params)

    project = self.services.project.GetProject(mr.cnxn, project_id)
    emails_by_id = self.services.user.LookupUserEmails(
        mr.cnxn, project.owner_ids, ignore_missed=True)

    tasks = self._MakeRulesDeletedEmailTasks(
        hostport, project, emails_by_id, rules)
    notified = notify_helpers.AddAllEmailTasks(tasks)

    return {
        'params': params,
        'notified': notified,
        'tasks': tasks,
        }

  def _MakeRulesDeletedEmailTasks(self, hostport, project, emails_by_id, rules):

    rules_url = framework_helpers.FormatAbsoluteURLForDomain(
        hostport, project.project_name, urls.ADMIN_RULES)

    email_data = {
        'project_name': project.project_name,
        'rules': rules,
        'rules_url': rules_url,
    }
    logging.info(email_data)
    subject = '%s Project: Deleted Filter Rules' % project.project_name
    email_body = self.email_template.GetResponse(email_data)
    body = notify_helpers._TruncateBody(email_body)

    email_tasks = []
    for rid in project.owner_ids:
      from_addr = emailfmt.FormatFromAddr(
          project, reveal_addr=True, can_reply_to=False)
      dest_email = emails_by_id.get(rid)
      email_tasks.append(
          dict(from_addr=from_addr, to=dest_email, subject=subject, body=body))

    return email_tasks

  def PostNotifyRulesDeletedTask(self, **kwargs):
    return self.handler(**kwargs)


class OutboundEmailTask(jsonfeed.FlaskInternalTask):
  """JSON servlet that sends one email.

  Handles tasks enqueued from notify_helpers._EnqueueOutboundEmail.
  """

  def HandleRequest(self, mr):
    """Process the task to send one email message.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """
    # To avoid urlencoding the email body, the most salient parameters to this
    # method are passed as a json-encoded POST body.
    try:
      email_params = json.loads(self.request.get_data(as_text=True))
    except ValueError:
      logging.error(self.request.get_data(as_text=True))
      raise
    # If running on a GAFYD domain, you must define an app alias on the
    # Application Settings admin web page.
    sender = email_params.get('from_addr')
    reply_to = email_params.get('reply_to')
    to = email_params.get('to')
    if not to:
      # Cannot proceed if we cannot create a valid EmailMessage.
      return {'note': 'Skipping because no "to" address found.'}

    # Don't send emails to any banned users.
    try:
      user_id = self.services.user.LookupUserID(mr.cnxn, to)
      user = self.services.user.GetUser(mr.cnxn, user_id)
      if user.banned:
        logging.info('Not notifying banned user %r', user.email)
        return {'note': 'Skipping because user is banned.'}
    except exceptions.NoSuchUserException:
      pass

    references = email_params.get('references')
    subject = email_params.get('subject')
    body = email_params.get('body')
    html_body = email_params.get('html_body')

    if settings.local_mode:
      to_format = settings.send_local_email_to
    else:
      to_format = settings.send_all_email_to

    if to_format:
      to_user, to_domain = to.split('@')
      to = to_format % {'user': to_user, 'domain': to_domain}

    logging.info(
        'Email:\n sender: %s\n reply_to: %s\n to: %s\n references: %s\n '
        'subject: %s\n body: %s\n html body: %s',
        sender, reply_to, to, references, subject, body, html_body)
    if html_body:
      logging.info('Readable HTML:\n%s', html_body.replace('<br/>', '<br/>\n'))
    message = mail.EmailMessage(
        sender=sender, to=to, subject=subject, body=body)
    if html_body:
      message.html = html_body
    if reply_to:
      message.reply_to = reply_to
    if references:
      message.headers = {'References': references}
    if settings.unit_test_mode:
      logging.info('Sending message "%s" in test mode.', message.subject)
    else:
      retry_count = 3
      for i in range(retry_count):
        try:
          message.send()
          break
        except apiproxy_errors.DeadlineExceededError as ex:
          logging.warning('Sending email timed out on try: %d', i)
          logging.warning(str(ex))

    return dict(
        sender=sender, to=to, subject=subject, body=body, html_body=html_body,
        reply_to=reply_to, references=references)

  def PostOutboundEmailTask(self, **kwargs):
    return self.handler(**kwargs)
