FEATURE: add support for multiple incoming emails for groups & categories

This commit is contained in:
Régis Hanol 2016-02-24 19:47:58 +01:00
parent 54262cc9b2
commit f7432d8ec9
8 changed files with 26 additions and 12 deletions

View file

@ -33,6 +33,8 @@ class Category < ActiveRecord::Base
length: { in: 1..50 } length: { in: 1..50 }
validate :parent_category_validator validate :parent_category_validator
validate :email_in_validator
validate :ensure_slug validate :ensure_slug
before_save :apply_permissions before_save :apply_permissions
before_save :downcase_email before_save :downcase_email
@ -308,7 +310,16 @@ SQL
end end
def downcase_email def downcase_email
self.email_in = email_in.downcase if self.email_in self.email_in = (email_in || "").strip.downcase.presence
end
def email_in_validator
return if self.email_in.blank?
email_in.split("|").each do |email|
unless Email.is_valid?(email)
self.errors.add(:base, I18n.t('category.errors.invalid_email_in', email_in: email))
end
end
end end
def downcase_name def downcase_name
@ -380,7 +391,7 @@ SQL
end end
def self.find_by_email(email) def self.find_by_email(email)
self.find_by(email_in: Email.downcase(email)) self.where("email_in LIKE ?", "%#{Email.downcase(email)}%").first
end end
def has_children? def has_children?

View file

@ -81,8 +81,10 @@ class Group < ActiveRecord::Base
def incoming_email_validator def incoming_email_validator
return if self.automatic || self.incoming_email.blank? return if self.automatic || self.incoming_email.blank?
unless Email.is_valid?(incoming_email) incoming_email.split("|").each do |email|
self.errors.add(:base, I18n.t('groups.errors.invalid_incoming_email', incoming_email: incoming_email)) unless Email.is_valid?(email)
self.errors.add(:base, I18n.t('groups.errors.invalid_incoming_email', incoming_email: email))
end
end end
end end
@ -332,7 +334,7 @@ class Group < ActiveRecord::Base
end end
def self.find_by_email(email) def self.find_by_email(email)
self.find_by(incoming_email: Email.downcase(email)) self.where("incoming_email LIKE ?", "%#{Email.downcase(email)}%").first
end end
def bulk_add(user_ids) def bulk_add(user_ids)

View file

@ -374,6 +374,7 @@ en:
self_parent: "A subcategory's parent cannot be itself" self_parent: "A subcategory's parent cannot be itself"
depth: "You can't nest a subcategory under another" depth: "You can't nest a subcategory under another"
email_in_already_exist: "Incoming email address '%{email_in}' is already in use for '%{category_name}' category." email_in_already_exist: "Incoming email address '%{email_in}' is already in use for '%{category_name}' category."
invalid_email_in: "'%{email_in}' is not a valid email address."
cannot_delete: cannot_delete:
uncategorized: "Can't delete Uncategorized" uncategorized: "Can't delete Uncategorized"
has_subcategories: "Can't delete this category because it has sub-categories." has_subcategories: "Can't delete this category because it has sub-categories."

View file

@ -214,11 +214,11 @@ module Email
end end
def group_incoming_emails_regex def group_incoming_emails_regex
@group_incoming_emails_regex ||= Regexp.union Group.pluck(:incoming_email).select(&:present?).uniq @group_incoming_emails_regex ||= Regexp.union Group.pluck(:incoming_email).select(&:present?).map { |e| e.split("|") }.flatten.uniq
end end
def category_email_in_regex def category_email_in_regex
@category_email_in_regex ||= Regexp.union Category.pluck(:email_in).select(&:present?).uniq @category_email_in_regex ||= Regexp.union Category.pluck(:email_in).select(&:present?).map { |e| e.split("|") }.flatten.uniq
end end
def find_related_post def find_related_post

View file

@ -223,7 +223,7 @@ describe Email::Receiver do
context "new message to a group" do context "new message to a group" do
let!(:group) { Fabricate(:group, incoming_email: "team@bar.com") } let!(:group) { Fabricate(:group, incoming_email: "team@bar.com|meat@bar.com") }
it "handles encoded display names" do it "handles encoded display names" do
expect { process(:encoded_display_name) }.to change(Topic, :count) expect { process(:encoded_display_name) }.to change(Topic, :count)
@ -275,7 +275,7 @@ describe Email::Receiver do
context "new topic in a category" do context "new topic in a category" do
let!(:category) { Fabricate(:category, email_in: "category@bar.com", email_in_allow_strangers: false) } let!(:category) { Fabricate(:category, email_in: "category@bar.com|category@foo.com", email_in_allow_strangers: false) }
it "raises a StrangersNotAllowedError when 'email_in_allow_strangers' is disabled" do it "raises a StrangersNotAllowedError when 'email_in_allow_strangers' is disabled" do
expect { process(:new_user) }.to raise_error(Email::Receiver::StrangersNotAllowedError) expect { process(:new_user) }.to raise_error(Email::Receiver::StrangersNotAllowedError)

View file

@ -1,6 +1,6 @@
Return-Path: <random.name@bar.ru> Return-Path: <random.name@bar.ru>
From: =?UTF-8?B?0KHQu9GD0YfQsNC50L3QsNGP?= =?UTF-8?B?INCY0LzRjw==?= <random.name@bar.ru> From: =?UTF-8?B?0KHQu9GD0YfQsNC50L3QsNGP?= =?UTF-8?B?INCY0LzRjw==?= <random.name@bar.ru>
To: team@bar.com To: meat@bar.com
Subject: I need help Subject: I need help
Date: Fri, 15 Jan 2016 00:12:43 +0100 Date: Fri, 15 Jan 2016 00:12:43 +0100
Message-ID: <29@foo.bar.mail> Message-ID: <29@foo.bar.mail>

View file

@ -1,6 +1,6 @@
Return-Path: <discourse@bar.com> Return-Path: <discourse@bar.com>
From: Foo Bar <discourse@bar.com> From: Foo Bar <discourse@bar.com>
To: category@bar.com To: category@foo.com
Subject: This is a topic from a complete stranger Subject: This is a topic from a complete stranger
Date: Fri, 15 Jan 2016 00:12:43 +0100 Date: Fri, 15 Jan 2016 00:12:43 +0100
Message-ID: <31@foo.bar.mail> Message-ID: <31@foo.bar.mail>

View file

@ -1,5 +1,5 @@
From: Some One <some@one.com> From: Some One <some@one.com>
To: team@bar.com To: meat@bar.com
Date: Mon, 1 Feb 2016 00:12:43 +0100 Date: Mon, 1 Feb 2016 00:12:43 +0100
Message-ID: <40@foo.bar.mail> Message-ID: <40@foo.bar.mail>
Mime-Version: 1.0 Mime-Version: 1.0