sisimai 5.6.0 → 5.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake-test.yml +0 -4
  3. data/ChangeLog.md +47 -0
  4. data/README-JA.md +19 -16
  5. data/README.md +23 -21
  6. data/lib/sisimai/address.rb +8 -31
  7. data/lib/sisimai/arf.rb +5 -6
  8. data/lib/sisimai/eb.rb +116 -0
  9. data/lib/sisimai/fact.rb +33 -51
  10. data/lib/sisimai/lda.rb +20 -18
  11. data/lib/sisimai/lhost/activehunter.rb +0 -2
  12. data/lib/sisimai/lhost/amazonses.rb +17 -18
  13. data/lib/sisimai/lhost/apachejames.rb +0 -1
  14. data/lib/sisimai/lhost/biglobe.rb +0 -16
  15. data/lib/sisimai/lhost/courier.rb +9 -7
  16. data/lib/sisimai/lhost/deutschetelekom.rb +120 -0
  17. data/lib/sisimai/lhost/domino.rb +2 -4
  18. data/lib/sisimai/lhost/dragonfly.rb +0 -27
  19. data/lib/sisimai/lhost/einsundeins.rb +4 -12
  20. data/lib/sisimai/lhost/exchange2003.rb +12 -11
  21. data/lib/sisimai/lhost/exchange2007.rb +17 -17
  22. data/lib/sisimai/lhost/exim.rb +34 -81
  23. data/lib/sisimai/lhost/ezweb.rb +15 -51
  24. data/lib/sisimai/lhost/fml.rb +8 -32
  25. data/lib/sisimai/lhost/gmail.rb +10 -32
  26. data/lib/sisimai/lhost/gmx.rb +7 -24
  27. data/lib/sisimai/lhost/googlegroups.rb +6 -5
  28. data/lib/sisimai/lhost/googleworkspace.rb +2 -5
  29. data/lib/sisimai/lhost/imailserver.rb +4 -9
  30. data/lib/sisimai/lhost/kddi.rb +8 -21
  31. data/lib/sisimai/lhost/mailfoundry.rb +0 -2
  32. data/lib/sisimai/lhost/mailmarshal.rb +1 -3
  33. data/lib/sisimai/lhost/messagingserver.rb +4 -15
  34. data/lib/sisimai/lhost/mfilter.rb +0 -1
  35. data/lib/sisimai/lhost/mimecast.rb +0 -1
  36. data/lib/sisimai/lhost/notes.rb +3 -3
  37. data/lib/sisimai/lhost/opensmtpd.rb +0 -40
  38. data/lib/sisimai/lhost/postfix.rb +14 -14
  39. data/lib/sisimai/lhost/qmail.rb +23 -89
  40. data/lib/sisimai/lhost/sendmail.rb +8 -7
  41. data/lib/sisimai/lhost/trendmicro.rb +5 -4
  42. data/lib/sisimai/lhost/v5sendmail.rb +2 -2
  43. data/lib/sisimai/lhost/verizon.rb +4 -4
  44. data/lib/sisimai/lhost/x1.rb +1 -2
  45. data/lib/sisimai/lhost/x2.rb +0 -2
  46. data/lib/sisimai/lhost/x3.rb +4 -9
  47. data/lib/sisimai/lhost/x6.rb +0 -1
  48. data/lib/sisimai/lhost/zoho.rb +0 -12
  49. data/lib/sisimai/lhost.rb +38 -19
  50. data/lib/sisimai/message.rb +1 -1
  51. data/lib/sisimai/order.rb +4 -1
  52. data/lib/sisimai/reason/authfailure.rb +8 -7
  53. data/lib/sisimai/reason/badreputation.rb +5 -4
  54. data/lib/sisimai/reason/blocked.rb +6 -5
  55. data/lib/sisimai/reason/contenterror.rb +8 -5
  56. data/lib/sisimai/reason/delivered.rb +3 -2
  57. data/lib/sisimai/reason/emailtoolarge.rb +7 -6
  58. data/lib/sisimai/reason/expired.rb +16 -4
  59. data/lib/sisimai/reason/failedstarttls.rb +5 -3
  60. data/lib/sisimai/reason/feedback.rb +2 -1
  61. data/lib/sisimai/reason/filtered.rb +9 -8
  62. data/lib/sisimai/reason/hasmoved.rb +5 -4
  63. data/lib/sisimai/reason/hostunknown.rb +14 -4
  64. data/lib/sisimai/reason/mailboxfull.rb +10 -8
  65. data/lib/sisimai/reason/mailererror.rb +3 -2
  66. data/lib/sisimai/reason/networkerror.rb +16 -3
  67. data/lib/sisimai/reason/norelaying.rb +8 -6
  68. data/lib/sisimai/reason/notaccept.rb +15 -7
  69. data/lib/sisimai/reason/notcompliantrfc.rb +5 -3
  70. data/lib/sisimai/reason/onhold.rb +8 -7
  71. data/lib/sisimai/reason/policyviolation.rb +11 -5
  72. data/lib/sisimai/reason/ratelimited.rb +5 -4
  73. data/lib/sisimai/reason/rejected.rb +24 -14
  74. data/lib/sisimai/reason/requireptr.rb +5 -4
  75. data/lib/sisimai/reason/securityerror.rb +5 -3
  76. data/lib/sisimai/reason/spamdetected.rb +6 -5
  77. data/lib/sisimai/reason/suppressed.rb +4 -3
  78. data/lib/sisimai/reason/suspend.rb +8 -3
  79. data/lib/sisimai/reason/syntaxerror.rb +5 -11
  80. data/lib/sisimai/reason/systemerror.rb +21 -2
  81. data/lib/sisimai/reason/systemfull.rb +4 -3
  82. data/lib/sisimai/reason/undefined.rb +2 -1
  83. data/lib/sisimai/reason/userunknown.rb +15 -9
  84. data/lib/sisimai/reason/vacation.rb +2 -1
  85. data/lib/sisimai/reason/virusdetected.rb +6 -5
  86. data/lib/sisimai/reason.rb +47 -42
  87. data/lib/sisimai/rfc1123.rb +1 -1
  88. data/lib/sisimai/rfc1894.rb +15 -8
  89. data/lib/sisimai/rfc2045.rb +8 -5
  90. data/lib/sisimai/rfc3464/thirdparty.rb +11 -10
  91. data/lib/sisimai/rfc3464.rb +10 -14
  92. data/lib/sisimai/rfc3834.rb +6 -5
  93. data/lib/sisimai/rfc791.rb +3 -38
  94. data/lib/sisimai/rhost/aol.rb +3 -2
  95. data/lib/sisimai/rhost/apple.rb +12 -11
  96. data/lib/sisimai/rhost/cloudflare.rb +3 -2
  97. data/lib/sisimai/rhost/cox.rb +38 -37
  98. data/lib/sisimai/rhost/facebook.rb +17 -16
  99. data/lib/sisimai/rhost/franceptt.rb +39 -38
  100. data/lib/sisimai/rhost/godaddy.rb +35 -34
  101. data/lib/sisimai/rhost/google.rb +22 -21
  102. data/lib/sisimai/rhost/gsuite.rb +8 -7
  103. data/lib/sisimai/rhost/iua.rb +11 -10
  104. data/lib/sisimai/rhost/kddi.rb +3 -2
  105. data/lib/sisimai/rhost/messagelabs.rb +13 -12
  106. data/lib/sisimai/rhost/microsoft.rb +37 -32
  107. data/lib/sisimai/rhost/mimecast.rb +18 -17
  108. data/lib/sisimai/rhost/nttdocomo.rb +10 -9
  109. data/lib/sisimai/rhost/outlook.rb +3 -2
  110. data/lib/sisimai/rhost/spectrum.rb +19 -18
  111. data/lib/sisimai/rhost/tencent.rb +10 -9
  112. data/lib/sisimai/rhost/yahooinc.rb +11 -10
  113. data/lib/sisimai/rhost/zoho.rb +8 -7
  114. data/lib/sisimai/rhost.rb +1 -1
  115. data/lib/sisimai/smtp/command.rb +13 -8
  116. data/lib/sisimai/smtp/failure.rb +9 -8
  117. data/lib/sisimai/smtp/reply.rb +23 -22
  118. data/lib/sisimai/smtp/status.rb +164 -159
  119. data/lib/sisimai/smtp/transcript.rb +3 -2
  120. data/lib/sisimai/string.rb +0 -12
  121. data/lib/sisimai/version.rb +1 -1
  122. data/lib/sisimai.rb +2 -1
  123. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-01.eml +66 -0
  124. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-02.eml +68 -0
  125. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-03.eml +50 -0
  126. data/set-of-emails/maildir/bsd/lhost-postfix-81.eml +130 -0
  127. data/set-of-emails/should-not-crash/go-423-deeply-nested-mime-parts.eml +20050 -0
  128. data/set-of-emails/should-not-crash/p5-664-iomart-mail-filter.eml +258 -0
  129. data/set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yet/.gitkeep +0 -0
  130. metadata +11 -2
@@ -1,14 +1,16 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::ContentError checks the bounce reason is "contenterror" or not This class is
3
+ # Sisimai::Reason::ContentError checks the bounce reason is "ContentError" or not This class is
4
4
  # called only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that a destination mail server has rejected email due to header format of the
7
- # email like the following. Sisimai will set "contenterror" to the reason of email bounce if the
7
+ # email like the following. Sisimai will set "ContentError" to the reason of email bounce if the
8
8
  # value of Status: field in a bounce email is "5.6.*".
9
9
  module ContentError
10
10
  class << self
11
+ require 'sisimai/eb'
11
12
  Index = [
13
+ "charset not supported",
12
14
  "executable files are not allowed in compressed files",
13
15
  "header error",
14
16
  "header size exceeds maximum permitted",
@@ -22,10 +24,11 @@ module Sisimai
22
24
  "message mime complexity exceeds the policy maximum",
23
25
  "message was blocked because its content presents a potential", # https://support.google.com/mail/answer/6590
24
26
  "routing loop detected -- too many received: headers",
27
+ 'too many "received" headers', # Exim/deliver.c:5425
25
28
  "we do not accept messages containing images or other attachments",
26
29
  ].freeze
27
30
 
28
- def text; return 'contenterror'; end
31
+ def text; return Sisimai::Eb::ReBODY; end
29
32
  def description; return 'Email rejected due to a header format of the email'; end
30
33
 
31
34
  # Try to match that the given text and regular expressions
@@ -44,9 +47,9 @@ module Sisimai
44
47
  # @see http://www.ietf.org/rfc/rfc2822.txt
45
48
  def true(argvs)
46
49
  require 'sisimai/reason/spamdetected'
47
- return true if argvs["reason"] == "blocked"
50
+ return true if argvs["reason"] == Sisimai::Eb::ReBLOC
48
51
  return false if Sisimai::Reason::SpamDetected.true(argvs)
49
- return true if Sisimai::SMTP::Status.name(argvs["deliverystatus"]) == "contenterror"
52
+ return true if Sisimai::SMTP::Status.name(argvs["deliverystatus"]) == Sisimai::Eb::ReBODY
50
53
  return match(argvs["diagnosticcode"].downcase)
51
54
  end
52
55
 
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Reason
3
3
  # Sisimai::Reason::Delivered checks the email you sent is delivered successfully or not by matching
4
- # diagnostic messages with message patterns. Sisimai will set "delivered" to the value of "reason"
4
+ # diagnostic messages with message patterns. Sisimai will set "Delivered" to the value of "reason"
5
5
  # when Status: field in the bounce message begins with "2" like following:
6
6
  #
7
7
  # Final-Recipient: rfc822; kijitora@neko.nyaan.jp
@@ -12,7 +12,8 @@ module Sisimai
12
12
  # This class is called only Sisimai.reason method. This is NOT AN ERROR reason.
13
13
  module Delivered
14
14
  class << self
15
- def text; return 'delivered'; end
15
+ require 'sisimai/eb'
16
+ def text; return Sisimai::Eb::ReSENT; end
16
17
  def description; return 'Email delivered successfully'; end
17
18
  def match; return false; end
18
19
  def true(*); return false; end
@@ -2,13 +2,14 @@ module Sisimai
2
2
  module Reason
3
3
  # This is the error that a sent email size is too big for a destination mail server. In many
4
4
  # case, There are many attachment files with email, or the file size is too large. Sisimai will
5
- # set "emailtoolarge" to the reason of email bounce if the value of Status: field in a bounce
5
+ # set "EmailTooLarge" to the reason of email bounce if the value of Status: field in a bounce
6
6
  # email is "5.2.3" or "5.3.4".
7
7
  module EmailTooLarge
8
8
  class << self
9
+ require 'sisimai/eb'
9
10
  Index = [
11
+ "exceeds the maximum size ",
10
12
  "line limit exceeded",
11
- "mail file size exceeds the maximum size allowed for mail delivery",
12
13
  "message too large",
13
14
  "size limit",
14
15
  "taille limite du message atteinte",
@@ -20,7 +21,7 @@ module Sisimai
20
21
  ["message ", "too", "big"],
21
22
  ].freeze
22
23
 
23
- def text; return 'emailtoolarge'; end
24
+ def text; return Sisimai::Eb::ReSIZE; end
24
25
  def description; return 'Email rejected due to an email size is too big for a destination mail server'; end
25
26
 
26
27
  # Try to match that the given text and regular expressions
@@ -39,18 +40,18 @@ module Sisimai
39
40
  # false: is not big
40
41
  # @see http://www.ietf.org/rfc/rfc2822.txt
41
42
  def true(argvs)
42
- return true if argvs['reason'] == 'emailtoolarge'
43
+ return true if argvs['reason'] == Sisimai::Eb::ReSIZE
43
44
 
44
45
  statuscode = argvs['deliverystatus'] || ''
45
46
  tempreason = Sisimai::SMTP::Status.name(statuscode)
46
47
 
47
- # Delivery status code points "emailtoolarge".
48
+ # Delivery status code points "EmailTooLarge".
48
49
  # Status: 5.3.4
49
50
  # Diagnostic-Code: SMTP; 552 5.3.4 Error: message file too big
50
51
  #
51
52
  # Status: 5.2.3
52
53
  # Deiagnostic-Code: Message length exceeds administrative limit
53
- return true if tempreason == 'emailtoolarge'
54
+ return true if tempreason == Sisimai::Eb::ReSIZE
54
55
  return match(argvs['diagnosticcode'].downcase)
55
56
  end
56
57
 
@@ -1,34 +1,46 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::Expired checks the bounce reason is "expired" or not. This class is called only
3
+ # Sisimai::Reason::Expired checks the bounce reason is "Expired" or not. This class is called only
4
4
  # Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that delivery time has expired due to connection failure or network error and
7
7
  # the message you sent has been in the queue for long time.
8
8
  module Expired
9
9
  class << self
10
+ require 'sisimai/eb'
10
11
  Index = [
11
12
  "connection timed out",
12
13
  "could not find a gateway for",
14
+ "delay reason: ", # Exim/deliver.c:7459
13
15
  "delivery attempts will continue to be",
16
+ "envelope expired", # OpenSMTPD/smtpd/queue.c:221
14
17
  "failed to deliver to domain ",
15
- "have been failing for a long time",
18
+ "frozen on arrival", # Exim/receive.c:4022
16
19
  "has been delayed",
20
+ "has been frozen", # Exim/deliver.c:7586
21
+ "have been failing for a long time", # Exim/smtp.c:3508
22
+ "host not reachable",
17
23
  "it has not been collected after",
18
24
  "message could not be delivered for more than",
19
25
  "message expired, ",
20
26
  "message has been in the queue too long",
27
+ "message was not delivered within ",
21
28
  "message timed out",
29
+ "retry timeout exceeded", # Exim/retry.c:902
30
+ "server did not accept our requests to connect",
22
31
  "server did not respond",
23
32
  "unable to deliver message after multiple retries",
24
33
  ].freeze
25
34
  Pairs = [
26
35
  ["could not be delivered for", " days"],
36
+ ["could not deliver for the last", "second"],
27
37
  ["delivery ", "expired"],
28
- ["not", "reach", "period"],
38
+ ["delivery ", "delayed"],
39
+ ["exceed", "time", "out"],
40
+ ["not", "reach", "period"], # Exim/smtp.c:3508
29
41
  ].freeze
30
42
 
31
- def text; return 'expired'; end
43
+ def text; return Sisimai::Eb::ReTIME; end
32
44
  def description; return 'Delivery time has expired due to a connection failure'; end
33
45
 
34
46
  # Try to match that the given text and regular expressions
@@ -1,16 +1,18 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::FailedSTARTTLS checks the bounce reason is "failedstarttls" or not.
3
+ # Sisimai::Reason::FailedSTARTTLS checks the bounce reason is "FailedSTARTTLS" or not.
4
4
  # This class is called only Sisimai::Reason class.
5
5
  module FailedSTARTTLS
6
6
  class << self
7
+ require 'sisimai/eb'
8
+
7
9
  # Email delivery failed due to STARTTLS related problem
8
10
  Index = [
9
11
  'starttls is required to send mail',
10
12
  'tls required but not supported', # SendGrid:the recipient mailserver does not support TLS or have a valid certificate
11
13
  ].freeze
12
14
 
13
- def text; return 'failedstarttls'; end
15
+ def text; return Sisimai::Eb::ReTTLS; end
14
16
  def description; return "Email delivery failed due to STARTTLS related problem"; end
15
17
 
16
18
  # Try to match that the given text and regular expressions
@@ -28,7 +30,7 @@ module Sisimai
28
30
  # false: Not FailedSTARTTLS
29
31
  # @see http://www.ietf.org/rfc/rfc2822.txt
30
32
  def true(argvs)
31
- return true if argvs["reason"] == "failedstarttls" || argvs["command"] == "STARTTLS"
33
+ return true if argvs["reason"] == Sisimai::Eb::ReTTLS || argvs["command"] == Sisimai::Eb::CeTTLS
32
34
  return true if [523, 524, 538].index(argvs["replycode"].to_i)
33
35
  return match(argvs["diagnosticcode"].downcase)
34
36
  end
@@ -4,7 +4,8 @@ module Sisimai
4
4
  # from Sisimai.reason method and Sisimai::ARF class.
5
5
  module Feedback
6
6
  class << self
7
- def text; return 'feedback'; end
7
+ require 'sisimai/eb'
8
+ def text; return Sisimai::Eb::ReFEED; end
8
9
  def description; return 'Email forwarded to the sender as a complaint message from your mailbox provider'; end
9
10
  def match; return false; end
10
11
  def true(*); return false; end
@@ -1,14 +1,15 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::Filtered checks the bounce reason is "filtered" or not. This class is called
3
+ # Sisimai::Reason::Filtered checks the bounce reason is "Filtered" or not. This class is called
4
4
  # only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that an email has been rejected by a header content after SMTP DATA command.
7
7
  # In Japanese cellular phones, the error will incur that a sender's email address or a domain
8
- # is rejected by recipient's email configuration. Sisimai will set "filtered" to the reason of
8
+ # is rejected by recipient's email configuration. Sisimai will set "Filtered" to the reason of
9
9
  # email bounce if the value of Status: field in a bounce email is "5.2.0" or "5.2.1".
10
10
  module Filtered
11
11
  class << self
12
+ require 'sisimai/eb'
12
13
  Index = [
13
14
  "account is protected by",
14
15
  "has restricted sms e-mail", # AT&T
@@ -24,7 +25,7 @@ module Sisimai
24
25
  "you have been blocked by the recipient",
25
26
  ].freeze
26
27
 
27
- def text; return 'filtered'; end
28
+ def text; return Sisimai::Eb::ReFILT; end
28
29
  def description; return 'Email rejected due to a header content after SMTP DATA command'; end
29
30
 
30
31
  # Try to match that the given text and regular expressions
@@ -42,19 +43,19 @@ module Sisimai
42
43
  # false: is not filtered
43
44
  # @see http://www.ietf.org/rfc/rfc2822.txt
44
45
  def true(argvs)
45
- return true if argvs['reason'] == 'filtered'
46
+ return true if argvs['reason'] == Sisimai::Eb::ReFILT
46
47
 
47
48
  tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus'])
48
- return false if tempreason == 'suspend'
49
+ return false if tempreason == Sisimai::Eb::ReQUIT
49
50
 
50
51
  issuedcode = argvs['diagnosticcode'].downcase || ''
51
52
  thecommand = argvs['command'] || ''
52
- if tempreason == 'filtered'
53
- # Delivery status code points "filtered".
53
+ if tempreason == Sisimai::Eb::ReFILT
54
+ # Delivery status code points "Filtered".
54
55
  require 'sisimai/reason/userunknown'
55
56
  return true if Sisimai::Reason::UserUnknown.match(issuedcode) || match(issuedcode)
56
57
  else
57
- # The value of "reason" isn't "filtered" when the value of "command" is an SMTP command
58
+ # The value of "reason" isn't "Filtered" when the value of "command" is an SMTP command
58
59
  # to be sent before the SMTP DATA command because all the MTAs read the headers and the
59
60
  # entire message body after the DATA command.
60
61
  return false if Sisimai::SMTP::Command::ExceptDATA.include?(thecommand)
@@ -1,16 +1,17 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::HasMoved checks the bounce reason is "hasmoved" or not. This class is called
3
+ # Sisimai::Reason::HasMoved checks the bounce reason is "HasMoved" or not. This class is called
4
4
  # only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that a user's mailbox has moved (and is not forwarded automatically). Sisimai
7
- # will set "hasmoved" to the reason of email bounce if the value of Status: field in a bounce email
7
+ # will set "HasMoved" to the reason of email bounce if the value of Status: field in a bounce email
8
8
  # is "5.1.6".
9
9
  module HasMoved
10
10
  class << self
11
+ require 'sisimai/eb'
11
12
  Index = [' has been replaced by '].freeze
12
13
 
13
- def text; return 'hasmoved'; end
14
+ def text; return Sisimai::Eb::ReMOVE; end
14
15
  def description; return "Email rejected due to user's mailbox has moved and is not forwarded automatically"; end
15
16
 
16
17
  # Try to match that the given text and regular expressions
@@ -28,7 +29,7 @@ module Sisimai
28
29
  # false: Has not moved
29
30
  # @see http://www.ietf.org/rfc/rfc2822.txt
30
31
  def true(argvs)
31
- return true if argvs['reason'] == 'hasmoved'
32
+ return true if argvs['reason'] == Sisimai::Eb::ReMOVE
32
33
  return false if Sisimai::SMTP::Command::BeforeRCPT.include?(argvs['command'])
33
34
  return match(argvs['diagnosticcode'].downcase)
34
35
  end
@@ -2,28 +2,38 @@ module Sisimai
2
2
  module Reason
3
3
  # This is the error that a domain part ( Right hand side of @ sign ) of a recipient's email
4
4
  # address does not exist. In many case, the domain part is misspelled, or the domain name has
5
- # been expired. Sisimai will set "hostunknown" to the reason of email bounce if the value of
5
+ # been expired. Sisimai will set "HostUnknown" to the reason of email bounce if the value of
6
6
  # Status: field in a bounce mail is "5.1.2".
7
7
  module HostUnknown
8
8
  class << self
9
+ require 'sisimai/eb'
9
10
  Index = [
11
+ "all host address lookups failed", # Exim/transports/smtp.c:3524
12
+ "couldn't find any host ", # qmail-remote.c:78
13
+ "dns server returned answer with no data",
10
14
  "domain is not reachable",
11
15
  "domain mentioned in email address is unknown",
12
16
  "domain must exist",
17
+ "domain name not found",
13
18
  "host or domain name not found",
14
19
  "host unknown",
15
20
  "host unreachable",
21
+ "illegal host/domain name found",
22
+ "invalid domain name", # OpenSMTPD/smtpd/mta.c:976
23
+ "mx records point to non-existent hosts", # Exim/routers/dnslookup.c:331
16
24
  "name or service not known",
17
25
  "no such domain",
18
26
  "recipient address rejected: unknown domain name",
27
+ "responded with code nxdomain",
19
28
  "unknown host",
20
29
  ].freeze
21
30
  Pairs = [
22
31
  ["domain ", "not exist"],
32
+ ["host ", " not found"],
23
33
  ["unrout", "able ", "address"],
24
34
  ].freeze
25
35
 
26
- def text; return 'hostunknown'; end
36
+ def text; return Sisimai::Eb::ReHOST; end
27
37
  def description; return "Delivery failed due to a domain part of a recipient's email address does not exist"; end
28
38
 
29
39
  # Try to match that the given text and regular expressions
@@ -43,13 +53,13 @@ module Sisimai
43
53
  # false: is not unknown host.
44
54
  # @see http://www.ietf.org/rfc/rfc2822.txt
45
55
  def true(argvs)
46
- return true if argvs['reason'] == 'hostunknown'
56
+ return true if argvs['reason'] == Sisimai::Eb::ReHOST
47
57
  return false if Sisimai::SMTP::Command::BeforeRCPT.include?(argvs['command'])
48
58
 
49
59
  issuedcode = argvs['diagnosticcode'].downcase || ''
50
60
  statuscode = argvs['deliverystatus'] || ''
51
61
 
52
- if Sisimai::SMTP::Status.name(statuscode) == 'hostunknown'
62
+ if Sisimai::SMTP::Status.name(statuscode) == Sisimai::Eb::ReHOST
53
63
  # To prevent classifying DNS errors as "HostUnknown"
54
64
  require 'sisimai/reason/networkerror'
55
65
  return true if Sisimai::Reason::NetworkError.match(issuedcode) == false
@@ -1,18 +1,20 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::MailboxFull checks the bounce reason is "mailboxfull" or not. This class is
3
+ # Sisimai::Reason::MailboxFull checks the bounce reason is "MailboxFull" or not. This class is
4
4
  # called only Sisimai::Reason class.
5
5
  #
6
- # This is the error that a recipient's mailbox is full. Sisimai will set "mailboxfull" to the
6
+ # This is the error that a recipient's mailbox is full. Sisimai will set "MailboxFull" to the
7
7
  # reason of email bounce if the value of Status: field in a bounce email is "4.2.2" or "5.2.2".
8
8
  module MailboxFull
9
9
  class << self
10
+ require 'sisimai/eb'
10
11
  Index = [
11
12
  "452 insufficient disk space",
12
13
  "account disabled temporarly for exceeding receiving limits",
13
14
  "boite du destinataire pleine",
14
15
  "exceeded storage allocation",
15
16
  "full mailbox",
17
+ "mailbox exceeds allowed size",
16
18
  "mailbox size limit exceeded",
17
19
  "mailbox would exceed maximum allowed storage",
18
20
  "mailfolder is full",
@@ -29,14 +31,14 @@ module Sisimai
29
31
  ["disk", "quota"],
30
32
  ["enough ", " space"],
31
33
  ["mailbox ", "exceeded", " limit"],
32
- ["mailbox ", "full"],
34
+ ["mailbox ", "full"], # Exim/transports/appendfile.c:2567
33
35
  ["mailbox ", "quota"],
34
36
  ["maildir ", "quota"],
35
37
  ["over ", "quota"],
36
- ["quota ", "exceeded"],
38
+ ["quota ", "exceeded"], # Exim/transports/appendfile.c:3050
37
39
  ].freeze
38
40
 
39
- def text; return 'mailboxfull'; end
41
+ def text; return Sisimai::Eb::ReFULL; end
40
42
  def description; return "Email rejected due to a recipient's mailbox is full"; end
41
43
 
42
44
  # Try to match that the given text and regular expressions
@@ -56,12 +58,12 @@ module Sisimai
56
58
  # @see http://www.ietf.org/rfc/rfc2822.txt
57
59
  def true(argvs)
58
60
  return false if argvs['deliverystatus'].empty?
59
- return true if argvs['reason'] == 'mailboxfull'
61
+ return true if argvs['reason'] == Sisimai::Eb::ReFULL
60
62
 
61
- # Delivery status code points "mailboxfull".
63
+ # Delivery status code points "MailboxFull".
62
64
  # Status: 4.2.2
63
65
  # Diagnostic-Code: SMTP; 450 4.2.2 <***@example.jp>... Mailbox Full
64
- return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'mailboxfull'
66
+ return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReFULL
65
67
  return match(argvs['diagnosticcode'].downcase)
66
68
  end
67
69
 
@@ -1,6 +1,6 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::MailerError checks the bounce reason is "mailererror" or not. This class is
3
+ # Sisimai::Reason::MailerError checks the bounce reason is "MailerError" or not. This class is
4
4
  # called only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that a mailer program has not exited successfully or exited unexpectedly on
@@ -10,6 +10,7 @@ module Sisimai
10
10
  # Diagnostic-Code: X-Unix; 255
11
11
  module MailerError
12
12
  class << self
13
+ require 'sisimai/eb'
13
14
  Index = [
14
15
  ' || exit ',
15
16
  'procmail: ',
@@ -23,7 +24,7 @@ module Sisimai
23
24
  'x-unix; ',
24
25
  ].freeze
25
26
 
26
- def text; return 'mailererror'; end
27
+ def text; return Sisimai::Eb::ReUNIX; end
27
28
  def description; return 'Email returned due to a mailer program has not exited successfully'; end
28
29
 
29
30
  # Try to match that the given text and regular expressions
@@ -1,6 +1,6 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::NetworkError checks the bounce reason is "networkerror" or not. This class is
3
+ # Sisimai::Reason::NetworkError checks the bounce reason is "NetworkError" or not. This class is
4
4
  # called only Sisimai::Reason class. This is the error that SMTP connection failed due to DNS
5
5
  # look up failure or other network problems.
6
6
  #
@@ -10,14 +10,26 @@ module Sisimai
10
10
  # kijitora@neko.example.jp: Network error on destination MXs
11
11
  module NetworkError
12
12
  class << self
13
+ require 'sisimai/eb'
13
14
  Index = [
15
+ "address family mismatch on destination mxs", # OpenSMTPD/smtpd/mta.c
16
+ "all routes to destination blocked", # OpenSMTPD/smtpd/mta.c
17
+ "bad dns lookup error code", # OpenSMTPD/smtpd/mta.c
14
18
  "could not connect and send the mail to",
19
+ "could not contact dns servers",
20
+ "could not retrieve source address", # OpenSMTPD/smtpd/mta.c
15
21
  "dns records for the destination computer could not be found",
22
+ "establish an smtp connection",
23
+ "exceeded maximum hop count", # Courier
16
24
  "host is unreachable",
17
25
  "host name lookup failure",
18
26
  "host not found, try again",
27
+ "listed as a best-preference mx",
28
+ "loop detected", # OpenSMTPD/smtpd/mta.c
19
29
  "maximum forwarding loop count exceeded",
20
- "no route to host",
30
+ "network error on destination mxs", # OpenSMTPD/smtpd/mta.c
31
+ "no relevant answers",
32
+ "temporary failure in mx lookup", # OpenSMTPD/smtpd/mta.c
21
33
  "too many hops",
22
34
  "unable to resolve route ",
23
35
  "unrouteable mail domain",
@@ -26,9 +38,10 @@ module Sisimai
26
38
  ["malformed", "name server reply"],
27
39
  ["mail ", "loop"],
28
40
  ["message ", "loop"],
41
+ ["no ", "route to"],
29
42
  ].freeze
30
43
 
31
- def text; return 'networkerror'; end
44
+ def text; return Sisimai::Eb::ReINET; end
32
45
  def description; return 'SMTP connection failed due to DNS look up failure or other network problems'; end
33
46
 
34
47
  # Try to match that the given text and regular expressions
@@ -1,6 +1,6 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::NoRelaying checks the bounce reason is "norelaying" or not. This class is
3
+ # Sisimai::Reason::NoRelaying checks the bounce reason is "NoRelaying" or not. This class is
4
4
  # called only Sisimai::Reason class.
5
5
  #
6
6
  # ... while talking to mailin-01.mx.example.com.:
@@ -9,6 +9,7 @@ module Sisimai
9
9
  # 554 5.0.0 Service unavailable
10
10
  module NoRelaying
11
11
  class << self
12
+ require 'sisimai/eb'
12
13
  Index = [
13
14
  "as a relay",
14
15
  "domain isn't in my list of allowed rcpthost",
@@ -16,9 +17,10 @@ module Sisimai
16
17
  "insecure mail relay",
17
18
  "no relaying",
18
19
  "not a gateway",
19
- "not an open relay, so get lost",
20
20
  "not local host",
21
+ "open relay",
21
22
  "relay not permitted",
23
+ "relay prohibition",
22
24
  "relaying denied", # Sendmail
23
25
  "relaying mail to ",
24
26
  "send to a non-local e-mail address", # MailEnable
@@ -28,10 +30,10 @@ module Sisimai
28
30
  ].freeze
29
31
  Pairs = [
30
32
  ["relay ", "denied"],
31
- [" not ", " to relay"],
33
+ ["n", "t ", "to relay"],
32
34
  ].freeze
33
35
 
34
- def text; return 'norelaying'; end
36
+ def text; return Sisimai::Eb::RePASS; end
35
37
  def description; return 'Email rejected with error message "Relaying Denied"'; end
36
38
 
37
39
  # Try to match that the given text and regular expressions
@@ -51,8 +53,8 @@ module Sisimai
51
53
  # @see http://www.ietf.org/rfc/rfc2822.txt
52
54
  def true(argvs)
53
55
  r = argvs['reason'] || ''
54
- return false if r.start_with?('securityerror', 'systemerror', 'undefined')
55
- return false if %w[CONN EHLO HELO].include?(argvs['command'])
56
+ return false if Sisimai::SMTP::Command::BeforeRCPT.include?(argvs['command'])
57
+ return false if r.start_with?(Sisimai::Eb::ReSAFE, Sisimai::Eb::RePROC, Sisimai::Eb::Re___0)
56
58
  return match(argvs['diagnosticcode'].downcase)
57
59
  end
58
60
 
@@ -1,24 +1,31 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::NotAccept checks the bounce reason is "notaccept" or not. This class is
3
+ # Sisimai::Reason::NotAccept checks the bounce reason is "NotAccept" or not. This class is
4
4
  # called only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that a destination mail server does ( or can ) not accept any email. In
7
- # many case, the server is high load or under the maintenance. Sisimai will set "notaccept" to
7
+ # many case, the server is high load or under the maintenance. Sisimai will set "NotAccept" to
8
8
  # the reason of email bounce if the value of Status: field in a bounce email is "5.3.2" or the
9
9
  # value of SMTP reply code is 556.
10
10
  module NotAccept
11
+ require 'sisimai/eb'
11
12
  class << self
12
13
  # Destination mail server does not accept any message
13
14
  Index = [
14
- "does not accept mail", # Sendmail, iCloud
15
+ "destination seem to reject all mails", # OpenSMTPD/smtp/mta.c
16
+ "does not accept mail", # Sendmail, iCloud
15
17
  "mail receiving disabled",
16
- "name server: .: host not found", # Sendmail
17
- "no mx record found for domain=", # Oath(Yahoo!)
18
+ "mx or srv record indicated no smtp ", # Exim/routers/dnslookup.c:328
19
+ "name server: .: host not found", # Sendmail
20
+ "no host found for existing smtp ", # Exim/transports/smtp.c:3502
18
21
  "no route for current request",
22
+ "null mx",
23
+ ].freeze
24
+ Pairs = [
25
+ ["no mx ", "found for "], # OpenSMTPD/smtp/mta.c
19
26
  ].freeze
20
27
 
21
- def text; return 'notaccept'; end
28
+ def text; return Sisimai::Eb::Re00MX; end
22
29
  def description; return 'Delivery failed due to a destination mail server does not accept any email'; end
23
30
 
24
31
  # Try to match that the given text and regular expressions
@@ -27,6 +34,7 @@ module Sisimai
27
34
  def match(argv1)
28
35
  return false if argv1.nil? || argv1.empty?
29
36
  return true if Index.any? { |a| argv1.include?(a) }
37
+ return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
30
38
  return false
31
39
  end
32
40
 
@@ -36,7 +44,7 @@ module Sisimai
36
44
  # false: Accept
37
45
  # @see http://www.ietf.org/rfc/rfc2822.txt
38
46
  def true(argvs)
39
- return true if argvs['reason'] == 'notaccept'
47
+ return true if argvs['reason'] == Sisimai::Eb::Re00MX
40
48
  return true if [521, 556].index(argvs['replycode'].to_i) # SMTP Reply Code is 554 or 556
41
49
  return false if Sisimai::SMTP::Command::BeforeRCPT.include?(argvs['command'])
42
50
  return match(argvs['diagnosticcode'].downcase)
@@ -1,21 +1,23 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::NotCompliantRFC checks the bounce reason is "notcompliantrfc" or not. This
3
+ # Sisimai::Reason::NotCompliantRFC checks the bounce reason is "NotCompliantRFC" or not. This
4
4
  # class is called only from Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that an email is not compliant RFC 5322 or other email related RFCs. For
7
7
  # example, there are multiple "Subject" headers in the email.
8
8
  module NotCompliantRFC
9
9
  class << self
10
+ require 'sisimai/eb'
10
11
  Index = [
11
12
  "duplicate header",
13
+ "duplicated message-id",
12
14
  "message is not rfc 5322 compliant",
13
15
  "multiple addresses in from: header are not accepted",
14
16
  "rfc 1035 violation",
15
17
  "https://support.google.com/mail/?p=rfcmessagenoncompliant",
16
18
  ].freeze
17
19
 
18
- def text; return 'notcompliantrfc'; end
20
+ def text; return Sisimai::Eb::ReNRFC; end
19
21
  def description; return 'Email rejected due to non-compliance with RFC'; end
20
22
 
21
23
  # Try to match that the given text and regular expressions
@@ -33,7 +35,7 @@ module Sisimai
33
35
  # false: Is not RFC compliant
34
36
  # @see http://www.ietf.org/rfc/rfc5322.txt
35
37
  def true(argvs)
36
- return true if argvs['reason'] == 'notcompliantrfc'
38
+ return true if argvs['reason'] == Sisimai::Eb::ReNRFC
37
39
  return match(argvs['diagnosticcode'].downcase)
38
40
  end
39
41