2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-09-06 10:50:21 +08:00

FEATURE: handle bounced emails

This commit is contained in:
Régis Hanol 2016-05-02 23:15:32 +02:00
parent b7b5caa50e
commit 8e611ec7a1
27 changed files with 354 additions and 23 deletions

View file

@ -56,10 +56,6 @@ module Email
end
def process_internal
# temporarily disable processing automated replies to VERP
return if @mail.destinations.any? { |to| to[/\+verp-\h{32}@/i] }
raise BouncedEmailError if @mail.bounced? && !@mail.retryable?
raise ScreenedEmailError if ScreenedEmail.should_block?(@from_email)
user = find_or_create_user(@from_email, @from_display_name)
@ -68,6 +64,7 @@ module Email
@incoming_email.update_columns(user_id: user.id)
raise BouncedEmailError if is_bounce?
raise InactiveUserError if !user.active && !user.staged
raise BlockedUserError if user.blocked
@ -132,6 +129,61 @@ module Email
end
end
SOFT_BOUNCE_SCORE ||= 1
HARD_BOUNCE_SCORE ||= 2
def is_bounce?
return false unless @mail.bounced? || verp
@incoming_email.update_columns(is_bounce: true)
if verp
bounce_key = verp[/\+verp-(\h{32})@/, 1]
if bounce_key && (email_log = EmailLog.find_by(bounce_key: bounce_key))
email_log.update_columns(bounced: true)
if @mail.error_status.present?
if @mail.error_status.start_with?("4.")
update_bounce_score(email_log.user.email, SOFT_BOUNCE_SCORE)
elsif @mail.error_status.start_with?("5.")
update_bounce_score(email_log.user.email, HARD_BOUNCE_SCORE)
end
end
end
end
true
end
def verp
@verp ||= @mail.destinations.select { |to| to[/\+verp-\h{32}@/] }.first
end
def update_bounce_score(email, score)
# only update bounce score once per day
key = "bounce_score:#{email}:#{Date.today}"
if $redis.setnx(key, "1")
$redis.expire(key, 25.hours)
if user = User.find_by(email: email)
user.user_stat.bounce_score += score
user.user_stat.reset_bounce_score_after = 30.days.from_now
user.user_stat.save
if user.active && user.user_stat.bounce_score >= SiteSetting.bounce_score_threshold
user.deactivate
StaffActionLogger.new(Discourse.system_user).log_revoke_email(user)
EmailToken.where(email: user.email, confirmed: true).update_all(confirmed: false)
end
end
true
else
false
end
end
def is_auto_generated?
return false if SiteSetting.auto_generated_whitelist.split('|').include?(@from_email)
@mail[:precedence].to_s[/list|junk|bulk|auto_reply/i] ||