# 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 GetNotifyIssueChangeTask(self, **kwargs):
  #   return self.handler(**kwargs)

  # 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 GetNotifyBlockingChangeTask(self, **kwargs):
  #   return self.handler(**kwargs)

  # 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 GetNotifyBulkChangeTask(self, **kwargs):
  #   return self.handler(**kwargs)

  # 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 GetNotifyApprovalChangeTask(self, **kwargs):
  #   return self.handler(**kwargs)

  # 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 GetNotifyRulesDeletedTask(self, **kwargs):
  #   return self.handler(**kwargs)

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


# TODO: change to FlaskInternalTask when convert to flask
class OutboundEmailTask(jsonfeed.InternalTask):
  """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.body)
    except ValueError:
      logging.error(self.request.body)
      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 GetOutboundEmailTask(self, **kwargs):
  #   return self.handler(**kwargs)

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