def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""
    available_access_levels = project_helpers.BuildProjectAccessOptions(
        mr.project)
    offer_access_level = len(available_access_levels) > 1
    access_view = project_views.ProjectAccessView(mr.project.access)

    return {
        'admin_tab_mode': self.ADMIN_TAB_META,
        'initial_summary': mr.project.summary,
        'initial_project_home': mr.project.home_page,
        'initial_docs_url': mr.project.docs_url,
        'initial_source_url': mr.project.source_url,
        'initial_logo_gcs_id': mr.project.logo_gcs_id,
        'initial_logo_file_name': mr.project.logo_file_name,
        'logo_view': tracker_views.LogoView(mr.project),
        'initial_description': mr.project.description,
        'issue_notify': mr.project.issue_notify_address,
        'process_inbound_email': ezt.boolean(
            mr.project.process_inbound_email),
        'email_from_addr': emailfmt.FormatFromAddr(mr.project),
        'only_owners_remove_restrictions': ezt.boolean(
            mr.project.only_owners_remove_restrictions),
        'only_owners_see_contributors': ezt.boolean(
            mr.project.only_owners_see_contributors),
        'offer_access_level': ezt.boolean(offer_access_level),
        'initial_access': access_view,
        'available_access_levels': available_access_levels,
        }
 def testServiceAccountCommenter(self):
     johndoe_bot = '*****@*****.**'
     commenter_view = framework_views.StuffUserView(111L, johndoe_bot, True)
     self.assertEqual(
         ('johndoe via monorail <*****@*****.**>'),
         emailfmt.FormatFromAddr(self.project,
                                 commenter_view=commenter_view,
                                 reveal_addr=False))
Exemple #3
0
 def testObscuredCommenter(self):
     commenter_view = framework_views.StuffUserView(111, '*****@*****.**',
                                                    True)
     self.assertEqual(
         u'u\u2026 via monorail <*****@*****.**>',
         emailfmt.FormatFromAddr(self.project,
                                 commenter_view=commenter_view,
                                 reveal_addr=False))
Exemple #4
0
  def _FormatBulkIssuesEmail(
      self, dest_email, issues, users_by_id, commenter_view,
      hostport, comment_text, amendments, config, project, is_member):
    """Format an email to one user listing many issues."""

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

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

    return dict(from_addr=from_addr, to=dest_email, subject=subject, body=body)
    def testBodySelection_NonMember(self):
        """We send non-members the email body that is indented for non-members."""
        email_task = notify_helpers._MakeEmailWorkItem(
            notify_reasons.AddrPerm(False, '*****@*****.**',
                                    self.member, REPLY_NOT_ALLOWED,
                                    user_pb2.UserPrefs()), ['reason'],
            self.issue, 'body link-only', 'body non', 'body mem', self.project,
            'example.com', self.commenter_view, self.detail_url)

        self.assertEqual('*****@*****.**', email_task['to'])
        self.assertEqual('Issue 1234 in proj1: summary', email_task['subject'])
        self.assertIn('body non', email_task['body'])
        self.assertEqual(
            emailfmt.FormatFromAddr(self.project,
                                    commenter_view=self.commenter_view,
                                    can_reply_to=False),
            email_task['from_addr'])
        self.assertEqual(emailfmt.NoReplyAddress(), email_task['reply_to'])
Exemple #6
0
  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 testNoCommenterWithNoReply(self):
     self.assertEqual(
         settings.send_noreply_email_as,
         emailfmt.FormatFromAddr(self.project, can_reply_to=False))
 def testNoCommenter(self):
     self.assertEqual(settings.send_email_as,
                      emailfmt.FormatFromAddr(self.project))
Exemple #9
0
  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(jojwang): monorail:3588, refine email contents based on direct
    # and indirect user_ids returned.

    email_tasks = []
    for rid in recipient_ids:
      # TODO(jojwang): monorail:3588, add reveal_addr based on
      # recipient member status
      from_addr = emailfmt.FormatFromAddr(
          project, commenter_view=commenter_view, can_reply_to=False)
      dest_email = users_by_id[rid].email
      email_tasks.append(
          dict(from_addr=from_addr, to=dest_email, subject=subject, body=body)
      )

    return email_tasks
Exemple #10
0
def _MakeEmailWorkItem(addr_perm,
                       reasons,
                       issue,
                       body_for_non_members,
                       body_for_members,
                       project,
                       hostport,
                       commenter_view,
                       detail_url,
                       seq_num=None,
                       subject_prefix=None,
                       compact_subject_prefix=None):
    """Make one email task dict for one user, includes a detailed reason."""
    subject_format = ((subject_prefix or 'Issue ') +
                      '%(local_id)d in %(project_name)s: %(summary)s')
    if addr_perm.user and addr_perm.user.email_compact_subject:
        subject_format = ((compact_subject_prefix or '') +
                          '%(project_name)s:%(local_id)d: %(summary)s')

    subject = subject_format % {
        'local_id': issue.local_id,
        'project_name': issue.project_name,
        'summary': issue.summary,
    }

    footer = _MakeNotificationFooter(reasons, addr_perm.reply_perm, hostport)
    if isinstance(footer, unicode):
        footer = footer.encode('utf-8')
    if addr_perm.is_member:
        logging.info('got member %r, sending body for members',
                     addr_perm.address)
        body = _TruncateBody(body_for_members) + footer
    else:
        logging.info('got non-member %r, sending body for non-members',
                     addr_perm.address)
        body = _TruncateBody(body_for_non_members) + footer
    logging.info('sending message footer:\n%r', footer)

    can_reply_to = (addr_perm.reply_perm != notify_reasons.REPLY_NOT_ALLOWED
                    and project.process_inbound_email)
    from_addr = emailfmt.FormatFromAddr(project,
                                        commenter_view=commenter_view,
                                        reveal_addr=addr_perm.is_member,
                                        can_reply_to=can_reply_to)
    if can_reply_to:
        reply_to = '%s@%s' % (project.project_name, emailfmt.MailDomain())
    else:
        reply_to = emailfmt.NoReplyAddress()
    refs = emailfmt.GetReferences(
        addr_perm.address, subject, seq_num,
        '%s@%s' % (project.project_name, emailfmt.MailDomain()))
    # We use markup to display a convenient link that takes users directly to the
    # issue without clicking on the email.
    html_body = None
    # cgi.escape the body and additionally escape single quotes which are
    # occassionally used to contain HTML attributes and event handler
    # definitions.
    html_escaped_body = cgi.escape(body, quote=1).replace("'", '&#39;')
    template = HTML_BODY_WITH_GMAIL_ACTION_TEMPLATE
    if addr_perm.user and not addr_perm.user.email_view_widget:
        template = HTML_BODY_WITHOUT_GMAIL_ACTION_TEMPLATE
    html_body = template % {
        'url': detail_url,
        'body': _AddHTMLTags(html_escaped_body.decode('utf-8')),
    }
    return dict(to=addr_perm.address,
                subject=subject,
                body=body,
                html_body=html_body,
                from_addr=from_addr,
                reply_to=reply_to,
                references=refs)
Exemple #11
0
    footer = _MakeNotificationFooter(reasons, reply_perm, hostport)
    if isinstance(footer, unicode):
        footer = footer.encode('utf-8')
    if recipient_is_member:
        logging.info('got member %r, sending body for members', to_addr)
        body = _TruncateBody(body_for_members) + footer
    else:
        logging.info('got non-member %r, sending body for non-members',
                     to_addr)
        body = _TruncateBody(body_for_non_members) + footer
    logging.info('sending message footer:\n%r', footer)

    can_reply_to = (reply_perm != notify_reasons.REPLY_NOT_ALLOWED
                    and project.process_inbound_email)
    from_addr = emailfmt.FormatFromAddr(project,
                                        commenter_view=commenter_view,
                                        reveal_addr=recipient_is_member,
                                        can_reply_to=can_reply_to)
    if can_reply_to:
        reply_to = '%s@%s' % (project.project_name, emailfmt.MailDomain())
    else:
        reply_to = emailfmt.NoReplyAddress()
    refs = emailfmt.GetReferences(
        to_addr, subject, seq_num,
        '%s@%s' % (project.project_name, emailfmt.MailDomain()))
    # We use markup to display a convenient link that takes users directly to the
    # issue without clicking on the email.
    html_body = None
    # cgi.escape the body and additionally escape single quotes which are
    # occassionally used to contain HTML attributes and event handler
    # definitions.
    html_escaped_body = cgi.escape(body, quote=1).replace("'", '&#39;')