The discussion centers on a bug where Discourse rejects emails from known users who lack permission to post in a private category, while accepting emails from anonymous users. The original reporter, downey, outlines that emails from unregistered addresses work, but those from registered non-members are rejected with a can_create? failed error. zogstrip confirms this is intentional behavior: the system associates the email with the user first, then checks permissions. Since the user is not in the allowed group, the post is blocked. The email_in_allow_strangers setting currently only applies to staged (unactivated) users.
Several users, including wityr and Christian_Kindel, argue this is counter-intuitive and problematic, especially for mailing list mirrors where known subscribers are blocked while unknown senders are accepted. dachary proposes code patches to bypass validation when email_in_allow_strangers is enabled, though sam explains that the current restriction is a security measure to prevent email spoofing and impersonation. Sam suggests a long-term solution involving a verification step where the user confirms the email was sent by them.
Other participants, such as Simon_Manning, argue that modern email authentication protocols like SPF, DKIM, and DMARC provide sufficient protection against spoofing, suggesting that the system could safely accept emails from known users if these checks pass. sam considers adding a site setting to allow operators to accept this risk. Simon_Manning further clarifies that the issue is specific to private categories; in public categories, known users with permissions can post via email without issue. The consensus among developers is that fixing this requires a comprehensive approach to security, potentially leveraging email authentication results to allow known users to post in restricted categories without compromising safety against impersonation. The issue persists in recent versions, affecting projects like the Tor Forum that rely on email-to-forum functionality.
Have a “private” category that only has create/reply/see access for members of a specific group. No other permissions.
Enable “anonymous email in” for that specific via a unique working alias to the incoming POP account.
Have a non-staff user that is not a member of the group send an email report in to the category email address from the email address associated with their account.
Send in an email from an account not associated with any known Discourse account.
Expected Behavior:
Both #3 and #4 result in new topics in the private category, and the group can begin discussion.
Actual Behavior:
The email in #4 works but email in #3 is rejected with the can_create? failed error.
When we receive an email, we first try to associate it to a user, and then we check for permissions. Since the user isn’t part of the group, they can’t post.
The email_in_allow_strangers field on the category only works for staged users.
Can confirm #3 still not working. Is the best workaround right now to have emails directed at a group rather than a category? Not my preferred arrangement but I can switch until a patch comes out.
This scenario seems to be replaced these days with the group functionality as a type of workaround, although I could see some use cases that it might still be just as valuable for categories/topics/discussions.
Like you say, this is just a (bad) workaround. IMO this should be controllable on a per-category level. Clearly a bug that this works only for anonymous but not for known users.
I just ran into this issue while trying to set up a category for our organizations info list. This category only allows a certain group to access it, but we selected the option to allow emails from anonymous users. Email addresses that are not associated with any of our discourse users can send a message that will show up in the category, but registered users that are not in the group get rejected due to “Insufficient Trust Level”. I think I understand the technical reason why it works this way (only works for staged users) but is there a reason why this would be the desired or expected behavior? It seems to me if we are choosing to allow anonymous users we probably want to allow all registered users as well.
대부분의 카테고리는 등록된 사용자만 사용할 수 있도록 설정되어 있지만, 커뮤니티의 비회원인 사용자가 핵심 개발자에게 이메일을 보내 간단한 질문을 하거나 우려 사항을 제기할 수 있는 방법을 마련하고 싶었습니다.
이를 위해 익명 사용자의 이메일을 받을 수 있는 카테고리를 설정하고 커스텀 주소(예: ourproject+contact@discoursemail.com)를 사용했습니다. 커뮤니티 전체에 너무 많은 메일이나 노이즈를 생성하지 않도록, 해당 카테고리의 읽기 권한은 핵심 프로젝트 멤버에게만 부여했습니다. (읽기 접근을 제한하면 생성/답변 접근도 함께 제한되므로, 핵심 멤버가 주제 생성과 답변도 할 수 있도록 해야 했습니다.)
하지만 익명 사용자가 공식 계정을 생성하면 더 이상 해당 연락처 이메일 주소로 메일을 보낼 수 없다는 사실을 알게 되었습니다. 이는 직관에 반하는 것으로, 이전보다 더 공식적이고 등록된 상태가 되었음에도 불구하고 오히려 이전보다 할 수 있는 일이 줄어든 상황이 되기 때문입니다.
이 주제에 도달하기 전까지 이 문제로 인해 상당한 혼란을 겪었으며, 여전히 불행한 상황이라고 생각합니다.
다음 패치(현재 main 브랜치 대상)가 카테고리에서 email_in_allow_strangers가 설정된 경우, 단계적 사용자(staged users)에게 적용되는 방식과 동일한 방식으로 유효성 검사를 건너뛰어 이 문제를 해결할 수 있다고 생각합니다. 이 방식이 타당해 보이나요?
diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb
index 7c76c44d61..dd3bc3cfb0 100644
--- a/lib/email/receiver.rb
+++ b/lib/email/receiver.rb
@@ -762,7 +762,7 @@ module Email
elided: elided,
title: subject,
category: destination.id,
- skip_validations: user.staged?)
+ skip_validations: (user.staged? || destination.email_in_allow_strangers))
elsif destination.is_a?(PostReplyKey)
# We don't stage new users for emails to reply addresses, exit if user is nil
동작하지 않는 이유는 **검증(validations)**이 게시글의 내용에 관한 것이지, 게시글을 생성할 권한이 있는지 여부에 관한 것이 아니기 때문입니다…
아래 패치를 테스트해보니 동작하는 것을 확인했습니다. 이것은 해킹이므로 집에서 시도하지 마세요 그 장점은 변경 사항이 어디에서 발생해야 하는지를 대략적으로 파악할 수 있다는 점입니다. 도전 과제는 이를 적절하게 수행하는 방법을 알아내는 것입니다. 조언이 있다면 환영합니다
diff --git a/app/jobs/regular/notify_mailing_list_subscribers.rb b/app/jobs/regular/notify_mailing_list_subscribers.rb
index c535296105..1d3bf79637 100644
--- a/app/jobs/regular/notify_mailing_list_subscribers.rb
+++ b/app/jobs/regular/notify_mailing_list_subscribers.rb
@@ -74,7 +74,7 @@ module Jobs
DiscourseEvent.trigger(:notify_mailing_list_subscribers, users, post)
users.find_each do |user|
- if Guardian.new(user).can_see?(post)
+ if Guardian.new(user).can_see?(post) && Guardian.new(user).can_see_category_staged?(post.topic.category)
if EmailLog.reached_max_emails?(user)
skip(user.email, user.id, post.id,
SkippedEmailLog.reason_types[:exceeded_emails_limit]
diff --git a/app/models/category.rb b/app/models/category.rb
index 630a74c425..6c253650c6 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -201,7 +201,7 @@ class Category < ActiveRecord::Base
end
else
permissions = permission_types.map { |p| CategoryGroup.permission_types[p] }
- where("(:staged AND LENGTH(COALESCE(email_in, '')) > 0 AND email_in_allow_strangers)
+ where("(LENGTH(COALESCE(email_in, '')) > 0 AND email_in_allow_strangers)
OR categories.id NOT IN (SELECT category_id FROM category_groups)
OR categories.id IN (
SELECT category_id
@@ -209,7 +209,6 @@ class Category < ActiveRecord::Base
WHERE permission_type IN (:permissions)
AND (group_id = :everyone OR group_id IN (SELECT group_id FROM group_users WHERE user_id = :user_id))
)",
- staged: guardian.is_staged?,
permissions: permissions,
user_id: guardian.user.id,
everyone: Group[:everyone].id)
diff --git a/lib/guardian/category_guardian.rb b/lib/guardian/category_guardian.rb
index 94a48466d6..2a4ba8015c 100644
--- a/lib/guardian/category_guardian.rb
+++ b/lib/guardian/category_guardian.rb
@@ -64,6 +64,14 @@ module CategoryGuardian
end
def can_see_category?(category)
+ return false unless category
+ return true if is_admin?
+ return true if !category.read_restricted
+ return true if category.email_in.present? && category.email_in_allow_strangers
+ secure_category_ids.include?(category.id)
+ end
+
+ def can_see_category_staged?(category)
return false unless category
return true if is_admin?
return true if !category.read_restricted
상세히 파고들지는 않았지만, Email::AuthenticationResults가 이미 출처 검증을 일부 수행하는 것으로 보입니다. 단기적으로는(혹은 좀 더 짧은 기간 동안) 판정 결과가(아직 제공되지 않는다면) 제공되도록 하여, pass 판정을 받은 이메일을 수용할 수 있도록 하면 좋을 것 같습니다.
장기적인 해결책에서는 pass 판정인 경우 "정말 당신인가요?"라는 인증 과정을 건너뛰도록 할 수도 있습니다.