mirror of
https://github.com/discourse/discourse.git
synced 2025-09-05 08:59:27 +08:00
FEATURE: handle bounced emails
This commit is contained in:
parent
b7b5caa50e
commit
8e611ec7a1
27 changed files with 354 additions and 23 deletions
|
@ -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] ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue