From cce8b4720a3f27077528f4ba2afbeb83ad8b464b Mon Sep 17 00:00:00 2001 From: riking Date: Wed, 13 Aug 2014 11:06:17 -0700 Subject: [PATCH] Have reciever handle multiple To addresses --- lib/email/receiver.rb | 70 +++++++++++-------- spec/components/email/receiver_spec.rb | 3 +- .../fixtures/emails/multiple_destinations.eml | 40 +++++++++++ spec/jobs/poll_mailbox_spec.rb | 17 ++++- 4 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 spec/fixtures/emails/multiple_destinations.eml diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb index 13a36939263..3845a97985f 100644 --- a/lib/email/receiver.rb +++ b/lib/email/receiver.rb @@ -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 diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index 58a1f26aade..71bc6a4d504 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -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{ diff --git a/spec/fixtures/emails/multiple_destinations.eml b/spec/fixtures/emails/multiple_destinations.eml new file mode 100644 index 00000000000..6d31bbf1974 --- /dev/null +++ b/spec/fixtures/emails/multiple_destinations.eml @@ -0,0 +1,40 @@ +Return-Path: +Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400 +Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Thu, 13 Jun 2013 17:03:50 -0400 +Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for ; Thu, 13 Jun 2013 14:03:48 -0700 +Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700 +Date: Thu, 13 Jun 2013 17:03:48 -0400 +From: Jake the Dog +To: finn@adventuretime.ooo, reply+59d8df8370b7e95c5a49fbf86aeb2c93@appmail.adventuretime.ooo +Message-ID: +Subject: re: [Discourse Meta] eviltrout posted in 'Adventure Time Sux' +Mime-Version: 1.0 +Content-Type: text/plain; + charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +X-Sieve: CMU Sieve 2.2 +X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu, + 13 Jun 2013 14:03:48 -0700 (PDT) +X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1 + +I could not disagree more. I am obviously biased but adventure time is the +greatest show ever created. Everyone should watch it. + +- Jake out + + +On Sun, Jun 9, 2013 at 1:39 PM, eviltrout via Discourse Meta + wrote: +> +> +> +> eviltrout posted in 'Adventure Time Sux' on Discourse Meta: +> +> --- +> hey guys everyone knows adventure time sucks! +> +> --- +> Please visit this link to respond: http://localhost:3000/t/adventure-time-sux/1234/3 +> +> To unsubscribe from these emails, visit your [user preferences](http://localhost:3000/user_preferences). +> \ No newline at end of file diff --git a/spec/jobs/poll_mailbox_spec.rb b/spec/jobs/poll_mailbox_spec.rb index d9f9dbd104e..ac72fc91813 100644 --- a/spec/jobs/poll_mailbox_spec.rb +++ b/spec/jobs/poll_mailbox_spec.rb @@ -167,8 +167,23 @@ 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 + + puts topic.posts + poller.handle_mail(email) + + puts topic.posts + 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