def extractAndAuthenticateCommands(self, signed_msg, to_addr): """Extract commands and handle special destinations. NB: The authentication is carried out against the current principal, not directly against the message. authenticateEmail must previously have been called on this thread. :returns: (final_result, add_comment_to_bug, commands) If final_result is non-none, stop processing and return this value to indicate whether the message was dealt with or not. If add_comment_to_bug, add the contents to the first bug selected. commands is a list of bug commands. """ CONTEXT = 'bug report' commands = self.getCommands(signed_msg) to_user, to_host = to_addr.split('@') add_comment_to_bug = False from_user = getUtility(ILaunchBag).user if to_user.lower() == 'help' or from_user is None: if from_user is not None and from_user.preferredemail is not None: to_address = str(from_user.preferredemail.email) else: to_address = signed_msg['From'] address = getUtility(IEmailAddressSet).getByEmail(to_address) if address is None: to_address = None if to_address is not None: self.sendHelpEmail(to_address) return True, False, None # If there are any commands, we must have strong authentication. # We send a different failure message for attempts to create a new # bug. elif to_user.lower() == 'new': ensure_not_weakly_authenticated(signed_msg, CONTEXT) elif len(commands) > 0: ensure_not_weakly_authenticated(signed_msg, CONTEXT) if to_user.lower() == 'new': commands.insert(0, BugEmailCommands.get('bug', ['new'])) elif to_user.isdigit(): # A comment to a bug. We set add_comment_to_bug to True so # that the comment gets added to the bug later. We don't add # the comment now, since we want to let the 'bug' command # handle the possible errors that can occur while getting # the bug. add_comment_to_bug = True commands.insert(0, BugEmailCommands.get('bug', [to_user])) elif to_user.lower() != 'edit': # Indicate that we didn't handle the mail. return False, False, None bug_commands = list(BugCommandGroups(commands)) return None, add_comment_to_bug, bug_commands
def processComment(self, mail, email_addr, file_alias): """Process an email and create a CodeReviewComment. The only mail command understood is 'vote', which takes 'approve', 'disapprove', or 'abstain' as values. Specifically, it takes any CodeReviewVote item value, case-insensitively. :return: True. """ user = getUtility(ILaunchBag).user try: merge_proposal = self.getBranchMergeProposal(email_addr) except NonExistantBranchMergeProposalAddress: send_process_error_notification( str(user.preferredemail.email), 'Submit Request Failure', 'There is no merge proposal at %s' % email_addr, mail) return True except BadBranchMergeProposalAddress: return False context = CodeReviewEmailCommandExecutionContext(merge_proposal, user) try: email_body_text = get_main_body(mail) commands = CodeEmailCommands.getCommands(email_body_text) processed_count = self.processCommands(context, commands) # Make sure that the email is in fact signed. if processed_count > 0: ensure_not_weakly_authenticated(mail, 'code review') message = getUtility(IMessageSet).fromEmail( mail.parsed_string, owner=getUtility(ILaunchBag).user, filealias=file_alias, parsed_message=mail) merge_proposal.createCommentFromMessage( message, context.vote, context.vote_tags, mail) except IncomingEmailError as error: send_process_error_notification( str(user.preferredemail.email), 'Submit Request Failure', error.message, mail, error.failing_command) transaction.abort() return True
def processComment(self, mail, email_addr, file_alias): """Process an email and create a CodeReviewComment. The only mail command understood is 'vote', which takes 'approve', 'disapprove', or 'abstain' as values. Specifically, it takes any CodeReviewVote item value, case-insensitively. :return: True. """ user = getUtility(ILaunchBag).user try: merge_proposal = self.getBranchMergeProposal(email_addr) except NonExistantBranchMergeProposalAddress: send_process_error_notification( str(user.preferredemail.email), 'Submit Request Failure', 'There is no merge proposal at %s' % email_addr, mail) return True except BadBranchMergeProposalAddress: return False context = CodeReviewEmailCommandExecutionContext(merge_proposal, user) try: email_body_text = get_main_body(mail) commands = CodeEmailCommands.getCommands(email_body_text) processed_count = self.processCommands(context, commands) # Make sure that the email is in fact signed. if processed_count > 0: ensure_not_weakly_authenticated(mail, 'code review') message = getUtility(IMessageSet).fromEmail( mail.parsed_string, owner=getUtility(ILaunchBag).user, filealias=file_alias, parsed_message=mail) merge_proposal.createCommentFromMessage(message, context.vote, context.vote_tags, mail) except IncomingEmailError as error: send_process_error_notification(str(user.preferredemail.email), 'Submit Request Failure', error.message, mail, error.failing_command) transaction.abort() return True
def test_normal_user(self): # If the current principal doesn't provide # IWeaklyAuthenticatedPrincipal, then we are good. signed_msg = self.factory.makeSignedMessage() ensure_not_weakly_authenticated(signed_msg, 'test case')