2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-09-05 08:59:27 +08:00

don't send more than 1 reply per day to auto-generated emails

This commit is contained in:
Régis Hanol 2016-06-28 16:42:05 +02:00
parent 1411eedad3
commit 214f5bff5c
8 changed files with 30 additions and 94 deletions

View file

@ -17,9 +17,6 @@ module Email
class MessageBuilder
attr_reader :template_args
REPLY_TO_AUTO_GENERATED_HEADER_KEY = "X-Discourse-Reply-to-Auto-Generated".freeze
REPLY_TO_AUTO_GENERATED_HEADER_VALUE = "marked".freeze
def initialize(to, opts=nil)
@to = to
@opts = opts || {}
@ -138,10 +135,6 @@ module Email
result['List-Unsubscribe'] = "<#{template_args[:user_preferences_url]}>"
end
if @opts[:mark_as_reply_to_auto_generated]
result[REPLY_TO_AUTO_GENERATED_HEADER_KEY] = REPLY_TO_AUTO_GENERATED_HEADER_VALUE
end
result['X-Discourse-Post-Id'] = @opts[:post_id].to_s if @opts[:post_id]
result['X-Discourse-Topic-Id'] = @opts[:topic_id].to_s if @opts[:topic_id]

View file

@ -15,16 +15,14 @@ module Email
receiver = Email::Receiver.new(@mail)
receiver.process!
rescue Email::Receiver::BouncedEmailError => e
# never reply to bounced emails
log_email_process_failure(@mail, e)
set_incoming_email_rejection_message(receiver.incoming_email, I18n.t("emails.incoming.errors.bounced_email_error"))
rescue Email::Receiver::AutoGeneratedEmailReplyError => e
log_email_process_failure(@mail, e)
set_incoming_email_rejection_message(receiver.incoming_email, I18n.t("emails.incoming.errors.auto_generated_email_reply"))
rescue => e
log_email_process_failure(@mail, e)
rejection_message = handle_failure(@mail, e)
if rejection_message.present? && receiver && (incoming_email = receiver.incoming_email)
incoming_email = receiver.try(:incoming_email)
rejection_message = handle_failure(@mail, e, incoming_email)
if rejection_message.present?
set_incoming_email_rejection_message(incoming_email, rejection_message.body.to_s)
end
end
@ -32,7 +30,7 @@ module Email
private
def handle_failure(mail_string, e)
def handle_failure(mail_string, e, incoming_email)
message_template = case e
when Email::Receiver::EmptyEmailError then :email_reject_empty
when Email::Receiver::NoBodyDetectedError then :email_reject_empty
@ -67,10 +65,6 @@ module Email
template_args[:rate_limit_description] = e.description
end
if message_template == :email_reject_auto_generated
template_args[:mark_as_reply_to_auto_generated] = true
end
if message_template
# inform the user about the rejection
message = Mail::Message.new(mail_string)
@ -79,7 +73,11 @@ module Email
template_args[:site_name] = SiteSetting.title
client_message = RejectionMailer.send_rejection(message_template, message.from, template_args)
Email::Sender.new(client_message, message_template).send
# don't send more than 1 reply per day to auto-generated emails
if !incoming_email.try(:is_auto_generated) || can_reply_to_auto_generated?(message.from)
Email::Sender.new(client_message, message_template).send
end
else
Rails.logger.error("Unrecognized error type (#{e}) when processing incoming email\n\nMail:\n#{mail_string}")
end
@ -87,6 +85,17 @@ module Email
client_message
end
def can_reply_to_auto_generated?(email)
key = "auto_generated_reply:#{email}:#{Date.today}"
if $redis.setnx(key, "1")
$redis.expire(key, 25.hours)
true
else
false
end
end
def set_incoming_email_rejection_message(incoming_email, message)
incoming_email.update_attributes!(rejection_message: message)
end

View file

@ -13,7 +13,6 @@ module Email
class ScreenedEmailError < ProcessingError; end
class UserNotFoundError < ProcessingError; end
class AutoGeneratedEmailError < ProcessingError; end
class AutoGeneratedEmailReplyError < ProcessingError; end
class BouncedEmailError < ProcessingError; end
class NoBodyDetectedError < ProcessingError; end
class InactiveUserError < ProcessingError; end
@ -82,8 +81,7 @@ module Email
if is_auto_generated?
@incoming_email.update_columns(is_auto_generated: true)
raise AutoGeneratedEmailReplyError if check_reply_to_auto_generated_header
raise AutoGeneratedEmailError if SiteSetting.block_auto_generated_emails?
raise AutoGeneratedEmailError if SiteSetting.block_auto_generated_emails?
end
if action = subscription_action_for(body, subject)
@ -151,20 +149,20 @@ module Email
if bounce_key && (email_log = EmailLog.find_by(bounce_key: bounce_key))
email_log.update_columns(bounced: true)
email = email_log.user.try(:email) || @from_email
if email.present?
if @mail.error_status.present?
if @mail.error_status.start_with?("4.")
Email::Receiver.update_bounce_score(email, SOFT_BOUNCE_SCORE)
elsif @mail.error_status.start_with?("5.")
Email::Receiver.update_bounce_score(email, HARD_BOUNCE_SCORE)
end
elsif is_auto_generated?
if email.present? && @mail.error_status.present?
if @mail.error_status.start_with?("4.")
Email::Receiver.update_bounce_score(email, SOFT_BOUNCE_SCORE)
else @mail.error_status.start_with?("5.")
Email::Receiver.update_bounce_score(email, HARD_BOUNCE_SCORE)
end
end
end
end
if is_auto_generated?
Email::Receiver.update_bounce_score(@from_email, SOFT_BOUNCE_SCORE)
end
true
end
@ -534,20 +532,6 @@ module Email
!topic.topic_allowed_groups.where("group_id IN (SELECT group_id FROM group_users WHERE user_id = ?)", user.id).exists?
end
private
def check_reply_to_auto_generated_header
headers = Mail::Header.new(@mail.body.to_s.gsub("\r\n\r\n", "\r\n")).to_a
index = headers.find_index do |f|
f.name == Email::MessageBuilder::REPLY_TO_AUTO_GENERATED_HEADER_KEY
end
if index
headers[index].value == Email::MessageBuilder::REPLY_TO_AUTO_GENERATED_HEADER_VALUE
end
end
end
end