diff --git a/lib/sisimai/reason.rb b/lib/sisimai/reason.rb index b5ff8f22..78b74023 100644 --- a/lib/sisimai/reason.rb +++ b/lib/sisimai/reason.rb @@ -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 @@ -25,11 +25,12 @@ 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 @@ -37,18 +38,18 @@ def 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 ] ] @@ -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 diff --git a/lib/sisimai/reason/speeding.rb b/lib/sisimai/reason/speeding.rb new file mode 100644 index 00000000..927fb3d6 --- /dev/null +++ b/lib/sisimai/reason/speeding.rb @@ -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 : Client host rejected: + # Please try again slower + return true if match(argvs['diagnosticcode'].downcase) + return false + end + + end + end + end +end + diff --git a/lib/sisimai/rhost/googleapps.rb b/lib/sisimai/rhost/googleapps.rb index 28058d6d..5018b807 100644 --- a/lib/sisimai/rhost/googleapps.rb +++ b/lib/sisimai/rhost/googleapps.rb @@ -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."] }], diff --git a/test/private/lhost-exim.rb b/test/private/lhost-exim.rb index 730bdcd3..ee40cfb3 100644 --- a/test/private/lhost-exim.rb +++ b/test/private/lhost-exim.rb @@ -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]], diff --git a/test/private/lhost-gmail.rb b/test/private/lhost-gmail.rb index 78430238..3e755d1c 100644 --- a/test/private/lhost-gmail.rb +++ b/test/private/lhost-gmail.rb @@ -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]], diff --git a/test/private/lhost-postfix.rb b/test/private/lhost-postfix.rb index 401b9fbf..ffeddc20 100644 --- a/test/private/lhost-postfix.rb +++ b/test/private/lhost-postfix.rb @@ -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]], diff --git a/test/public/lhost-postfix.rb b/test/public/lhost-postfix.rb index 7c91a945..7cb085cc 100644 --- a/test/public/lhost-postfix.rb +++ b/test/public/lhost-postfix.rb @@ -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]], diff --git a/test/public/reason-children-test.rb b/test/public/reason-children-test.rb index cee447e3..7d016c06 100644 --- a/test/public/reason-children-test.rb +++ b/test/public/reason-children-test.rb @@ -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 : 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'], diff --git a/test/public/reason-test.rb b/test/public/reason-test.rb index 8c1fec8c..5c816a57 100644 --- a/test/public/reason-test.rb +++ b/test/public/reason-test.rb @@ -90,6 +90,7 @@ class ReasonTest < Minitest::Test 'smtp;550 5.2.2 ... Mailbox Full', 'smtp;550 Requested action not taken: mailbox unavailable (-2019901852:4030:-2147467259)', 'smtp;550 5.1.1 ... User unknown', + '451 4.7.1 : Client host rejected: Please try again slower', '550 5.1.1 ... User Unknown ', '550 5.1.1 ... ', '550 Bad SPF records for [example.org:192.0.2.2], see http://spf.pobox.com/',