예제 #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())
 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
 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())
 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()
    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()))
 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'])
 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)
    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)
    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")
 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)
 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'])
 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'])
 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)
    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))
    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))
 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))
    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))
 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)
 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"])
 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)