{"record":{"id":"cb9a4c17e0e2de43","repo":"theonedev/onedev","slug":"not-eligible-to-comment-issue","errorCode":null,"errorMessage":"Not eligible to comment issue: ","messagePattern":"Not eligible to comment issue: ","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":403,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/mail/DefaultMailService.java","lineNumber":525,"sourceCode":"\t\t\t\t\t\t\t\t\t\tbindings.put(\"issue\", involvedIssue);\n\n\t\t\t\t\t\t\t\t\t\tString htmlBody = EmailTemplates.evalTemplate(true, template, bindings);\n\t\t\t\t\t\t\t\t\t\tString textBody = EmailTemplates.evalTemplate(false, template, bindings);\n\n\t\t\t\t\t\t\t\t\t\tvar threadingReferences = getThreadingReferences(UUID.randomUUID().toString(), getMessageId(message));\n\t\t\t\t\t\t\t\t\t\tsendMailAsync(newArrayList(fromInternetAddress.getAddress()), newArrayList(), newArrayList(),\n\t\t\t\t\t\t\t\t\t\t\t\tsubject, htmlBody, textBody, null, null, threadingReferences);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (fromUser != null) {\n\t\t\t\t\t\t\t\t\t\t\tif (SecurityUtils.canAccessIssue(fromUser.asSubject(), involvedIssue))\t\n\t\t\t\t\t\t\t\t\t\t\t\taddComment(involvedIssue, message, fromInternetAddress, fromUser, receiverInternetAddresses);\n\t\t\t\t\t\t\t\t\t\t\telse \n\t\t\t\t\t\t\t\t\t\t\t\tthrow new UnauthorizedException(\"No permission to comment issue: \" + involvedIssue.getReference());\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tif (involvedIssue.getExternalParticipants().contains(fromInternetAddress)) \t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\taddComment(involvedIssue, message, fromInternetAddress, null, receiverInternetAddresses);\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\tthrow new UnauthorizedException(\"Not eligible to comment issue: \" + involvedIssue.getReference());\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (subAddress.contains(\"pullrequest\")) {\n\t\t\t\t\t\t\t\t\tif (fromUser != null) {\n\t\t\t\t\t\t\t\t\t\tinvolvedPullRequest = pullRequestService.get(entityId);\n\t\t\t\t\t\t\t\t\t\tif (involvedPullRequest == null)\n\t\t\t\t\t\t\t\t\t\t\tthrow new ExplicitException(\"Non-existent pull request specified in recipient address: \" + parsedReceiverAddress);\n\t\t\t\t\t\t\t\t\t\tif (subAddress.contains(\"unsubscribe\")) {\n\t\t\t\t\t\t\t\t\t\t\tPullRequestWatch watch = pullRequestWatchService.find(involvedPullRequest, fromUser);\n\t\t\t\t\t\t\t\t\t\t\tif (watch != null) \n\t\t\t\t\t\t\t\t\t\t\t\twatch.setWatching(false);\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tString subject = \"Unsubscribed successfully from pull request \" + involvedPullRequest.getReference().toString(null);\n\n\t\t\t\t\t\t\t\t\t\t\tString template = StringUtils.join(settingService.getEmailTemplates().getPullRequestNotificationUnsubscribed(), \"\\n\");\n\t\t\t\t\t\t\t\t\t\t\tMap<String, Object> bindings = new HashMap<>();\n\t\t\t\t\t\t\t\t\t\t\tbindings.put(\"pullRequest\", involvedPullRequest);\n\t\t\t\t\t\t\t\t\t\t\tString htmlBody = EmailTemplates.evalTemplate(true, template, bindings);","sourceCodeStart":507,"sourceCodeEnd":543,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/mail/DefaultMailService.java#L507-L543","documentation":"For anonymous (unrecognized email sender) replies to an issue, OneDev only allows commenting if the sender address is already listed in the issue's external participants. Otherwise an UnauthorizedException 'Not eligible to comment issue: <ref>' is thrown.","triggerScenarios":"Email reply to issue~<id>~comment where fromUser is null and the From address is not in involvedIssue.getExternalParticipants().","commonSituations":"External reporter emails from a different address than the one used originally; someone uninvolved discovers the issue address and tries to reply; forwarding the thread from another mailbox.","solutions":["Reply from the original email address that participated in the issue.","Have a project member add the address as an external participant, or enable service desk so anonymous senders can open issues.","Comment through the web UI instead."],"exampleFix":"// before\nFrom: other@example.com (not an external participant of issue #42)\n// after\nFrom: original-reporter@example.com (in issue's external participants)","handlingStrategy":"validation","validationCode":"if (fromUser == null && !issue.getExternalParticipants().contains(fromAddress))\n    throw new UnauthorizedException(\"Not eligible to comment issue: \" + issue.getReference());","typeGuard":null,"tryCatchPattern":"try { handleMessage(message); } catch (UnauthorizedException e) { bounceToSender(e.getMessage()); }","preventionTips":["Reply from the original participant address","Enable service desk for anonymous participation","Keep the same mailbox for the whole thread"],"tags":["email","authorization","anonymous"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}