コード例 #1
0
    def test_process_for_imported_branch(self):
        """Make sure that the database user is able refer to import branches.

        Import branches have different permission checks than other branches.

        Permission to mark a merge proposal as approved checks launchpad.Edit
        of the target branch, or membership of the review team on the target
        branch.  For import branches launchpad.Edit also checks the registrant
        of the code import if there is one, and membership of vcs-imports.  So
        if someone is attempting to review something on an import branch, but
        they don't have launchpad.Edit but are a member of the review team,
        then a check against the code import is done.
        """
        mail = self.factory.makeSignedMessage(body=' merge approved')
        code_import = self.factory.makeCodeImport()
        bmp = self.factory.makeBranchMergeProposal(
            target_branch=code_import.branch)
        email_addr = bmp.address
        switch_dbuser(config.processmail.dbuser)
        pop_notifications()
        self.code_handler.process(mail, email_addr, None)
        notification = pop_notifications()[0]
        # The returned message is a multipart message, the first part is
        # the message, and the second is the original message.
        message, original = notification.get_payload()
        self.assertTrue(
            "You are not a reviewer for the branch" in
            message.get_payload(decode=True))
コード例 #2
0
 def test_holdMessage(self):
     # calling holdMessage() will create a held message and a notification.
     # The messages content is re-encoded
     team, member = self.factory.makeTeamWithMailingListSubscribers(
         'team', auto_subscribe=False)
     sender = self.factory.makePerson()
     email = dedent(str("""\
         From: %s
         To: %s
         Subject:  =?iso-8859-1?q?Adi=C3=B3s?=
         Message-ID: <first-post>
         Date: Fri, 01 Aug 2000 01:08:59 -0000\n
         hi.
         """ % (sender.preferredemail.email, team.mailing_list.address)))
     message = getUtility(IMessageSet).fromEmail(email)
     pop_notifications()
     held_message = team.mailing_list.holdMessage(message)
     self.assertEqual(PostedMessageStatus.NEW, held_message.status)
     self.assertEqual(message.rfc822msgid, held_message.message_id)
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     self.assertEqual(
         'New mailing list message requiring approval for Team',
         notifications[0]['subject'])
     self.assertTextMatchesExpressionIgnoreWhitespace(
         '.*Subject: Adi=C3=83=C2=B3s.*', notifications[0].get_payload())
コード例 #3
0
 def test_send_message(self):
     self.factory.makePerson(email='*****@*****.**', name='me')
     user = self.factory.makePerson(email='*****@*****.**', name='him')
     subject = 'test subject'
     body = 'test body'
     recipients_set = NotificationRecipientSet()
     recipients_set.add(user, 'test reason', 'test rationale')
     pop_notifications()
     send_direct_contact_email('*****@*****.**', recipients_set, subject, body)
     notifications = pop_notifications()
     notification = notifications[0]
     self.assertEqual(1, len(notifications))
     self.assertEqual('Me <*****@*****.**>', notification['From'])
     self.assertEqual('Him <*****@*****.**>', notification['To'])
     self.assertEqual(subject, notification['Subject'])
     self.assertEqual(
         'test rationale', notification['X-Launchpad-Message-Rationale'])
     self.assertIs(None, notification['Precedence'])
     self.assertTrue('launchpad' in notification['Message-ID'])
     self.assertEqual(
         '\n'.join([
             '%s' % body,
             '-- ',
             'This message was sent from Launchpad by',
             'Me (http://launchpad.dev/~me)',
             'test reason.',
             'For more information see',
             'https://help.launchpad.net/YourAccount/ContactingPeople']),
         notification.get_payload())
コード例 #4
0
def _createUbuntuBugTaskLinkedToQuestion():
    """Get the id of an Ubuntu bugtask linked to a question.

    The Ubuntu team is set as the answer contact for Ubuntu, and no-priv
    is used as the submitter..
    """
    login('*****@*****.**')
    sample_person = getUtility(IPersonSet).getByEmail('*****@*****.**')
    ubuntu_team = getUtility(IPersonSet).getByName('ubuntu-team')
    ubuntu_team.addLanguage(getUtility(ILanguageSet)['en'])
    ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
    ubuntu.addAnswerContact(ubuntu_team, ubuntu_team.teamowner)
    ubuntu_question = ubuntu.newQuestion(
        sample_person, "Can't install Ubuntu",
        "I insert the install CD in the CD-ROM drive, but it won't boot.")
    no_priv = getUtility(IPersonSet).getByEmail('*****@*****.**')
    params = CreateBugParams(owner=no_priv,
                             title="Installer fails on a Mac PPC",
                             comment=ubuntu_question.description)
    bug = ubuntu.createBug(params)
    ubuntu_question.linkBug(bug)
    [ubuntu_bugtask] = bug.bugtasks
    login(ANONYMOUS)
    # Remove the notifcations for the newly created question.
    pop_notifications()
    return ubuntu_bugtask.id
コード例 #5
0
 def test_holdMessage(self):
     # calling holdMessage() will create a held message and a notification.
     # The messages content is re-encoded
     team, member = self.factory.makeTeamWithMailingListSubscribers(
         'team', auto_subscribe=False)
     sender = self.factory.makePerson()
     email = dedent(str("""\
         From: %s
         To: %s
         Subject:  =?iso-8859-1?q?Adi=C3=B3s?=
         Message-ID: <first-post>
         Date: Fri, 01 Aug 2000 01:08:59 -0000\n
         hi.
         """ % (sender.preferredemail.email, team.mailing_list.address)))
     message = getUtility(IMessageSet).fromEmail(email)
     pop_notifications()
     held_message = team.mailing_list.holdMessage(message)
     self.assertEqual(PostedMessageStatus.NEW, held_message.status)
     self.assertEqual(message.rfc822msgid, held_message.message_id)
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     self.assertEqual(
         'New mailing list message requiring approval for Team',
         notifications[0]['subject'])
     self.assertTextMatchesExpressionIgnoreWhitespace(
         '.*Subject: Adi=C3=83=C2=B3s.*', notifications[0].get_payload())
コード例 #6
0
 def test_send_message(self):
     self.factory.makePerson(email='*****@*****.**', name='me')
     user = self.factory.makePerson(email='*****@*****.**', name='him')
     subject = 'test subject'
     body = 'test body'
     recipients_set = NotificationRecipientSet()
     recipients_set.add(user, 'test reason', 'test rationale')
     pop_notifications()
     send_direct_contact_email('*****@*****.**', recipients_set, subject, body)
     notifications = pop_notifications()
     notification = notifications[0]
     self.assertEqual(1, len(notifications))
     self.assertEqual('Me <*****@*****.**>', notification['From'])
     self.assertEqual('Him <*****@*****.**>', notification['To'])
     self.assertEqual(subject, notification['Subject'])
     self.assertEqual('test rationale',
                      notification['X-Launchpad-Message-Rationale'])
     self.assertIs(None, notification['Precedence'])
     self.assertTrue('launchpad' in notification['Message-ID'])
     self.assertEqual(
         '\n'.join([
             '%s' % body, '-- ', 'This message was sent from Launchpad by',
             'Me (http://launchpad.dev/~me)', 'test reason.',
             'For more information see',
             'https://help.launchpad.net/YourAccount/ContactingPeople'
         ]), notification.get_payload())
コード例 #7
0
 def setUp(self):
     super(TestMailingListImportScript, self).setUp()
     # Since these tests involve two processes, the setup transaction must
     # be committed, otherwise the script won't see the changes.
     transaction.commit()
     # Make sure the mailbox is empty.
     pop_notifications()
コード例 #8
0
    def test_process_for_imported_branch(self):
        """Make sure that the database user is able refer to import branches.

        Import branches have different permission checks than other branches.

        Permission to mark a merge proposal as approved checks launchpad.Edit
        of the target branch, or membership of the review team on the target
        branch.  For import branches launchpad.Edit also checks the registrant
        of the code import if there is one, and membership of vcs-imports.  So
        if someone is attempting to review something on an import branch, but
        they don't have launchpad.Edit but are a member of the review team,
        then a check against the code import is done.
        """
        mail = self.factory.makeSignedMessage(body=' merge approved')
        code_import = self.factory.makeCodeImport()
        bmp = self.factory.makeBranchMergeProposal(
            target_branch=code_import.branch)
        email_addr = bmp.address
        switch_dbuser(config.processmail.dbuser)
        pop_notifications()
        self.code_handler.process(mail, email_addr, None)
        notification = pop_notifications()[0]
        # The returned message is a multipart message, the first part is
        # the message, and the second is the original message.
        message, original = notification.get_payload()
        self.assertTrue(
            "You are not a reviewer for the branch" in
            message.get_payload(decode=True))
コード例 #9
0
 def got_status(ignored):
     if expected_notification:
         self.failIf(
             len(pop_notifications()) == 0, "No notifications received")
     else:
         self.failIf(
             len(pop_notifications()) > 0, "Notifications received")
コード例 #10
0
 def test_run_branches_empty(self):
     """If the branches are empty, we tell the user."""
     # If the job has been waiting for a significant period of time (15
     # minutes for now), we run the job anyway.  The checkReady method
     # then raises and this is caught as a user error by the job system,
     # and as such sends an email to the error recipients, which for this
     # job is the merge proposal registrant.
     eric = self.factory.makePerson(name='eric', email='*****@*****.**')
     bmp = self.factory.makeBranchMergeProposal(registrant=eric)
     job = UpdatePreviewDiffJob.create(bmp)
     pop_notifications()
     JobRunner([job]).runAll()
     [email] = pop_notifications()
     self.assertEqual('Eric <*****@*****.**>', email['to'])
     self.assertEqual(
         'Launchpad error while generating the diff for a merge proposal',
         email['subject'])
     branch = bmp.source_branch
     self.assertEqual(
         'Launchpad encountered an error during the following operation: '
         'generating the diff for a merge proposal.  '
         'The source branch of http://code.launchpad.dev/~%s/%s/%s/'
         '+merge/%d has no revisions.' %
         (branch.owner.name, branch.target.name, branch.name, bmp.id),
         email.get_payload(decode=True))
コード例 #11
0
 def test_run_sends_email(self):
     """MergeProposalCreationJob.run sends an email."""
     bmp = self.createProposalWithEmptyBranches()
     job = MergeProposalNeedsReviewEmailJob.create(bmp)
     self.assertEqual([], pop_notifications())
     with dbuser("merge-proposal-jobs"):
         JobRunner([job]).runAll()
     self.assertEqual(2, len(pop_notifications()))
コード例 #12
0
 def test_run_sends_email(self):
     """MergeProposalCreationJob.run sends an email."""
     self.useBzrBranches(direct_database=True)
     bmp = self.createProposalWithEmptyBranches()
     job = MergeProposalNeedsReviewEmailJob.create(bmp)
     self.assertEqual([], pop_notifications())
     job.run()
     self.assertEqual(2, len(pop_notifications()))
コード例 #13
0
 def got_status(ignored):
     if expected_notification:
         self.failIf(
             len(pop_notifications()) == 0,
             "No notifications received")
     else:
         self.failIf(
             len(pop_notifications()) > 0,
             "Notifications received")
コード例 #14
0
 def make_product_user(self, licenses):
     user = self.factory.makePerson(name='registrant',
                                    email='*****@*****.**')
     login_person(user)
     product = self.factory.makeProduct(name='ball',
                                        owner=user,
                                        licenses=licenses)
     pop_notifications()
     return product, user
コード例 #15
0
 def make_product_user(self, licenses):
     # Setup an a view that implements ProductLicenseMixin.
     super(LicenseNotificationTestCase, self).setUp()
     user = self.factory.makePerson(
         name='registrant', email='*****@*****.**')
     login_person(user)
     product = self.factory.makeProduct(
         name='ball', owner=user, licenses=licenses)
     pop_notifications()
     return product, user
コード例 #16
0
 def test_getMessageDispositions_discard(self):
     # List moderators can discard messages.
     team, sender, message = self.makeMailingListAndHeldMessage()
     pop_notifications()
     self.mailinglist_api.holdMessage('team', message.as_string())
     found = self.message_approval_set.getMessageByMessageID('<first-post>')
     found.discard(team.teamowner)
     self.assertEqual(PostedMessageStatus.DISCARD_PENDING, found.status)
     self.assertEqual({u'<first-post>': (u'team', 'discard')},
                      self.mailinglist_api.getMessageDispositions())
     self.assertEqual(PostedMessageStatus.DISCARDED, found.status)
コード例 #17
0
 def test_run_deactivation_aborted(self):
     # The deactivation steps and email are aborted if the commercial
     # subscription was renewed after the job was created.
     product, reviewer = self.make_notification_data(
         licenses=[License.OTHER_PROPRIETARY])
     job = CommercialExpiredJob.create(product, reviewer)
     pop_notifications()
     job.run()
     notifications = pop_notifications()
     self.assertEqual(0, len(notifications))
     self.assertIs(True, product.active)
コード例 #18
0
    def test_new_subscription_sends_email(self):
        # Creating a new subscription sends an email to all members
        # of the person or team subscribed.
        self.assertEqual(0, len(pop_notifications()))

        self.archive.newSubscription(self.subscriber,
                                     registrant=self.archive.owner)

        notifications = pop_notifications()
        self.assertEqual(1, len(notifications))
        self.assertEqual(self.subscriber.preferredemail.email,
                         notifications[0]['to'])
コード例 #19
0
 def test_getMessageDispositions_discard(self):
     # List moderators can discard messages.
     team, sender, message = self.makeMailingListAndHeldMessage()
     pop_notifications()
     self.mailinglist_api.holdMessage('team', message.as_string())
     found = self.message_approval_set.getMessageByMessageID('<first-post>')
     found.discard(team.teamowner)
     self.assertEqual(PostedMessageStatus.DISCARD_PENDING, found.status)
     self.assertEqual(
         {u'<first-post>': (u'team', 'discard')},
         self.mailinglist_api.getMessageDispositions())
     self.assertEqual(PostedMessageStatus.DISCARDED, found.status)
コード例 #20
0
    def test_new_subscription_sends_email(self):
        # Creating a new subscription sends an email to all members
        # of the person or team subscribed.
        self.assertEqual(0, len(pop_notifications()))

        self.archive.newSubscription(
            self.subscriber, registrant=self.archive.owner)

        notifications = pop_notifications()
        self.assertEqual(1, len(notifications))
        self.assertEqual(
            self.subscriber.preferredemail.email, notifications[0]['to'])
コード例 #21
0
 def test_accessible_private_bug(self):
     # Private bugs are accessible by their subscribers.
     person = self.factory.makePerson()
     with celebrity_logged_in('admin'):
         bug = getUtility(IBugSet).get(4)
         bug.setPrivate(True, person)
         bug.subscribe(person, person)
     # Drop the notifications from celebrity_logged_in.
     pop_notifications()
     message = self.getFailureForMessage('*****@*****.**',
                                         from_address=removeSecurityProxy(
                                             person.preferredemail).email)
     self.assertIs(None, message)
コード例 #22
0
 def test_accessible_private_bug(self):
     # Private bugs are accessible by their subscribers.
     person = self.factory.makePerson()
     with celebrity_logged_in('admin'):
         bug = getUtility(IBugSet).get(4)
         bug.setPrivate(True, person)
         bug.subscribe(person, person)
     # Drop the notifications from celebrity_logged_in.
     pop_notifications()
     message = self.getFailureForMessage(
         '*****@*****.**',
         from_address=removeSecurityProxy(person.preferredemail).email)
     self.assertIs(None, message)
コード例 #23
0
    def testSendingCancellationEmail(self):
        """Test that when a token is deactivated, its user gets an email.

        The email must contain the right headers and text.
        """
        subs, tokens = self.setupDummyTokens()
        script = self.getScript()

        # Clear out any existing email.
        pop_notifications()

        script.sendCancellationEmail(tokens[0])

        num_emails = len(stub.test_emails)
        self.assertEqual(
            num_emails, 1, "Expected 1 email, got %s" % num_emails)

        [email] = pop_notifications()
        self.assertEqual(
            email['Subject'],
            "PPA access cancelled for PPA named myppa for Joe Smith")
        self.assertEqual(email['To'], "*****@*****.**")
        self.assertEqual(
            email['From'],
            "PPA named myppa for Joe Smith <*****@*****.**>")
        self.assertEqual(email['Sender'], "*****@*****.**")

        body = email.get_payload()
        self.assertEqual(
            body,
            "Hello Sample Person,\n\n"
            "Launchpad: cancellation of archive access\n"
            "-----------------------------------------\n\n"
            "Your access to the private software archive "
                "\"PPA named myppa for Joe\nSmith\", "
            "which is hosted by Launchpad, has been "
                "cancelled.\n\n"
            "You will now no longer be able to download software from this "
                "archive.\n"
            "If you think this cancellation is in error, you should contact "
                "the owner\n"
            "of the archive to verify it.\n\n"
            "You can contact the archive owner by visiting their Launchpad "
                "page here:\n\n"
            "<http://launchpad.dev/~joe>\n\n"
            "If you have any concerns you can contact the Launchpad team by "
                "emailing\n"
            "[email protected]\n\n"
            "Regards,\n"
            "The Launchpad team")
コード例 #24
0
 def test_new_list_notification(self):
     team = self.factory.makeTeam(name='team')
     member = self.factory.makePerson()
     with person_logged_in(team.teamowner):
         team.addMember(member, reviewer=team.teamowner)
         pop_notifications()
         self.factory.makeMailingList(team, team.teamowner)
     notifications = pop_notifications()
     self.assertEqual(2, len(notifications))
     self.assertEqual(
         'New Mailing List for Team', notifications[0]['subject'])
     self.assertTextMatchesExpressionIgnoreWhitespace(
         '.*To subscribe:.*http://launchpad.dev/~.*/\+editemails.*',
         notifications[0].get_payload())
コード例 #25
0
 def test_new_list_notification(self):
     team = self.factory.makeTeam(name='team')
     member = self.factory.makePerson()
     with person_logged_in(team.teamowner):
         team.addMember(member, reviewer=team.teamowner)
         pop_notifications()
         self.factory.makeMailingList(team, team.teamowner)
     notifications = pop_notifications()
     self.assertEqual(2, len(notifications))
     self.assertEqual(
         'New Mailing List for Team', notifications[0]['subject'])
     self.assertTextMatchesExpressionIgnoreWhitespace(
         '.*To subscribe:.*http://launchpad.dev/~.*/\+editmailinglists.*',
         notifications[0].get_payload())
コード例 #26
0
    def testNoEmailOnCancellationForSuppressedArchive(self):
        """No email should be sent if the archive has
        suppress_subscription_notifications set."""
        subs, tokens = self.setupDummyTokens()
        token = tokens[0]
        token.archive.suppress_subscription_notifications = True
        script = self.getScript()

        # Clear out any existing email.
        pop_notifications()

        script.sendCancellationEmail(token)

        self.assertEmailQueueLength(0)
コード例 #27
0
 def test_run(self):
     # Smoke test that run() can make the email from the template and data.
     product, reviewer = self.make_notification_data(
         licenses=[License.OTHER_PROPRIETARY])
     commercial_subscription = product.commercial_subscription
     if self.EXPIRE_SUBSCRIPTION:
         self.expire_commercial_subscription(product)
     iso_date = commercial_subscription.date_expires.date().isoformat()
     job = self.JOB_CLASS.create(product, reviewer)
     pop_notifications()
     job.run()
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     self.assertIn(iso_date, notifications[0].get_payload())
コード例 #28
0
 def test_run(self):
     # sendEmailToMaintainer() sends an email to the maintainers.
     data = self.make_notification_data()
     job = ProductNotificationJob.create(*data)
     product, email_template_name, subject, reviewer = data
     [address] = job.recipients.getEmails()
     pop_notifications()
     job.run()
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     self.assertEqual(address, notifications[0]['To'])
     self.assertEqual(subject, notifications[0]['Subject'])
     self.assertIn(
         'Launchpad <*****@*****.**>', notifications[0]['From'])
コード例 #29
0
    def testSendingCancellationEmail(self):
        """Test that when a token is deactivated, its user gets an email.

        The email must contain the right headers and text.
        """
        subs, tokens = self.setupDummyTokens()
        script = self.getScript()

        # Clear out any existing email.
        pop_notifications()

        script.sendCancellationEmail(tokens[0])

        num_emails = len(stub.test_emails)
        self.assertEqual(num_emails, 1,
                         "Expected 1 email, got %s" % num_emails)

        [email] = pop_notifications()
        self.assertEqual(
            email['Subject'],
            "PPA access cancelled for PPA named myppa for Joe Smith")
        self.assertEqual(email['To'], "*****@*****.**")
        self.assertEqual(
            email['From'],
            "PPA named myppa for Joe Smith <*****@*****.**>")
        self.assertEqual(email['Sender'], "*****@*****.**")

        body = email.get_payload()
        self.assertEqual(
            body, "Hello Sample Person,\n\n"
            "Launchpad: cancellation of archive access\n"
            "-----------------------------------------\n\n"
            "Your access to the private software archive "
            "\"PPA named myppa for Joe\nSmith\", "
            "which is hosted by Launchpad, has been "
            "cancelled.\n\n"
            "You will now no longer be able to download software from this "
            "archive.\n"
            "If you think this cancellation is in error, you should contact "
            "the owner\n"
            "of the archive to verify it.\n\n"
            "You can contact the archive owner by visiting their Launchpad "
            "page here:\n\n"
            "<http://launchpad.dev/~joe>\n\n"
            "If you have any concerns you can contact the Launchpad team by "
            "emailing\n"
            "[email protected]\n\n"
            "Regards,\n"
            "The Launchpad team")
コード例 #30
0
 def test_wrapping(self):
     self.factory.makePerson(email='*****@*****.**')
     user = self.factory.makePerson()
     recipients_set = NotificationRecipientSet()
     recipients_set.add(user, 'test reason', 'test rationale')
     pop_notifications()
     body = 'Can you help me? ' * 8
     send_direct_contact_email('*****@*****.**', recipients_set, 'subject', body)
     notifications = pop_notifications()
     body, footer = notifications[0].get_payload().split('-- ')
     self.assertEqual(
         'Can you help me? Can you help me? Can you help me? '
         'Can you help me? Can\n'
         'you help me? Can you help me? Can you help me? '
         'Can you help me?\n', body)
コード例 #31
0
 def test_name_utf8_encoding(self):
     # Names are encoded in the From and To headers.
     self.factory.makePerson(email='*****@*****.**', displayname=u'sn\xefrf')
     user = self.factory.makePerson(email='*****@*****.**',
                                    displayname=u'pti\xedng')
     recipients_set = NotificationRecipientSet()
     recipients_set.add(user, 'test reason', 'test rationale')
     pop_notifications()
     send_direct_contact_email('*****@*****.**', recipients_set, 'test', 'test')
     notifications = pop_notifications()
     notification = notifications[0]
     self.assertEqual('=?utf-8?b?c27Dr3Jm?= <*****@*****.**>',
                      notification['From'])
     self.assertEqual('=?utf-8?q?pti=C3=ADng?= <*****@*****.**>',
                      notification['To'])
コード例 #32
0
 def test_name_utf8_encoding(self):
     # Names are encoded in the From and To headers.
     self.factory.makePerson(email='*****@*****.**', displayname=u'sn\xefrf')
     user = self.factory.makePerson(
         email='*****@*****.**', displayname=u'pti\xedng')
     recipients_set = NotificationRecipientSet()
     recipients_set.add(user, 'test reason', 'test rationale')
     pop_notifications()
     send_direct_contact_email('*****@*****.**', recipients_set, 'test', 'test')
     notifications = pop_notifications()
     notification = notifications[0]
     self.assertEqual(
         '=?utf-8?b?c27Dr3Jm?= <*****@*****.**>', notification['From'])
     self.assertEqual(
         '=?utf-8?q?pti=C3=ADng?= <*****@*****.**>', notification['To'])
コード例 #33
0
 def test_nominateReview_no_job_if_work_in_progress(self):
     # When a reviewer is nominated for a proposal that is work in
     # progress, no email job is created.
     bmp = self.factory.makeBranchMergeProposal(
         set_state=BranchMergeProposalStatus.WORK_IN_PROGRESS)
     reviewer = self.factory.makePerson()
     pop_notifications()
     with person_logged_in(bmp.registrant):
         bmp.nominateReviewer(reviewer, bmp.registrant, None)
     # No email is sent.
     sent_mail = pop_notifications()
     self.assertEqual([], sent_mail)
     # No job created.
     job_count = self.getReviewEmailJobs(bmp).count()
     self.assertEqual(0, job_count)
コード例 #34
0
 def test_nominateReview_no_job_if_work_in_progress(self):
     # When a reviewer is nominated for a proposal that is work in
     # progress, no email job is created.
     bmp = self.factory.makeBranchMergeProposal(
         set_state=BranchMergeProposalStatus.WORK_IN_PROGRESS)
     reviewer = self.factory.makePerson()
     pop_notifications()
     with person_logged_in(bmp.registrant):
         bmp.nominateReviewer(reviewer, bmp.registrant, None)
     # No email is sent.
     sent_mail = pop_notifications()
     self.assertEqual([], sent_mail)
     # No job created.
     job_count = self.getReviewEmailJobs(bmp).count()
     self.assertEqual(0, job_count)
コード例 #35
0
 def test_sendEmailToMaintainer(self):
     # sendEmailToMaintainer() sends an email to the maintainers.
     data = self.make_notification_data()
     job = ProductNotificationJob.create(*data)
     product, email_template_name, subject, reviewer = data
     team, team_admin = self.make_maintainer_team(product)
     addresses = job.recipients.getEmails()
     pop_notifications()
     job.sendEmailToMaintainer(email_template_name, 'frog', '*****@*****.**')
     notifications = pop_notifications()
     self.assertEqual(2, len(notifications))
     self.assertEqual(addresses[0], notifications[0]['To'])
     self.assertEqual(addresses[1], notifications[1]['To'])
     self.assertEqual('*****@*****.**', notifications[1]['From'])
     self.assertEqual('frog', notifications[1]['Subject'])
コード例 #36
0
 def test_product_licenses_modified_licenses_other_dont_know(self):
     product, event = self.make_product_event([License.DONT_KNOW])
     product_licenses_modified(product, event)
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     request = get_current_browser_request()
     self.assertEqual(0, len(request.response.notifications))
コード例 #37
0
    def test_invalid_signature(self):
        """Invalid signature should not be handled as an OOPs.

        It should produce a message explaining to the user what went wrong.
        """
        person = self.factory.makePerson()
        transaction.commit()
        email_address = person.preferredemail.email
        invalid_body = (
            "-----BEGIN PGP SIGNED MESSAGE-----\n"
            "Hash: SHA1\n\n"
            "Body\n"
            "-----BEGIN PGP SIGNATURE-----\n"
            "Not a signature.\n"
            "-----END PGP SIGNATURE-----\n"
        )
        ctrl = MailController(email_address, "*****@*****.**", "subject", invalid_body, bulk=False)
        ctrl.send()
        handleMail()
        self.assertEqual([], self.oopses)
        [notification] = pop_notifications()
        body = notification.get_payload()[0].get_payload(decode=True)
        self.assertIn(
            "An error occurred while processing a mail you sent to "
            "Launchpad's email\ninterface.\n\n\n"
            "Error message:\n\nSignature couldn't be verified: "
            "(7, 58, u'No data')",
            body,
        )
コード例 #38
0
 def test_sendall_first_failure_strips_attachments(self):
     # If sending an email fails, we try again without the (almost
     # certainly) large attachment.
     recipients = {
         self.factory.makePerson(name='good', email='*****@*****.**'):
             FakeSubscription(),
         self.factory.makePerson(name='bad', email='*****@*****.**'):
             FakeSubscription()}
     # Only raise the first time for bob.
     controller_factory = RaisingMailControllerFactory(
         '*****@*****.**', 1)
     mailer = AttachmentMailer(
         'subject', None, recipients, '*****@*****.**',
         mail_controller_class=controller_factory)
     mailer.sendAll()
     # Both emails are sent.
     notifications = pop_notifications()
     self.assertEqual(2, len(notifications))
     bad, good = notifications
     # The good email as the expected attachments.
     good_parts = good.get_payload()
     self.assertEqual(3, len(good_parts))
     self.assertEqual(
         'attachment1', good_parts[1].get_payload(decode=True))
     self.assertEqual(
         'attachment2', good_parts[2].get_payload(decode=True))
     # The bad email has the normal attachments stripped off and replaced
     # with the text.
     bad_parts = bad.get_payload()
     self.assertEqual(2, len(bad_parts))
     self.assertEqual(
         'Excessively large attachments removed.',
         bad_parts[1].get_payload(decode=True))
コード例 #39
0
 def test_retry_delay(self):
     # The job is retried every minute, unless it just made one of its
     # first four attempts to poll the status endpoint, in which case the
     # delays are 15/15/30/30 seconds.
     self.useFixture(FakeLogger())
     snapbuild = self.makeSnapBuild()
     job = SnapStoreUploadJob.create(snapbuild)
     client = FakeSnapStoreClient()
     client.upload.failure = UploadFailedResponse("Proxy error",
                                                  can_retry=True)
     self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient))
     with dbuser(config.ISnapStoreUploadJobSource.dbuser):
         JobRunner([job]).runAll()
     self.assertNotIn("status_url", job.metadata)
     self.assertEqual(timedelta(seconds=60), job.retry_delay)
     job.scheduled_start = None
     client.upload.failure = None
     client.upload.result = self.status_url
     client.checkStatus.failure = UploadNotScannedYetResponse()
     for expected_delay in (15, 15, 30, 30, 60):
         with dbuser(config.ISnapStoreUploadJobSource.dbuser):
             JobRunner([job]).runAll()
         self.assertIn("status_url", job.snapbuild.store_upload_metadata)
         self.assertIsNone(job.store_url)
         self.assertEqual(timedelta(seconds=expected_delay),
                          job.retry_delay)
         job.scheduled_start = None
     client.checkStatus.failure = None
     client.checkStatus.result = (self.store_url, 1)
     with dbuser(config.ISnapStoreUploadJobSource.dbuser):
         JobRunner([job]).runAll()
     self.assertEqual(self.store_url, job.store_url)
     self.assertIsNone(job.error_message)
     self.assertEqual([], pop_notifications())
     self.assertEqual(JobStatus.COMPLETED, job.job.status)
コード例 #40
0
    def test_nominateReview_email_content(self):
        # The email that is sent contains the description of the proposal, and
        # a link to the proposal.
        bmp = self.factory.makeBranchMergeProposal(
            set_state=BranchMergeProposalStatus.NEEDS_REVIEW)
        reviewer = self.factory.makePerson()
        with person_logged_in(bmp.registrant):
            bmp.description = 'This branch is awesome.'
            bmp.nominateReviewer(reviewer, bmp.registrant, None)
        review_request_job = self.getReviewNotificationEmail(bmp)
        review_request_job.run()
        [sent_mail] = pop_notifications()
        expected = dedent("""\
            You have been requested to review the proposed merge of"""
            """ %(source)s into %(target)s.

            For more details, see:
            %(bmp)s

            This branch is awesome.

            --\x20
            %(bmp)s
            You are requested to review the proposed merge of %(source)s"""
            """ into %(target)s.
            """ % {
                'source': bmp.source_branch.bzr_identity,
                'target': bmp.target_branch.bzr_identity,
                'bmp': canonical_url(bmp)})
        self.assertEqual(expected, sent_mail.get_payload(decode=True))
コード例 #41
0
    def testNoEmailOnCancellationForSuppressedArchive(self):
        """No email should be sent if the archive has
        suppress_subscription_notifications set."""
        subs, tokens = self.setupDummyTokens()
        token = tokens[0]
        token.archive.suppress_subscription_notifications = True
        script = self.getScript()

        # Clear out any existing email.
        pop_notifications()

        script.sendCancellationEmail(token)

        num_emails = len(stub.test_emails)
        self.assertEqual(
            num_emails, 0, "Expected 0 emails, got %s" % num_emails)
コード例 #42
0
    def test_nominateReview_email_content(self):
        # The email that is sent contains the description of the proposal, and
        # a link to the proposal.
        bmp = self.factory.makeBranchMergeProposal(
            set_state=BranchMergeProposalStatus.NEEDS_REVIEW)
        reviewer = self.factory.makePerson()
        with person_logged_in(bmp.registrant):
            bmp.description = 'This branch is awesome.'
            bmp.nominateReviewer(reviewer, bmp.registrant, None)
        review_request_job = self.getReviewNotificationEmail(bmp)
        with dbuser(config.IBranchMergeProposalJobSource.dbuser):
            review_request_job.run()
        [sent_mail] = pop_notifications()
        expected = dedent("""\
            You have been requested to review the proposed merge of"""
            """ %(source)s into %(target)s.

            For more details, see:
            %(bmp)s

            This branch is awesome.

            --\x20
            You are requested to review the proposed merge of %(source)s"""
            """ into %(target)s.
            """ % {
                'source': bmp.source_branch.bzr_identity,
                'target': bmp.target_branch.bzr_identity,
                'bmp': canonical_url(bmp)})
        self.assertEqual(expected, sent_mail.get_payload(decode=True))
コード例 #43
0
 def test_wrapping(self):
     self.factory.makePerson(email='*****@*****.**')
     user = self.factory.makePerson()
     recipients_set = NotificationRecipientSet()
     recipients_set.add(user, 'test reason', 'test rationale')
     pop_notifications()
     body = 'Can you help me? ' * 8
     send_direct_contact_email('*****@*****.**', recipients_set, 'subject', body)
     notifications = pop_notifications()
     body, footer = notifications[0].get_payload().split('-- ')
     self.assertEqual(
         'Can you help me? Can you help me? Can you help me? '
         'Can you help me? Can\n'
         'you help me? Can you help me? Can you help me? '
         'Can you help me?\n',
         body)
コード例 #44
0
 def test_product_licenses_modified_licenses_other_open_source(self):
     product, event = self.make_product_event([License.OTHER_OPEN_SOURCE])
     product_licenses_modified(product, event)
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     request = get_current_browser_request()
     self.assertEqual(0, len(request.response.notifications))
コード例 #45
0
 def test_product_licenses_modified_licenses_other_proprietary(self):
     product, event = self.make_product_event([License.OTHER_PROPRIETARY])
     product_licenses_modified(product, event)
     notifications = pop_notifications()
     self.assertEqual(1, len(notifications))
     request = get_current_browser_request()
     self.assertEqual(1, len(request.response.notifications))
コード例 #46
0
    def _test_handleStatus_notifies(self, status):
        # An email notification is sent for a given build status if
        # notifications are allowed for that status.
        expected_notification = (
            status in self.behaviour.ALLOWED_STATUS_NOTIFICATIONS)

        with dbuser(config.builddmaster.dbuser):
            yield self.behaviour.handleStatus(self.build.buildqueue_record,
                                              status, {})

        if expected_notification:
            self.assertNotEqual(0, len(pop_notifications()),
                                "Notifications received")
        else:
            self.assertEqual(0, len(pop_notifications()),
                             "Notifications received")
コード例 #47
0
 def test_send_known_license(self):
     # A known licence does not generate an email.
     product, user = self.make_product_user([License.GNU_GPL_V2])
     notification = LicenseNotification(product)
     result = notification.send()
     self.assertIs(False, result)
     self.assertEqual(0, len(pop_notifications()))
コード例 #48
0
 def test_product_licenses_modified_licenses_common_license(self):
     product, event = self.make_product_event([License.MIT])
     product_licenses_modified(product, event)
     notifications = pop_notifications()
     self.assertEqual(0, len(notifications))
     request = get_current_browser_request()
     self.assertEqual(0, len(request.response.notifications))
コード例 #49
0
 def test_handleStatus_ABORTED_cancels_cancelling(self):
     with dbuser(config.builddmaster.dbuser):
         self.build.updateStatus(BuildStatus.CANCELLING)
         yield self.behaviour.handleStatus(self.build.buildqueue_record,
                                           "ABORTED", {})
     self.assertEqual(0, len(pop_notifications()), "Notifications received")
     self.assertEqual(BuildStatus.CANCELLED, self.build.status)
コード例 #50
0
 def test_empty_recipient_set(self):
     # The recipient set can be empty. No messages are sent and the
     # action does not count toward the daily quota.
     self.factory.makePerson(email='*****@*****.**', name='me')
     user = self.factory.makePerson(email='*****@*****.**', name='him')
     recipients_set = NotificationRecipientSet()
     old_message = self.factory.makeSignedMessage(email_address='*****@*****.**')
     authorization = IDirectEmailAuthorization(user)
     for action in xrange(authorization.message_quota - 1):
         authorization.record(old_message)
     pop_notifications()
     send_direct_contact_email(
         '*****@*****.**', recipients_set, 'subject', 'body')
     notifications = pop_notifications()
     self.assertEqual(0, len(notifications))
     self.assertTrue(authorization.is_allowed)
コード例 #51
0
    def test_runAll_mails_user_errors(self):
        """User errors should be mailed out without oopsing.

        User errors are identified by the RunnableJob.user_error_types
        attribute.  They do not cause an oops to be recorded, and their
        error messages are mailed to interested parties verbatim.
        """
        job_1, job_2 = self.makeTwoJobs()

        class ExampleError(Exception):
            pass

        def raiseError():
            raise ExampleError('Fake exception.  Foobar, I say!')
        job_1.run = raiseError
        job_1.user_error_types = (ExampleError,)
        job_1.error_recipients = ['*****@*****.**']
        runner = JobRunner([job_1, job_2])
        runner.runAll()
        self.assertEqual([], self.oopses)
        notifications = pop_notifications()
        self.assertEqual(1, len(notifications))
        body = notifications[0].get_payload(decode=True)
        self.assertEqual(
            'Launchpad encountered an error during the following operation:'
            ' appending a string to a list.  Fake exception.  Foobar, I say!',
            body)
        self.assertEqual(
            'Launchpad error while appending a string to a list',
            notifications[0]['subject'])
コード例 #52
0
 def test_notify_from_person_override(self):
     # notify() takes an optional from_person to override the calculated
     # From: address in announcement emails.
     spr = self.factory.makeSourcePackageRelease()
     self.factory.makeSourcePackageReleaseFile(sourcepackagerelease=spr)
     archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
     pocket = PackagePublishingPocket.RELEASE
     distroseries = self.factory.makeDistroSeries()
     distroseries.changeslist = "*****@*****.**"
     blamer = self.factory.makePerson()
     from_person = self.factory.makePerson(email="*****@*****.**",
                                           displayname="Lemmy Kilmister")
     notify(blamer,
            spr, [], [],
            archive,
            distroseries,
            pocket,
            action='accepted',
            announce_from_person=from_person)
     notifications = pop_notifications()
     self.assertEqual(2, len(notifications))
     # The first notification is to the blamer, the second notification is
     # to the announce list, which is the one that gets the overridden
     # From:
     self.assertEqual("Lemmy Kilmister <*****@*****.**>",
                      notifications[1]["From"])
コード例 #53
0
 def test_notify_from_person_override_with_unicode_names(self):
     # notify() takes an optional from_person to override the calculated
     # From: address in announcement emails. Non-ASCII real names should be
     # correctly encoded in the From heade.
     spr = self.factory.makeSourcePackageRelease()
     self.factory.makeSourcePackageReleaseFile(sourcepackagerelease=spr)
     archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
     pocket = PackagePublishingPocket.RELEASE
     distroseries = self.factory.makeDistroSeries()
     distroseries.changeslist = "*****@*****.**"
     blamer = self.factory.makePerson()
     from_person = self.factory.makePerson(email="*****@*****.**",
                                           displayname=u"Loïc Motörhead")
     notify(blamer,
            spr, [], [],
            archive,
            distroseries,
            pocket,
            action='accepted',
            announce_from_person=from_person)
     notifications = pop_notifications()
     self.assertEqual(2, len(notifications))
     # The first notification is to the blamer, the second notification is
     # to the announce list, which is the one that gets the overridden
     # From:
     self.assertEqual(
         "=?utf-8?q?Lo=C3=AFc_Mot=C3=B6rhead?= <*****@*****.**>",
         notifications[1]["From"])
コード例 #54
0
 def got_status(ignored):
     self.assertEqual(
         0, len(pop_notifications()), "Notifications received")
     self.assertEqual(BuildStatus.NEEDSBUILD, self.build.status)
     self.assertEqual(1, self.builder.failure_count)
     self.assertEqual(1, self.build.failure_count)
     self.assertIn("clean", self.slave.call_log)