Merge pull request #2647 from riking/multiple-addresses

Allow processing of email sent to multiple addresses
This commit is contained in:
Sam 2014-08-22 10:32:42 +10:00
commit ac4f6d9c97
17 changed files with 66 additions and 31 deletions

View File

@ -43,6 +43,8 @@ module Jobs
message_template = :email_reject_parsing
when Email::Receiver::EmailLogNotFound
message_template = :email_reject_reply_key
when Email::Receiver::BadDestinationAddress
message_template = :email_reject_destination
when ActiveRecord::Rollback
message_template = :email_reject_post_error
when Email::Receiver::InvalidPost

View File

@ -1472,6 +1472,13 @@ en:
The provided reply key is invalid or unknown, so we don't know what this email is in reply to. Contact a staff member.
email_reject_destination:
subject_template: "Email issue -- Bad Destination Address(es)"
text_body_template: |
We're sorry, but your email message to %{destination} (titled %{former_title}) didn't work.
None of the destination addresses are recognized by the forum. Please make sure that the forum is in the To: line (not CC or BCC), and that you are sending to the email address provided by the forum administrators.
email_error_notification:
subject_template: "Email issue -- POP authentication error"
text_body_template: |

View File

@ -13,10 +13,11 @@ module Email
class EmptyEmailError < ProcessingError; end
class UserNotFoundError < ProcessingError; end
class UserNotSufficientTrustLevelError < ProcessingError; end
class BadDestinationAddress < ProcessingError; end
class EmailLogNotFound < ProcessingError; end
class InvalidPost < ProcessingError; end
attr_reader :body, :reply_key, :email_log
attr_reader :body, :email_log
def initialize(raw)
@raw = raw
@ -37,10 +38,26 @@ module Email
discourse_email_parser
raise EmailUnparsableError if @body.blank?
if is_in_email?
@user = User.find_by_email(@message.from.first)
dest_info = {type: :invalid, obj: nil}
@message.to.each do |to_address|
if dest_info[:type] == :invalid
dest_info = check_address to_address
end
end
raise BadDestinationAddress if dest_info[:type] == :invalid
if dest_info[:type] == :category
raise BadDestinationAddress unless SiteSetting.email_in
category = dest_info[:obj]
@category_id = category.id
@allow_strangers = category.email_in_allow_strangers
user_email = @message.from.first
@user = User.find_by_email(user_email)
if @user.blank? && @allow_strangers
wrap_body_in_quote
wrap_body_in_quote user_email
# TODO This is WRONG it should register an account
# and email the user details on how to log in / activate
@user = Discourse.system_user
@ -51,22 +68,32 @@ module Email
create_new_topic
else
@reply_key = @message.to.first
@email_log = dest_info[:obj]
# Extract the `reply_key` from the format the site has specified
tokens = SiteSetting.reply_by_email_address.split("%{reply_key}")
tokens.each do |t|
@reply_key.gsub!(t, "") if t.present?
end
# Look up the email log for the reply key
@email_log = EmailLog.for(reply_key)
raise EmailLogNotFound if @email_log.blank?
create_reply
end
end
def check_address(address)
category = Category.find_by_email(address)
return {type: :category, obj: category} if category
regex = Regexp.escape SiteSetting.reply_by_email_address
regex = regex.gsub(Regexp.escape('%{reply_key}'), "(.*)")
regex = Regexp.new regex
match = regex.match address
if match && match[1].present?
reply_key = match[1]
email_log = EmailLog.for(reply_key)
return {type: :reply, obj: email_log}
end
{type: :invalid, obj: nil}
end
private
def parse_body
@ -135,21 +162,8 @@ module Email
@body.strip!
end
def is_in_email?
@allow_strangers = false
return false unless SiteSetting.email_in
category = Category.find_by_email(@message.to.first)
return false unless category
@category_id = category.id
@allow_strangers = category.email_in_allow_strangers
true
end
def wrap_body_in_quote
@body = "[quote=\"#{@message.from.first}\"]
def wrap_body_in_quote(user_email)
@body = "[quote=\"#{user_email}\"]
#{@body}
[/quote]"
end

View File

@ -181,7 +181,6 @@ greatest show ever created. Everyone should watch it.
expect(receiver.body).to eq(reply_body)
expect(receiver.email_log).to eq(email_log)
expect(receiver.reply_key).to eq(reply_key)
attachment_email = fixture_file("emails/attachment.eml")
attachment_email = fill_email(attachment_email, "test@test.com", to)
@ -209,7 +208,7 @@ greatest show ever created. Everyone should watch it.
# no email in for user
expect{
process_email(from: "cobb@dob.com", to: "invalid@address.com")
}.to raise_error(Email::Receiver::EmailLogNotFound)
}.to raise_error(Email::Receiver::BadDestinationAddress)
# valid target invalid user
expect{

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -167,8 +167,21 @@ describe Jobs::PollMailbox do
email.should be_deleted
end
it "works with multiple To addresses" do
email = MockPop3EmailObject.new fixture_file('emails/multiple_destinations.eml')
expect_success
poller.handle_mail(email)
new_post = Post.find_by(topic: topic, post_number: 2)
assert new_post.present?
assert_equal expected_post.strip, new_post.cooked.strip
email.should be_deleted
end
describe "with the wrong reply key" do
let(:email) { MockPop3EmailObject.new fixture_file('emails/wrong_reply_key.eml')}
let(:email) { MockPop3EmailObject.new fixture_file('emails/wrong_reply_key.eml') }
it "raises an EmailLogNotFound error" do
expect_exception Email::Receiver::EmailLogNotFound