Skip to content

Commit

Permalink
Implement Sisimai::Reason::Speeding for parsing a bounce mail rejecte…
Browse files Browse the repository at this point in the history
…d due to exceeding a rate limit or sending too fast #239
  • Loading branch information
azumakuniyuki committed Nov 5, 2022
1 parent 7a445ce commit 346c08e
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 19 deletions.
22 changes: 11 additions & 11 deletions lib/sisimai/reason.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ def index
return %w[
AuthFailure Blocked ContentError ExceedLimit Expired Filtered HasMoved HostUnknown
MailboxFull MailerError MesgTooBig NetworkError NotAccept OnHold Rejected NoRelaying
SpamDetected VirusDetected PolicyViolation SecurityError Suspend SystemError SystemFull
TooManyConn UserUnknown SyntaxError
Speeding SpamDetected VirusDetected PolicyViolation SecurityError Suspend SystemError
SystemFull TooManyConn UserUnknown SyntaxError
]
end

Expand All @@ -25,30 +25,31 @@ def path
end

# Reason list better to retry detecting an error reason
# @return [Array] Reason list
# @return [Hash] Reason list
def retry
return {
'undefined' => true, 'onhold' => true, 'systemerror' => true, 'securityerror' => true,
'networkerror' => true, 'hostunknown' => true, 'userunknown' => true
'expired' => true, 'suspend' => true, 'networkerror' => true, 'hostunknown' => true,
'userunknown' => true
}.freeze
end
ModulePath = Sisimai::Reason.path
GetRetried = Sisimai::Reason.retry
ClassOrder = [
%w[
MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying AuthFailure UserUnknown
Filtered Rejected HostUnknown SpamDetected TooManyConn Blocked
Filtered Rejected HostUnknown SpamDetected Speeding TooManyConn Blocked
],
%w[
MailboxFull SpamDetected PolicyViolation VirusDetected NoRelaying AuthFailure
SecurityError SystemError NetworkError Suspend Expired ContentError SystemFull NotAccept
MailerError
SecurityError SystemError NetworkError Speeding Suspend Expired ContentError SystemFull
NotAccept MailerError
],
%w[
MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected HostUnknown
SpamDetected TooManyConn Blocked SpamDetected AuthFailure SecurityError SystemError
NetworkError Suspend Expired ContentError HasMoved SystemFull NotAccept MailerError
NoRelaying SyntaxError OnHold
SpamDetected Speeding TooManyConn Blocked SpamDetected AuthFailure SecurityError
SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull NotAccept
MailerError NoRelaying SyntaxError OnHold
]
]

Expand Down Expand Up @@ -121,7 +122,6 @@ def anotherone(argvs)
while true
diagnostic = argvs['diagnosticcode'].downcase || ''
trytomatch = reasontext.empty? ? true : false
trytomatch ||= true if reasontext == 'expired'
trytomatch ||= true if GetRetried[reasontext]
trytomatch ||= true if argvs['diagnostictype'] != 'SMTP'
throw :TRY_TO_MATCH unless trytomatch
Expand Down
48 changes: 48 additions & 0 deletions lib/sisimai/reason/speeding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Sisimai
module Reason
# Sisimai::Reason::Speeding checks the bounce reason is "speeding" or not. This class is called
# only Sisimai::Reason class. This is the error that a connection rejected due to exceeding a
# rate limit or sending too fast.
module Speeding
class << self
Index = [
'please try again slower',
'receiving mail at a rate that prevents additional messages from being delivered',
]

def text; return 'speeding'; end
def description; return 'Rejected due to exceeding a rate limit or sending too fast'; end

# Try to match that the given text and regular expressions
# @param [String] argv1 String to be matched with regular expressions
# @return [True,False] false: Did not match
# true: Matched
def match(argv1)
return nil unless argv1
return true if Index.any? { |a| argv1.include?(a) }
return false
end

# Speeding or not
# @param [Sisimai::Fact] argvs Object to be detected the reason
# @return [True,False] true: is speeding
# false: is not speeding
# @see http://www.ietf.org/rfc/rfc2822.txt
def true(argvs)
return nil if argvs['deliverystatus'].empty?
return true if argvs['reason'] == 'speeding'

# Action: failed
# Status: 4.7.1
# Remote-MTA: dns; smtp.example.jp
# Diagnostic-Code: smtp; 451 4.7.1 <mx.example.org[192.0.2.2]>: Client host rejected:
# Please try again slower
return true if match(argvs['diagnosticcode'].downcase)
return false
end

end
end
end
end

4 changes: 2 additions & 2 deletions lib/sisimai/rhost/googleapps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class << self
'X.1.1' => [{ reason: 'userunknown', string: ['The email account that you tried to reach does not exist.'] }],
'X.1.2' => [{ reason: 'hostunknown', string: ["We weren't able to find the recipient domain."] }],
'X.2.1' => [
{ reason: 'suspend', string: ['The email account that you tried to reach is disabled.'] },
{ reason: 'exceedlimit', string: ['The user you are trying to contact is receiving mail '] },
{ reason: 'suspend', string: ['The email account that you tried to reach is disabled.'] },
{ reason: 'speeding', string: ['The user you are trying to contact is receiving mail '] },
],
'X.2.2' => [{ reason: 'mailboxfull', string: ['The email account that you tried to reach is over quota.'] }],
'X.2.3' => [{ reason: 'exceedlimit', string: ["Your message exceeded Google's message size limits."] }],
Expand Down
2 changes: 1 addition & 1 deletion test/private/lhost-exim.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module Exim
'01038' => [['5.7.0', '550', 'blocked', false]],
'01039' => [['4.0.922', '', 'mailboxfull', false]],
'01040' => [['4.0.947', '', 'expired', false]],
'01041' => [['4.0.947', '451', 'expired', false]],
'01041' => [['4.0.947', '451', 'spamdetected', false]],
'01042' => [['5.0.944', '', 'networkerror', false]],
'01043' => [['5.0.911', '550', 'userunknown', true]],
'01044' => [['5.0.944', '', 'networkerror', false]],
Expand Down
4 changes: 2 additions & 2 deletions test/private/lhost-gmail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ module Gmail
'01032' => [['5.0.947', '', 'expired', false]],
'01033' => [['5.0.971', '', 'blocked', false]],
'01034' => [['4.0.947', '', 'expired', false]],
'01035' => [['4.0.947', '', 'expired', false]],
'01036' => [['4.0.947', '', 'expired', false]],
'01035' => [['4.0.971', '', 'blocked', false]],
'01036' => [['4.0.971', '', 'blocked', false]],
'01037' => [['5.0.971', '', 'blocked', false]],
'01038' => [['5.0.911', '550', 'userunknown', true]],
'01039' => [['5.1.1', '550', 'userunknown', true]],
Expand Down
4 changes: 2 additions & 2 deletions test/private/lhost-postfix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ module Postfix
'01211' => [['5.1.1', '550', 'userunknown', true]],
'01212' => [['5.2.1', '550', 'userunknown', true]],
'01213' => [['5.1.1', '550', 'userunknown', true]],
'01214' => [['5.2.1', '550', 'exceedlimit', false]],
'01215' => [['5.2.1', '550', 'exceedlimit', false]],
'01214' => [['5.2.1', '550', 'speeding', false]],
'01215' => [['5.2.1', '550', 'speeding', false]],
'01216' => [['4.0.0', '', 'blocked', false]],
'01217' => [['4.0.0', '', 'blocked', false]],
'01218' => [['4.0.0', '', 'blocked', false]],
Expand Down
2 changes: 1 addition & 1 deletion test/public/lhost-postfix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module Postfix
'56' => [['4.4.2', '', 'networkerror', false]],
'57' => [['5.2.1', '550', 'userunknown', true]],
'58' => [['5.7.1', '550', 'blocked', false]],
'59' => [['5.2.1', '550', 'exceedlimit', false]],
'59' => [['5.2.1', '550', 'speeding', false]],
'60' => [['4.0.0', '', 'blocked', false]],
'61' => [['5.0.0', '550', 'suspend', false]],
'62' => [['5.0.0', '550', 'virusdetected', false]],
Expand Down
1 change: 1 addition & 0 deletions test/public/reason-children-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ReasonChildrenTest < Minitest::Test
'PolicyViolation' => ['570 5.7.7 Email not accepted for policy reasons'],
'SecurityError' => ['570 5.7.0 Authentication failure'],
'SpamDetected' => ['570 5.7.7 Spam Detected'],
'Speeding' => ['451 4.7.1 <smtp3.example.jp[192.0.2.1]>: Client host rejected: Please try again slower'],
'Suspend' => ['550 5.0.0 Recipient suspend the service'],
'SystemError' => ['500 5.3.5 System config error'],
'SystemFull' => ['550 5.0.0 Mail system full'],
Expand Down
1 change: 1 addition & 0 deletions test/public/reason-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class ReasonTest < Minitest::Test
'smtp;550 5.2.2 <[email protected]>... Mailbox Full',
'smtp;550 Requested action not taken: mailbox unavailable (-2019901852:4030:-2147467259)',
'smtp;550 5.1.1 <[email protected]>... User unknown',
'451 4.7.1 <smtp3.example.jp[192.0.2.1]>: Client host rejected: Please try again slower',
'550 5.1.1 <[email protected]>... User Unknown ',
'550 5.1.1 <[email protected]>... ',
'550 Bad SPF records for [example.org:192.0.2.2], see http://spf.pobox.com/',
Expand Down

0 comments on commit 346c08e

Please sign in to comment.