Category not accepting "anonymous email" from known users

Reproduce:

  1. Have a “private” category that only has create/reply/see access for members of a specific group. No other permissions.
  2. Enable “anonymous email in” for that specific via a unique working alias to the incoming POP account.
  3. 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.
  4. 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.
8 Mi Piace

@zogstrip can you review this?

Is this still a problem?

I’m no longer running a site with incoming email enabled so unfortunately can’t reproduce to say either way.

2 Mi Piace

Pretty sure #3 still isn’t working.

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.

3 Mi Piace

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.

1 Mi Piace

I don’t think we can ever support #3 unless we add another setting that opens up any incoming emails?

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.

Sounds plausible. Is this a big thing to do?

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.

1 Mi Piace

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.

1 Mi Piace

Anche noi abbiamo riscontrato questo problema con il nostro sito la settimana scorsa. Per noi, la situazione è la seguente:

Sebbene la maggior parte delle nostre categorie sia destinata solo agli utenti registrati, volevamo un modo per un non membro della comunità di mettersi in contatto con gli sviluppatori principali via email per fare una domanda rapida, sollevare un problema, ecc.

Abbiamo fatto questo impostando una categoria per accettare email da utenti anonimi utilizzando un indirizzo personalizzato (ad esempio, ourproject+contact@discoursemail.com). Abbiamo impostato i permessi della categoria in modo che fosse leggibile solo dai membri principali del progetto per evitare di generare troppe email o rumore per la comunità in generale (il che significava rendere le discussioni creabili e rispondibili anche dai membri principali, poiché non c’è modo di limitare l’accesso in lettura senza limitare anche l’accesso alla creazione/risposta).

Tuttavia, abbiamo poi scoperto che se l’utente anonimo avesse successivamente creato un account ufficiale, non avrebbe più potuto inviare email all’indirizzo di contatto. Questo sembra controintuitivo, dato che ora sono più ufficiali e registrati di prima, ma possono fare rigorosamente meno di quanto potevano fare prima.

Ciò mi ha causato molta confusione prima di trovare questo argomento e sembra ancora una situazione sfortunata.

-Brad

2 Mi Piace

Questo problema persiste ancora nella versione 2.7.8. È confuso il fatto che una mail inviata all’indirizzo email associato a una categoria venga accettata quando il mittente non ha un account registrato nel forum, ma venga rifiutata se lo ha.

3 Mi Piace

Credo che la seguente patch (rispetto al ramo main corrente) possa risolvere il problema saltando le convalida quando email_in_allow_strangers è impostato per la categoria, nello stesso modo in cui viene saltato per gli utenti in staging. Ha senso?

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)
         # Non mettiamo in staging nuovi utenti per gli indirizzi di risposta alle email, esci se l'utente è nil

Non funziona perché le validazioni riguardano il contenuto del post, non i permessi per creare o meno un post…

Ho testato la patch sottostante e funziona. È un trucco, non provarlo a casa :scream: Il suo merito è identificare grossolanamente dove dovrebbero avvenire le modifiche. La sfida è capire come farlo in modo corretto. Qualsiasi consiglio sarà molto gradito :pray:

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
2 Mi Piace

Cosa ne pensi di questo suggerimento @zogstrip?

1 Mi Piace

Penso che il comportamento qui sia intenzionale; una correzione dovrà essere piuttosto completa.

Il problema nel permettere alle persone di associare un argomento a un account esistente è che chiunque può falsificare l’email di chiunque altro.

Credo che la soluzione a lungo termine sia:

  1. sam@somewhere.com ha un account su Discourse.
  2. sam@somewhere.com invia un’email a una categoria con “email anonima in”.
  3. Discourse invia un’email a sam@somewhere.com: "Sembra che tu abbia pubblicato: CONTENUTO DEL POST, all’URL di Discourse. È davvero stato tu?
  4. Clicca su Sì.
  5. L’argomento viene creato.

Senza questa protezione, questa funzionalità sarebbe completamente aperta all’impersonificazione, il che è molto rischioso.

5 Mi Piace

Non è forse già presente questo problema, indipendentemente dal parametro Accetta email da utenti anonimi senza account?

Condivido quel punto di vista: quando un’email è associata a una categoria e la casella Accetta email da utenti anonimi senza account è selezionata, un’email in arrivo

  1. associata a un account Discourse
  2. a cui non è consentito leggere i messaggi secondo i parametri Sicurezza della categoria

dovrebbe essere accettata.

1 Mi Piace

L’uso di SPF/DKIM/DMARC, che ora è molto più diffuso rispetto al 2016, non protegge a sufficienza da questo problema?

Qualsiasi buon provider di posta elettronica (per l’utente) non consentirà ad altri utenti di inviare da indirizzi che non appartengono a loro e qualsiasi buon provider di posta elettronica o servizio di ricezione (per l’istanza Discourse) dovrebbe rifiutare le e-mail che non superano la validazione di origine.

Esisteranno provider che non convalidano l’indirizzo del mittente e/o non impostano record SPF/ecc., ma se un utente sceglie di utilizzare un provider di posta elettronica che non fa nulla per proteggere dall’impersonificazione, sembra ragionevole che possa essere impersonato.

Non ci sono entrato particolarmente a fondo, ma sembra che Email::AuthenticationResults faccia già una qualche validazione dell’origine. Forse nel breve (più breve) termine, il verdetto potrebbe essere reso disponibile (se non lo è già) in modo che queste email possano essere accettate con un verdetto di superamento.

Nella tua soluzione a lungo termine, la verifica “eri davvero tu?” potrebbe anche essere saltata in caso di verdetto di superamento.