Search in sources :

Example 6 with MailMessage

use of com.google.gerrit.mail.MailMessage in project gerrit by GerritCodeReview.

the class Pop3MailReceiver method handleEmails.

/**
 * Opens a connection to the mail server, removes emails where deletion is pending, reads new
 * email and closes the connection.
 *
 * @param async determines if processing messages should happen asynchronously
 * @throws MailTransferException in case of a known transport failure
 * @throws IOException in case of a low-level transport failure
 */
@Override
public synchronized void handleEmails(boolean async) throws MailTransferException, IOException {
    POP3Client pop3;
    if (mailSettings.encryption != Encryption.NONE) {
        pop3 = new POP3SClient(mailSettings.encryption.name(), true);
    } else {
        pop3 = new POP3Client();
    }
    if (mailSettings.port > 0) {
        pop3.setDefaultPort(mailSettings.port);
    }
    pop3.connect(mailSettings.host);
    try {
        if (!pop3.login(mailSettings.username, mailSettings.password)) {
            throw new MailTransferException("Could not login to POP3 email server. Check username and password");
        }
        try {
            POP3MessageInfo[] messages = pop3.listMessages();
            if (messages == null) {
                throw new MailTransferException("Could not retrieve message list via POP3");
            }
            logger.atInfo().log("Received %d messages via POP3", messages.length);
            // Fetch messages
            List<MailMessage> mailMessages = new ArrayList<>();
            for (POP3MessageInfo msginfo : messages) {
                if (msginfo == null) {
                    // Message was deleted
                    continue;
                }
                try (BufferedReader reader = (BufferedReader) pop3.retrieveMessage(msginfo.number)) {
                    if (reader == null) {
                        throw new MailTransferException("Could not retrieve POP3 message header for message " + msginfo.identifier);
                    }
                    int[] message = fetchMessage(reader);
                    MailMessage mailMessage = RawMailParser.parse(message);
                    // 822 and delete the message if deletion is pending.
                    if (pendingDeletion.contains(mailMessage.id())) {
                        if (pop3.deleteMessage(msginfo.number)) {
                            pendingDeletion.remove(mailMessage.id());
                        } else {
                            logger.atSevere().log("Could not delete message %d", msginfo.number);
                        }
                    } else {
                        // Process message further
                        mailMessages.add(mailMessage);
                    }
                } catch (MailParsingException e) {
                    logger.atSevere().log("Could not parse message %d", msginfo.number);
                }
            }
            dispatchMailProcessor(mailMessages, async);
        } finally {
            pop3.logout();
        }
    } finally {
        pop3.disconnect();
    }
}
Also used : POP3SClient(org.apache.commons.net.pop3.POP3SClient) POP3MessageInfo(org.apache.commons.net.pop3.POP3MessageInfo) MailMessage(com.google.gerrit.mail.MailMessage) MailParsingException(com.google.gerrit.mail.MailParsingException) POP3Client(org.apache.commons.net.pop3.POP3Client) ArrayList(java.util.ArrayList) BufferedReader(java.io.BufferedReader)

Example 7 with MailMessage

use of com.google.gerrit.mail.MailMessage in project gerrit by GerritCodeReview.

the class MailProcessor method persistComments.

private void persistComments(BatchUpdate.Factory buf, MailMessage message, MailMetadata metadata, Account.Id sender) throws UpdateException, RestApiException {
    try (ManualRequestContext ctx = oneOffRequestContext.openAs(sender)) {
        List<ChangeData> changeDataList = queryProvider.get().enforceVisibility(true).byLegacyChangeId(Change.id(metadata.changeNumber));
        if (changeDataList.isEmpty()) {
            sendRejectionEmail(message, InboundEmailError.CHANGE_NOT_FOUND);
            return;
        }
        if (changeDataList.size() != 1) {
            logger.atSevere().log("Message %s references unique change %s," + " but there are %d matching changes in the index." + " Will delete message.", message.id(), metadata.changeNumber, changeDataList.size());
            sendRejectionEmail(message, InboundEmailError.INTERNAL_EXCEPTION);
            return;
        }
        ChangeData cd = Iterables.getOnlyElement(changeDataList);
        if (existingMessageIds(cd).contains(message.id())) {
            logger.atInfo().log("Message %s was already processed. Will delete message.", message.id());
            return;
        }
        // Get all comments; filter and sort them to get the original list of
        // comments from the outbound email.
        // TODO(hiesel) Also filter by original comment author.
        Collection<HumanComment> comments = cd.publishedComments().stream().filter(c -> (c.writtenOn.getTime() / 1000) == (metadata.timestamp.getTime() / 1000)).sorted(CommentsUtil.COMMENT_ORDER).collect(toList());
        Project.NameKey project = cd.project();
        // If URL is not defined, we won't be able to parse line comments. We still attempt to get the
        // other ones.
        String changeUrl = urlFormatter.get().getChangeViewUrl(cd.project(), cd.getId()).orElse("http://gerrit.invalid/");
        List<MailComment> parsedComments;
        if (useHtmlParser(message)) {
            parsedComments = HtmlParser.parse(message, comments, changeUrl);
        } else {
            parsedComments = TextParser.parse(message, comments, changeUrl);
        }
        if (parsedComments.isEmpty()) {
            logger.atWarning().log("Could not parse any comments from %s. Will delete message.", message.id());
            sendRejectionEmail(message, InboundEmailError.PARSING_ERROR);
            return;
        }
        ImmutableList<CommentForValidation> parsedCommentsForValidation = parsedComments.stream().map(comment -> CommentForValidation.create(CommentForValidation.CommentSource.HUMAN, MAIL_COMMENT_TYPE_TO_VALIDATION_TYPE.get(comment.getType()), comment.getMessage(), comment.getMessage().length())).collect(ImmutableList.toImmutableList());
        CommentValidationContext commentValidationCtx = CommentValidationContext.create(cd.change().getChangeId(), cd.change().getProject().get(), cd.change().getDest().branch());
        ImmutableList<CommentValidationFailure> commentValidationFailures = PublishCommentUtil.findInvalidComments(commentValidationCtx, commentValidators, parsedCommentsForValidation);
        if (!commentValidationFailures.isEmpty()) {
            sendRejectionEmail(message, InboundEmailError.COMMENT_REJECTED);
            return;
        }
        Op o = new Op(PatchSet.id(cd.getId(), metadata.patchSet), parsedComments, message.id());
        BatchUpdate batchUpdate = buf.create(project, ctx.getUser(), TimeUtil.now());
        batchUpdate.addOp(cd.getId(), o);
        batchUpdate.execute();
    }
}
Also used : DynamicItem(com.google.gerrit.extensions.registration.DynamicItem) Inject(com.google.inject.Inject) HumanComment(com.google.gerrit.entities.HumanComment) UpdateException(com.google.gerrit.server.update.UpdateException) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) Map(java.util.Map) RetryHelper(com.google.gerrit.server.update.RetryHelper) UrlFormatter(com.google.gerrit.server.config.UrlFormatter) Side(com.google.gerrit.extensions.client.Side) OneOffRequestContext(com.google.gerrit.server.util.OneOffRequestContext) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) Account(com.google.gerrit.entities.Account) MailFilter(com.google.gerrit.server.mail.MailFilter) Set(java.util.Set) ApprovalsUtil(com.google.gerrit.server.approval.ApprovalsUtil) ChangeData(com.google.gerrit.server.query.change.ChangeData) List(java.util.List) HtmlParser(com.google.gerrit.mail.HtmlParser) Emails(com.google.gerrit.server.account.Emails) CommentAdded(com.google.gerrit.server.extensions.events.CommentAdded) PluginSetContext(com.google.gerrit.server.plugincontext.PluginSetContext) InternalChangeQuery(com.google.gerrit.server.query.change.InternalChangeQuery) Optional(java.util.Optional) MailMetadata(com.google.gerrit.mail.MailMetadata) BatchUpdateOp(com.google.gerrit.server.update.BatchUpdateOp) FluentLogger(com.google.common.flogger.FluentLogger) ChangeMessagesUtil(com.google.gerrit.server.ChangeMessagesUtil) Singleton(com.google.inject.Singleton) AccountCache(com.google.gerrit.server.account.AccountCache) Iterables(com.google.common.collect.Iterables) CommentValidationContext(com.google.gerrit.extensions.validators.CommentValidationContext) TextParser(com.google.gerrit.mail.TextParser) PublishCommentUtil(com.google.gerrit.server.PublishCommentUtil) UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) CommentsUtil(com.google.gerrit.server.CommentsUtil) CommentForValidation(com.google.gerrit.extensions.validators.CommentForValidation) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) PATCHSET_LEVEL(com.google.gerrit.entities.Patch.PATCHSET_LEVEL) Strings(com.google.common.base.Strings) MessageIdGenerator(com.google.gerrit.server.mail.send.MessageIdGenerator) ImmutableList(com.google.common.collect.ImmutableList) PostUpdateContext(com.google.gerrit.server.update.PostUpdateContext) Change(com.google.gerrit.entities.Change) PatchSet(com.google.gerrit.entities.PatchSet) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) MailComment(com.google.gerrit.mail.MailComment) ChangeContext(com.google.gerrit.server.update.ChangeContext) Extension(com.google.gerrit.extensions.registration.Extension) InboundEmailError(com.google.gerrit.server.mail.send.InboundEmailRejectionSender.InboundEmailError) MailMessage(com.google.gerrit.mail.MailMessage) MailHeaderParser(com.google.gerrit.mail.MailHeaderParser) StorageException(com.google.gerrit.exceptions.StorageException) CommentValidationFailure(com.google.gerrit.extensions.validators.CommentValidationFailure) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) ManualRequestContext(com.google.gerrit.server.util.ManualRequestContext) Collectors.toList(java.util.stream.Collectors.toList) Provider(com.google.inject.Provider) DynamicMap(com.google.gerrit.extensions.registration.DynamicMap) Project(com.google.gerrit.entities.Project) TimeUtil(com.google.gerrit.server.util.time.TimeUtil) CommentValidator(com.google.gerrit.extensions.validators.CommentValidator) AccountState(com.google.gerrit.server.account.AccountState) PatchSetUtil(com.google.gerrit.server.PatchSetUtil) EmailReviewComments(com.google.gerrit.server.change.EmailReviewComments) InboundEmailRejectionSender(com.google.gerrit.server.mail.send.InboundEmailRejectionSender) BatchUpdateOp(com.google.gerrit.server.update.BatchUpdateOp) MailComment(com.google.gerrit.mail.MailComment) CommentForValidation(com.google.gerrit.extensions.validators.CommentForValidation) CommentValidationContext(com.google.gerrit.extensions.validators.CommentValidationContext) ChangeData(com.google.gerrit.server.query.change.ChangeData) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) Project(com.google.gerrit.entities.Project) CommentValidationFailure(com.google.gerrit.extensions.validators.CommentValidationFailure) ManualRequestContext(com.google.gerrit.server.util.ManualRequestContext) HumanComment(com.google.gerrit.entities.HumanComment)

Aggregations

MailMessage (com.google.gerrit.mail.MailMessage)7 ArrayList (java.util.ArrayList)3 Test (org.junit.Test)3 GerritConfig (com.google.gerrit.acceptance.config.GerritConfig)2 ReviewInput (com.google.gerrit.extensions.api.changes.ReviewInput)2 CommentInput (com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput)2 RobotCommentInput (com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput)2 ChangeInfo (com.google.gerrit.extensions.common.ChangeInfo)2 CommentInfo (com.google.gerrit.extensions.common.CommentInfo)2 RestApiException (com.google.gerrit.extensions.restapi.RestApiException)2 MailParsingException (com.google.gerrit.mail.MailParsingException)2 UpdateException (com.google.gerrit.server.update.UpdateException)2 Message (com.google.gerrit.testing.FakeEmailSender.Message)2 Strings (com.google.common.base.Strings)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 Iterables (com.google.common.collect.Iterables)1 FluentLogger (com.google.common.flogger.FluentLogger)1 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)1 Account (com.google.gerrit.entities.Account)1