add support for incoming emails in CC/BCC fields
This commit is contained in:
parent
6c2dee29a8
commit
93d1cc6294
|
@ -14,9 +14,7 @@ module Jobs
|
||||||
|
|
||||||
def execute(args)
|
def execute(args)
|
||||||
@args = args
|
@args = args
|
||||||
if SiteSetting.pop3_polling_enabled?
|
poll_pop3 if SiteSetting.pop3_polling_enabled?
|
||||||
poll_pop3
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_mail(mail)
|
def handle_mail(mail)
|
||||||
|
@ -31,7 +29,6 @@ module Jobs
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_failure(mail_string, e)
|
def handle_failure(mail_string, e)
|
||||||
|
|
||||||
Rails.logger.warn("Email can not be processed: #{e}\n\n#{mail_string}") if SiteSetting.log_mail_processing_failures
|
Rails.logger.warn("Email can not be processed: #{e}\n\n#{mail_string}") if SiteSetting.log_mail_processing_failures
|
||||||
|
|
||||||
template_args = {}
|
template_args = {}
|
||||||
|
@ -90,14 +87,14 @@ module Jobs
|
||||||
|
|
||||||
connection.start(SiteSetting.pop3_polling_username, SiteSetting.pop3_polling_password) do |pop|
|
connection.start(SiteSetting.pop3_polling_username, SiteSetting.pop3_polling_password) do |pop|
|
||||||
unless pop.mails.empty?
|
unless pop.mails.empty?
|
||||||
pop.each do |mail|
|
pop.each { |mail| handle_mail(mail) }
|
||||||
handle_mail(mail)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
pop.finish
|
pop.finish
|
||||||
end
|
end
|
||||||
rescue Net::POPAuthenticationError => e
|
rescue Net::POPAuthenticationError => e
|
||||||
Discourse.handle_job_exception(e, error_context(@args, "Signing in to poll incoming email"))
|
Discourse.handle_job_exception(e, error_context(@args, "Signing in to poll incoming email"))
|
||||||
|
rescue Net::POPError => e
|
||||||
|
Discourse.handle_job_exception(e, error_context(@args, "Generic POP error"))
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,19 +10,25 @@ class EmailLog < ActiveRecord::Base
|
||||||
|
|
||||||
after_create do
|
after_create do
|
||||||
# Update last_emailed_at if the user_id is present and email was sent
|
# Update last_emailed_at if the user_id is present and email was sent
|
||||||
User.where(id: user_id).update_all("last_emailed_at = CURRENT_TIMESTAMP") if user_id.present? and !skipped
|
User.where(id: user_id).update_all("last_emailed_at = CURRENT_TIMESTAMP") if user_id.present? && !skipped
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.count_per_day(start_date, end_date)
|
def self.count_per_day(start_date, end_date)
|
||||||
where('created_at >= ? and created_at < ? AND skipped = false', start_date, end_date).group('date(created_at)').order('date(created_at)').count
|
sent.where("created_at BETWEEN ? AND ?", start_date, end_date)
|
||||||
|
.group("DATE(created_at)")
|
||||||
|
.order("DATE(created_at)")
|
||||||
|
.count
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.for(reply_key)
|
def self.for(reply_key)
|
||||||
EmailLog.find_by(reply_key: reply_key)
|
self.find_by(reply_key: reply_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.last_sent_email_address
|
def self.last_sent_email_address
|
||||||
where(email_type: 'signup').order('created_at DESC').first.try(:to_address)
|
self.where(email_type: "signup")
|
||||||
|
.order(created_at: :desc)
|
||||||
|
.first
|
||||||
|
.try(:to_address)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,8 @@ module Email
|
||||||
body = parse_body(message)
|
body = parse_body(message)
|
||||||
|
|
||||||
dest_info = { type: :invalid, obj: nil }
|
dest_info = { type: :invalid, obj: nil }
|
||||||
message.to.each do |to_address|
|
# 'smtp_envelope_to' is a combination of: to, cc and bcc fields
|
||||||
|
message.smtp_envelope_to.each do |to_address|
|
||||||
dest_info = check_address(to_address)
|
dest_info = check_address(to_address)
|
||||||
break if dest_info[:type] != :invalid
|
break if dest_info[:type] != :invalid
|
||||||
end
|
end
|
||||||
|
@ -51,7 +52,6 @@ module Email
|
||||||
|
|
||||||
case dest_info[:type]
|
case dest_info[:type]
|
||||||
when :group
|
when :group
|
||||||
raise BadDestinationAddress unless SiteSetting.email_in
|
|
||||||
group = dest_info[:obj]
|
group = dest_info[:obj]
|
||||||
|
|
||||||
if @user.blank?
|
if @user.blank?
|
||||||
|
@ -68,7 +68,6 @@ module Email
|
||||||
|
|
||||||
create_new_topic(archetype: Archetype.private_message, target_group_names: [group.name])
|
create_new_topic(archetype: Archetype.private_message, target_group_names: [group.name])
|
||||||
when :category
|
when :category
|
||||||
raise BadDestinationAddress unless SiteSetting.email_in
|
|
||||||
category = dest_info[:obj]
|
category = dest_info[:obj]
|
||||||
|
|
||||||
if @user.blank? && category.email_in_allow_strangers
|
if @user.blank? && category.email_in_allow_strangers
|
||||||
|
@ -108,11 +107,14 @@ module Email
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_address(address)
|
def check_address(address)
|
||||||
group = Group.find_by_email(address)
|
# only check groups/categories when 'email_in' is enabled
|
||||||
return { type: :group, obj: group } if group
|
if SiteSetting.email_in
|
||||||
|
group = Group.find_by_email(address)
|
||||||
|
return { type: :group, obj: group } if group
|
||||||
|
|
||||||
category = Category.find_by_email(address)
|
category = Category.find_by_email(address)
|
||||||
return { type: :category, obj: category } if category
|
return { type: :category, obj: category } if category
|
||||||
|
end
|
||||||
|
|
||||||
regex = Regexp.escape(SiteSetting.reply_by_email_address)
|
regex = Regexp.escape(SiteSetting.reply_by_email_address)
|
||||||
regex = regex.gsub(Regexp.escape('%{reply_key}'), "(.*)")
|
regex = regex.gsub(Regexp.escape('%{reply_key}'), "(.*)")
|
||||||
|
|
|
@ -474,16 +474,17 @@ This is a link http://example.com"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_email(mail, from, to, body = nil, subject = nil)
|
def fill_email(mail, from, to, body = nil, subject = nil, cc = nil)
|
||||||
result = mail.gsub("FROM", from).gsub("TO", to)
|
result = mail.gsub("FROM", from).gsub("TO", to)
|
||||||
result.gsub!(/Hey.*/m, body) if body
|
result.gsub!(/Hey.*/m, body) if body
|
||||||
result.sub!(/We .*/, subject) if subject
|
result.sub!(/We .*/, subject) if subject
|
||||||
|
result.sub!("CC", cc.presence || "")
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_email(opts)
|
def process_email(opts)
|
||||||
incoming_email = fixture_file("emails/valid_incoming.eml")
|
incoming_email = fixture_file("emails/valid_incoming.eml")
|
||||||
email = fill_email(incoming_email, opts[:from], opts[:to], opts[:body], opts[:subject])
|
email = fill_email(incoming_email, opts[:from], opts[:to], opts[:body], opts[:subject], opts[:cc])
|
||||||
Email::Receiver.new(email).process
|
Email::Receiver.new(email).process
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -532,15 +533,15 @@ greatest show ever created. Everyone should watch it.
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "processes an email to a category" do
|
describe "processes an email to a category" do
|
||||||
|
let(:to) { "some@email.com" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
SiteSetting.email_in = true
|
SiteSetting.email_in = true
|
||||||
|
SiteSetting.email_in_min_trust = TrustLevel[4].to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
it "correctly can target categories" do
|
it "correctly can target categories" do
|
||||||
to = "some@email.com"
|
|
||||||
|
|
||||||
Fabricate(:category, email_in_allow_strangers: false, email_in: to)
|
Fabricate(:category, email_in_allow_strangers: false, email_in: to)
|
||||||
SiteSetting.email_in_min_trust = TrustLevel[4].to_s
|
|
||||||
|
|
||||||
# no email in for user
|
# no email in for user
|
||||||
expect{
|
expect{
|
||||||
|
@ -614,7 +615,7 @@ greatest show ever created. Everyone should watch it.
|
||||||
}.to raise_error(Email::Receiver::UserNotFoundError)
|
}.to raise_error(Email::Receiver::UserNotFoundError)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a topic for allowed category" do
|
it "creates a topic for matching category" do
|
||||||
Fabricate(:category, email_in_allow_strangers: true, email_in: email_in)
|
Fabricate(:category, email_in_allow_strangers: true, email_in: email_in)
|
||||||
process_email(from: user_email, to: email_in, body: body)
|
process_email(from: user_email, to: email_in, body: body)
|
||||||
|
|
||||||
|
@ -636,7 +637,7 @@ greatest show ever created. Everyone should watch it.
|
||||||
SiteSetting.allow_staged_accounts = true
|
SiteSetting.allow_staged_accounts = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a message for allowed group" do
|
it "creates a message for matching group" do
|
||||||
Fabricate(:group, incoming_email: incoming_email)
|
Fabricate(:group, incoming_email: incoming_email)
|
||||||
process_email(from: user_email, to: incoming_email, body: body)
|
process_email(from: user_email, to: incoming_email, body: body)
|
||||||
|
|
||||||
|
@ -652,4 +653,31 @@ greatest show ever created. Everyone should watch it.
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "supports incoming mail in CC fields" do
|
||||||
|
|
||||||
|
let(:incoming_email) { "foo@bar.com" }
|
||||||
|
let(:user_email) { "#{SecureRandom.hex(32)}@foobar.com" }
|
||||||
|
let(:body) { "This is a message to\n\na group via CC ;)" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.email_in = true
|
||||||
|
SiteSetting.allow_staged_accounts = true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "creates a message for matching group" do
|
||||||
|
Fabricate(:group, incoming_email: incoming_email)
|
||||||
|
process_email(from: user_email, to: "some@email.com", body: body, cc: incoming_email)
|
||||||
|
|
||||||
|
staged_account = User.find_by_email(user_email)
|
||||||
|
expect(staged_account).to be
|
||||||
|
expect(staged_account.staged).to be(true)
|
||||||
|
|
||||||
|
post = staged_account.posts.order(id: :desc).first
|
||||||
|
expect(post).to be
|
||||||
|
expect(post.raw).to eq(body)
|
||||||
|
expect(post.topic.private_message?).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ 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
|
Date: Thu, 13 Jun 2013 17:03:48 -0400
|
||||||
From: Jake the Dog <FROM>
|
From: Jake the Dog <FROM>
|
||||||
To: <TO>
|
To: <TO>
|
||||||
|
Cc: <CC>
|
||||||
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
|
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
|
||||||
Subject: We should have a post-by-email-feature.
|
Subject: We should have a post-by-email-feature.
|
||||||
Mime-Version: 1.0
|
Mime-Version: 1.0
|
||||||
|
|
Loading…
Reference in New Issue