sisimai 5.7.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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +15 -0
  3. data/README-JA.md +8 -8
  4. data/README.md +8 -8
  5. data/lib/sisimai/arf.rb +2 -1
  6. data/lib/sisimai/eb.rb +116 -0
  7. data/lib/sisimai/fact.rb +24 -17
  8. data/lib/sisimai/lda.rb +20 -18
  9. data/lib/sisimai/lhost/amazonses.rb +11 -10
  10. data/lib/sisimai/lhost/courier.rb +4 -3
  11. data/lib/sisimai/lhost/domino.rb +2 -1
  12. data/lib/sisimai/lhost/einsundeins.rb +3 -2
  13. data/lib/sisimai/lhost/exchange2003.rb +8 -7
  14. data/lib/sisimai/lhost/exchange2007.rb +14 -13
  15. data/lib/sisimai/lhost/exim.rb +7 -6
  16. data/lib/sisimai/lhost/ezweb.rb +4 -3
  17. data/lib/sisimai/lhost/fml.rb +4 -3
  18. data/lib/sisimai/lhost/gmail.rb +10 -9
  19. data/lib/sisimai/lhost/googlegroups.rb +3 -2
  20. data/lib/sisimai/lhost/googleworkspace.rb +2 -1
  21. data/lib/sisimai/lhost/imailserver.rb +3 -2
  22. data/lib/sisimai/lhost/kddi.rb +4 -3
  23. data/lib/sisimai/lhost/notes.rb +2 -1
  24. data/lib/sisimai/lhost/postfix.rb +7 -6
  25. data/lib/sisimai/lhost/qmail.rb +10 -9
  26. data/lib/sisimai/lhost/sendmail.rb +4 -3
  27. data/lib/sisimai/lhost/trendmicro.rb +2 -1
  28. data/lib/sisimai/lhost/v5sendmail.rb +2 -1
  29. data/lib/sisimai/lhost/verizon.rb +3 -2
  30. data/lib/sisimai/reason/authfailure.rb +6 -5
  31. data/lib/sisimai/reason/badreputation.rb +5 -4
  32. data/lib/sisimai/reason/blocked.rb +6 -5
  33. data/lib/sisimai/reason/contenterror.rb +6 -5
  34. data/lib/sisimai/reason/delivered.rb +3 -2
  35. data/lib/sisimai/reason/emailtoolarge.rb +6 -5
  36. data/lib/sisimai/reason/expired.rb +3 -2
  37. data/lib/sisimai/reason/failedstarttls.rb +5 -3
  38. data/lib/sisimai/reason/feedback.rb +2 -1
  39. data/lib/sisimai/reason/filtered.rb +9 -8
  40. data/lib/sisimai/reason/hasmoved.rb +5 -4
  41. data/lib/sisimai/reason/hostunknown.rb +5 -4
  42. data/lib/sisimai/reason/mailboxfull.rb +7 -6
  43. data/lib/sisimai/reason/mailererror.rb +3 -2
  44. data/lib/sisimai/reason/networkerror.rb +3 -2
  45. data/lib/sisimai/reason/norelaying.rb +4 -3
  46. data/lib/sisimai/reason/notaccept.rb +5 -4
  47. data/lib/sisimai/reason/notcompliantrfc.rb +4 -3
  48. data/lib/sisimai/reason/onhold.rb +8 -7
  49. data/lib/sisimai/reason/policyviolation.rb +7 -6
  50. data/lib/sisimai/reason/ratelimited.rb +5 -4
  51. data/lib/sisimai/reason/rejected.rb +18 -14
  52. data/lib/sisimai/reason/requireptr.rb +5 -4
  53. data/lib/sisimai/reason/securityerror.rb +4 -3
  54. data/lib/sisimai/reason/spamdetected.rb +6 -5
  55. data/lib/sisimai/reason/suppressed.rb +4 -3
  56. data/lib/sisimai/reason/suspend.rb +4 -3
  57. data/lib/sisimai/reason/syntaxerror.rb +4 -3
  58. data/lib/sisimai/reason/systemerror.rb +3 -2
  59. data/lib/sisimai/reason/systemfull.rb +4 -3
  60. data/lib/sisimai/reason/undefined.rb +2 -1
  61. data/lib/sisimai/reason/userunknown.rb +13 -9
  62. data/lib/sisimai/reason/vacation.rb +2 -1
  63. data/lib/sisimai/reason/virusdetected.rb +6 -5
  64. data/lib/sisimai/reason.rb +45 -40
  65. data/lib/sisimai/rfc1894.rb +8 -2
  66. data/lib/sisimai/rfc2045.rb +6 -3
  67. data/lib/sisimai/rfc3464/thirdparty.rb +10 -9
  68. data/lib/sisimai/rfc3834.rb +4 -2
  69. data/lib/sisimai/rhost/aol.rb +3 -2
  70. data/lib/sisimai/rhost/apple.rb +12 -11
  71. data/lib/sisimai/rhost/cloudflare.rb +3 -2
  72. data/lib/sisimai/rhost/cox.rb +38 -37
  73. data/lib/sisimai/rhost/facebook.rb +17 -16
  74. data/lib/sisimai/rhost/franceptt.rb +39 -38
  75. data/lib/sisimai/rhost/godaddy.rb +35 -34
  76. data/lib/sisimai/rhost/google.rb +22 -21
  77. data/lib/sisimai/rhost/gsuite.rb +8 -7
  78. data/lib/sisimai/rhost/iua.rb +11 -10
  79. data/lib/sisimai/rhost/kddi.rb +3 -2
  80. data/lib/sisimai/rhost/messagelabs.rb +13 -12
  81. data/lib/sisimai/rhost/microsoft.rb +33 -32
  82. data/lib/sisimai/rhost/mimecast.rb +18 -17
  83. data/lib/sisimai/rhost/nttdocomo.rb +10 -9
  84. data/lib/sisimai/rhost/outlook.rb +3 -2
  85. data/lib/sisimai/rhost/spectrum.rb +19 -18
  86. data/lib/sisimai/rhost/tencent.rb +10 -9
  87. data/lib/sisimai/rhost/yahooinc.rb +11 -10
  88. data/lib/sisimai/rhost/zoho.rb +8 -7
  89. data/lib/sisimai/smtp/command.rb +13 -8
  90. data/lib/sisimai/smtp/failure.rb +9 -8
  91. data/lib/sisimai/smtp/reply.rb +23 -22
  92. data/lib/sisimai/smtp/status.rb +141 -140
  93. data/lib/sisimai/smtp/transcript.rb +3 -2
  94. data/lib/sisimai/version.rb +1 -1
  95. data/lib/sisimai.rb +2 -1
  96. data/set-of-emails/maildir/bsd/lhost-postfix-81.eml +130 -0
  97. data/set-of-emails/should-not-crash/go-423-deeply-nested-mime-parts.eml +20050 -0
  98. metadata +5 -2
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Exim
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  require 'sisimai/rfc1894'
8
9
 
@@ -60,12 +61,12 @@ module Sisimai::Lhost
60
61
  MessagesOf = {
61
62
  # find exim/ -type f -exec grep 'message = US' {} /dev/null \;
62
63
  # route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
63
- "userunknown" => ["user not found"],
64
+ Sisimai::Eb::ReUSER => ["user not found"],
64
65
  # parser.c:666| *errorptr = string_sprintf("%s (expected word or \"<\")", *errorptr);
65
66
  # parser.c:701| if(bracket_count++ > 5) FAILED(US"angle-brackets nested too deep");
66
67
  # parser.c:738| FAILED(US"domain missing in source-routed address");
67
68
  # parser.c:747| : string_sprintf("malformed address: %.32s may not follow %.*s",
68
- "syntaxerror" => [
69
+ Sisimai::Eb::ReCOMM => [
69
70
  "angle-brackets nested too deep",
70
71
  'expected word or "<"',
71
72
  "domain missing in source-routed address",
@@ -389,8 +390,8 @@ module Sisimai::Lhost
389
390
  case e["command"]
390
391
  # - HELO | Connected to 192.0.2.135 but my name was rejected.
391
392
  # - MAIL | Connected to 192.0.2.135 but sender was rejected.
392
- when "HELO", "EHLO" then e["reason"] = "blocked"
393
- when "MAIL" then e["reason"] = "onhold"
393
+ when Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO then e["reason"] = Sisimai::Eb::ReBLOC
394
+ when Sisimai::Eb::CeMAIL then e["reason"] = Sisimai::Eb::Re___1
394
395
  else
395
396
  # Try to match the error message with each message pattern
396
397
  MessagesOf.each_key do |r|
@@ -401,7 +402,7 @@ module Sisimai::Lhost
401
402
  end
402
403
 
403
404
  if e["reason"].empty?
404
- e["reason"] = "expired" if DelayedFor.any? { |a| e["diagnosis"].include?(a) }
405
+ e["reason"] = Sisimai::Eb::ReTIME if DelayedFor.any? { |a| e["diagnosis"].include?(a) }
405
406
  end
406
407
  end
407
408
  end
@@ -420,7 +421,7 @@ module Sisimai::Lhost
420
421
  re = e["reason"]
421
422
  cv = ""
422
423
 
423
- if Sisimai::SMTP::Failure.is_temporary(cr) || re == "expired"
424
+ if Sisimai::SMTP::Failure.is_temporary(cr) || re == Sisimai::Eb::ReTIME
424
425
  # Set the pseudo status code as a temporary error
425
426
  cv = Sisimai::SMTP::Status.code(re, true) if Sisimai::Reason.is_explicit(re)
426
427
  end
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module EZweb
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
@@ -100,14 +101,14 @@ module Sisimai::Lhost
100
101
  if mhead['x-spasign'].to_s == 'NG'
101
102
  # Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
102
103
  # Filtered recipient returns message that include 'X-SPASIGN' header
103
- e['reason'] = 'filtered'
104
+ e['reason'] = Sisimai::Eb::ReFILT
104
105
  else
105
106
  # There is no X-SPASIGN header or the value of the header is not "NG"
106
- e['reason'] = "suspend" if UnpaidUser.any? { |a| e['diagnosis'].include?(a) }
107
+ e['reason'] = Sisimai::Eb::ReQUIT if UnpaidUser.any? { |a| e['diagnosis'].include?(a) }
107
108
  end
108
109
  next if e['reason'] != ""
109
110
  next if e['recipient'].end_with?('@ezweb.ne.jp', '@au.com')
110
- e["reason"] = "userunknown" if e["diagnosis"].start_with?("<")
111
+ e["reason"] = Sisimai::Eb::ReUSER if e["diagnosis"].start_with?("<")
111
112
  end
112
113
 
113
114
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
@@ -3,24 +3,25 @@ module Sisimai::Lhost
3
3
  # https://www.fml.org/. Methods in the module are called from only Sisimai::Message.
4
4
  module FML
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
9
10
  Boundaries = ['Original mail as follows:'].freeze
10
11
  ErrorTitle = {
11
- 'rejected' => [
12
+ Sisimai::Eb::ReFROM => [
12
13
  ' are not member',
13
14
  'NOT MEMBER article from ',
14
15
  'reject mail ',
15
16
  'Spam mail from a spammer is rejected',
16
17
  ],
17
- 'systemerror' => [
18
+ Sisimai::Eb::RePROC => [
18
19
  'fml system error message',
19
20
  'Loop Alert: ',
20
21
  'Loop Back Warning: ',
21
22
  'WARNING: UNIX FROM Loop',
22
23
  ],
23
- 'securityerror' => ['Security Alert'],
24
+ Sisimai::Eb::ReSAFE => ['Security Alert'],
24
25
  }.freeze
25
26
 
26
27
  # @abstract Decodes the bounce message from fml mailling list server/manager
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Gmail
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
@@ -17,7 +18,7 @@ module Sisimai::Lhost
17
18
  # We recommend contacting the other email provider for further information about the
18
19
  # cause of this error. The error that the other server returned was:
19
20
  # 500 Remote server does not support TLS (state 6).
20
- '6' => { 'command' => 'MAIL', 'reason' => 'failedstarttls' },
21
+ '6' => { 'command' => Sisimai::Eb::CeMAIL, 'reason' => Sisimai::Eb::ReTTLS },
21
22
 
22
23
  # https://www.google.td/support/forum/p/gmail/thread?tid=08a60ebf5db24f7b&hl=en
23
24
  # Technical details of permanent failure:
@@ -25,7 +26,7 @@ module Sisimai::Lhost
25
26
  # We recommend contacting the other email provider for further information about the
26
27
  # cause of this error. The error that the other server returned was:
27
28
  # 535 SMTP AUTH failed with the remote server. (state 8).
28
- '8' => { 'command' => 'AUTH', 'reason' => 'systemerror' },
29
+ '8' => { 'command' => Sisimai::Eb::CeAUTH, 'reason' => Sisimai::Eb::RePROC },
29
30
 
30
31
  # https://www.google.co.nz/support/forum/p/gmail/thread?tid=45208164dbca9d24&hl=en
31
32
  # Technical details of temporary failure:
@@ -33,7 +34,7 @@ module Sisimai::Lhost
33
34
  # We recommend contacting the other email provider for further information about the
34
35
  # cause of this error. The error that the other server returned was:
35
36
  # 454 454 TLS missing certificate: error:0200100D:system library:fopen:Permission denied (#4.3.0) (state 9).
36
- '9' => { 'command' => 'AUTH', 'reason' => 'failedstarttls' },
37
+ '9' => { 'command' => Sisimai::Eb::CeAUTH, 'reason' => Sisimai::Eb::ReTTLS },
37
38
 
38
39
  # https://www.google.com/support/forum/p/gmail/thread?tid=5cfab8c76ec88638&hl=en
39
40
  # Technical details of permanent failure:
@@ -41,14 +42,14 @@ module Sisimai::Lhost
41
42
  # We recommend contacting the other email provider for further information about the
42
43
  # cause of this error. The error that the other server returned was:
43
44
  # 500 Remote server does not support SMTP Authenticated Relay (state 12).
44
- '12' => { 'command' => 'AUTH', 'reason' => 'norelaying' },
45
+ '12' => { 'command' => Sisimai::Eb::CeAUTH, 'reason' => Sisimai::Eb::RePASS },
45
46
 
46
47
  # Technical details of permanent failure:
47
48
  # Google tried to deliver your message, but it was rejected by the recipient domain.
48
49
  # We recommend contacting the other email provider for further information about the
49
50
  # cause of this error. The error that the other server returned was:
50
51
  # 550 550 5.7.1 <****@gmail.com>... Access denied (state 13).
51
- '13' => { 'command' => 'EHLO', 'reason' => 'blocked' },
52
+ '13' => { 'command' => Sisimai::Eb::CeEHLO, 'reason' => Sisimai::Eb::ReBLOC },
52
53
 
53
54
  # Technical details of permanent failure:
54
55
  # Google tried to deliver your message, but it was rejected by the recipient domain.
@@ -57,7 +58,7 @@ module Sisimai::Lhost
57
58
  # 550 550 5.1.1 <******@*********.**>... User Unknown (state 14).
58
59
  # 550 550 5.2.2 <*****@****.**>... Mailbox Full (state 14).
59
60
  #
60
- '14' => { 'command' => 'RCPT', 'reason' => 'userunknown' },
61
+ '14' => { 'command' => Sisimai::Eb::CeRCPT, 'reason' => Sisimai::Eb::ReUSER },
61
62
 
62
63
  # https://www.google.cz/support/forum/p/gmail/thread?tid=7090cbfd111a24f9&hl=en
63
64
  # Technical details of permanent failure:
@@ -66,7 +67,7 @@ module Sisimai::Lhost
66
67
  # cause of this error. The error that the other server returned was:
67
68
  # 550 550 5.7.1 SPF unauthorized mail is prohibited. (state 15).
68
69
  # 554 554 Error: no valid recipients (state 15).
69
- '15' => { 'command' => 'DATA', 'reason' => 'filtered' },
70
+ '15' => { 'command' => Sisimai::Eb::CeDATA, 'reason' => Sisimai::Eb::ReFILT },
70
71
 
71
72
  # https://www.google.com/support/forum/p/Google%20Apps/thread?tid=0aac163bc9c65d8e&hl=en
72
73
  # Technical details of permanent failure:
@@ -75,14 +76,14 @@ module Sisimai::Lhost
75
76
  # cause of this error. The error that the other server returned was:
76
77
  # 550 550 <****@***.**> No such user here (state 17).
77
78
  # 550 550 #5.1.0 Address rejected ***@***.*** (state 17).
78
- '17' => { 'command' => 'DATA', 'reason' => 'filtered' },
79
+ '17' => { 'command' => Sisimai::Eb::CeDATA, 'reason' => Sisimai::Eb::ReFILT },
79
80
 
80
81
  # Technical details of permanent failure:
81
82
  # Google tried to deliver your message, but it was rejected by the recipient domain.
82
83
  # We recommend contacting the other email provider for further information about the
83
84
  # cause of this error. The error that the other server returned was:
84
85
  # 550 550 Unknown user *****@***.**.*** (state 18).
85
- '18' => { 'command' => 'DATA', 'reason' => 'filtered' },
86
+ '18' => { 'command' => Sisimai::Eb::CeDATA, 'reason' => Sisimai::Eb::ReFILT },
86
87
  }.freeze
87
88
 
88
89
  # @abstract Decodes the bounce message from Gmail
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module GoogleGroups
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  Boundaries = ['----- Original message -----', 'Content-Type: message/rfc822'].freeze
8
9
 
@@ -47,10 +48,10 @@ module Sisimai::Lhost
47
48
  receivedby = mhead['received'] || []
48
49
  recordwide = {
49
50
  'diagnosis' => entiremesg,
50
- 'reason' => 'onhold',
51
+ 'reason' => Sisimai::Eb::Re___1,
51
52
  'rhost' => Sisimai::RFC5322.received(receivedby[0])[1],
52
53
  }
53
- recordwide['reason'] = 'rejected' if emailparts[0].scan(/^[ ]?[*][ ]?/).size == 4
54
+ recordwide['reason'] = Sisimai::Eb::ReFROM if emailparts[0].scan(/^[ ]?[*][ ]?/).size == 4
54
55
 
55
56
  mhead['x-failed-recipients'].split(',').each do |e|
56
57
  # X-Failed-Recipients: neko@example.jp, nyaan@example.org, ...
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called only from Sisimai::Message.
4
4
  module GoogleWorkspace
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  require 'sisimai/string'
8
9
  require 'sisimai/address'
@@ -14,7 +15,7 @@ module Sisimai::Lhost
14
15
  error: ["The response was:", "The response from the remote server was:"],
15
16
  }.freeze
16
17
  MessagesOf = {
17
- "userunknown" => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
+ Sisimai::Eb::ReUSER => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
19
  }.freeze
19
20
 
20
21
  # @abstract Decodes the bounce message from Google Workspace
@@ -4,13 +4,14 @@ module Sisimai::Lhost
4
4
  # Methods in the module are called from only Sisimai::Message.
5
5
  module IMailServer
6
6
  class << self
7
+ require 'sisimai/eb'
7
8
  require 'sisimai/lhost'
8
9
 
9
10
  Boundaries = ['Original message follows.'].freeze
10
11
  StartingOf = {error: ['Body of message generated response:']}.freeze
11
12
  MessagesOf = {
12
- 'userunknown' => ['Unknown user', 'Invalid final delivery userid'],
13
- 'expired' => ['Delivery failed '],
13
+ Sisimai::Eb::ReUSER => ['Unknown user', 'Invalid final delivery userid'],
14
+ Sisimai::Eb::ReTIME => ['Delivery failed '],
14
15
  }.freeze
15
16
 
16
17
  # @abstract Decodes the bounce message from Progress iMail Server
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module KDDI
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
@@ -72,11 +73,11 @@ module Sisimai::Lhost
72
73
  if mhead['x-spasign'].to_s == 'NG'
73
74
  # Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by KDDI)
74
75
  # Filtered recipient returns message that include 'X-SPASIGN' header
75
- e['reason'] = 'filtered'
76
+ e['reason'] = Sisimai::Eb::ReFILT
76
77
  else
77
78
  # There is no X-SPASIGN: header in the bounce message
78
- # set "userunknown" when the remote server rejected after RCPT command.
79
- e['reason'] = 'userunknown' if e['command'] == 'RCPT'
79
+ # set "UserUnknown" when the remote server rejected after RCPT command.
80
+ e['reason'] = Sisimai::Eb::ReUSER if e['command'] == Sisimai::Eb::CeRCPT
80
81
  end
81
82
  end
82
83
 
@@ -3,13 +3,14 @@ module Sisimai::Lhost
3
3
  # (formerly Lotus Notes Server)). Methods in the module are called from only Sisimai::Message.
4
4
  module Notes
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
9
10
  Boundaries = ['------- Returned Message --------'].freeze
10
11
  StartingOf = {message: ['------- Failure Reasons ']}.freeze
11
12
  MessagesOf = {
12
- 'userunknown' => [
13
+ Sisimai::Eb::ReUSER => [
13
14
  'User not listed in public Name & Address Book',
14
15
  'ディレクトリのリストにありません',
15
16
  ],
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Postfix
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  require 'sisimai/rfc1123'
8
9
  require 'sisimai/smtp/reply'
@@ -65,12 +66,12 @@ module Sisimai::Lhost
65
66
 
66
67
  case e["command"]
67
68
  # Use the argument of EHLO/HELO command as a value of "lhost"
68
- when "HELO", "EHLO" then v['lhost'] = e['argument']
69
- when "MAIL"
69
+ when Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO then v['lhost'] = e['argument']
70
+ when Sisimai::Eb::CeMAIL
70
71
  # Set the argument of "MAIL" command to pseudo To: header of the original message
71
72
  emailparts[1] += sprintf("To: %s\n", e['argument']) if emailparts[1].size == 0
72
73
 
73
- when "RCPT"
74
+ when Sisimai::Eb::CeRCPT
74
75
  # RCPT TO: <...>
75
76
  if v["recipient"] != ""
76
77
  # There are multiple recipient addresses in the transcript of session
@@ -277,9 +278,9 @@ module Sisimai::Lhost
277
278
  end
278
279
  end
279
280
 
280
- e['command'] = commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis'])
281
- e['command'] = 'HELO' if e["command"].empty? && e['diagnosis'].include?('refused to talk to me:')
282
- e['spec'] = 'SMTP' if e["spec"].empty? && Sisimai::String.aligned(e['diagnosis'], ['host ', ' said:'])
281
+ e['command'] = commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis'])
282
+ e['command'] = Sisimai::Eb::CeHELO if e["command"].empty? && e['diagnosis'].include?('refused to talk to me:')
283
+ e['spec'] = 'SMTP' if e["spec"].empty? && Sisimai::String.aligned(e['diagnosis'], ['host ', ' said:'])
283
284
  end
284
285
 
285
286
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
@@ -4,6 +4,7 @@ module Sisimai::Lhost
4
4
  # Methods in the module are called from only Sisimai::Message.
5
5
  module Qmail
6
6
  class << self
7
+ require 'sisimai/eb'
7
8
  require 'sisimai/lhost'
8
9
  require 'sisimai/string'
9
10
 
@@ -49,27 +50,27 @@ module Sisimai::Lhost
49
50
  }.freeze
50
51
  CommandSet = {
51
52
  # qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
52
- "CONN" => [" but greeting failed."],
53
+ Sisimai::Eb::CeCONN => [" but greeting failed."],
53
54
  # qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
54
- "EHLO" => [" but my name was rejected."],
55
+ Sisimai::Eb::CeEHLO => [" but my name was rejected."],
55
56
  # qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
56
57
  # reason = rejected
57
- "MAIL" => [" but sender was rejected."],
58
+ Sisimai::Eb::CeMAIL => [" but sender was rejected."],
58
59
  # qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
59
60
  # qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
60
61
  # reason = userunknown
61
- "RCPT" => [" does not like recipient."],
62
+ Sisimai::Eb::CeRCPT => [" does not like recipient."],
62
63
  # qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
63
64
  # qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
64
65
  # qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
65
66
  # qmail-remote.c:272| if (code >= 400) quit("Z"," failed after I sent the message");
66
- "DATA" => [" failed on DATA command", " failed after I sent the message"],
67
+ Sisimai::Eb::CeDATA => [" failed on DATA command", " failed after I sent the message"],
67
68
  }.freeze
68
69
 
69
70
  MessagesOf = {
70
71
  # notqmail 1.08 returns the following error message when the destination MX is NullMX
71
- "notaccept" => ["Sorry, I couldn't find a mail exchanger or IP address"],
72
- "userunknown" => ["no mailbox here by that name"],
72
+ Sisimai::Eb::Re00MX => ["Sorry, I couldn't find a mail exchanger or IP address"],
73
+ Sisimai::Eb::ReUSER => ["no mailbox here by that name"],
73
74
  }.freeze
74
75
 
75
76
  # @abstract Decodes the bounce message from qmail
@@ -158,9 +159,9 @@ module Sisimai::Lhost
158
159
  end
159
160
 
160
161
  # Detect the reason of bounce
161
- if %w[HELO EHLO].index(e["command"])
162
+ if [Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO].index(e["command"])
162
163
  # HELO | Connected to 192.0.2.135 but my name was rejected.
163
- e["reason"] = "blocked"
164
+ e["reason"] = Sisimai::Eb::ReBLOC
164
165
  else
165
166
  # Try to match with each error message in the table
166
167
  # Check that the error message includes any of message patterns or not
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Sendmail
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  require 'sisimai/rfc1123'
8
9
  require 'sisimai/smtp/reply'
@@ -187,9 +188,9 @@ module Sisimai::Lhost
187
188
  break
188
189
  end
189
190
 
190
- e["command"] = thecommand if e["command"].empty?
191
- e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
192
- e["command"] = "EHLO" if e["command"].empty? && esmtpreply.size > 0
191
+ e["command"] = thecommand if e["command"].empty?
192
+ e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
193
+ e["command"] = Sisimai::Eb::CeEHLO if e["command"].empty? && esmtpreply.size > 0
193
194
 
194
195
  while true
195
196
  # Check alternative status code and override it
@@ -4,6 +4,7 @@ module Sisimai::Lhost
4
4
  # Methods in the module are called from only Sisimai::Message.
5
5
  module TrendMicro
6
6
  class << self
7
+ require 'sisimai/eb'
7
8
  require 'sisimai/lhost'
8
9
  Boundaries = ['Content-Type: message/rfc822'].freeze
9
10
 
@@ -73,7 +74,7 @@ module Sisimai::Lhost
73
74
  return nil if recipients == 0
74
75
 
75
76
  dscontents.each do |e|
76
- e['reason'] = 'userunknown' if e['diagnosis'].include?('Unable to deliver')
77
+ e['reason'] = Sisimai::Eb::ReUSER if e['diagnosis'].include?('Unable to deliver')
77
78
  end
78
79
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
79
80
  end
@@ -41,6 +41,7 @@ module Sisimai::Lhost
41
41
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
42
42
  return nil if emailparts[1].size == 0
43
43
 
44
+ require 'sisimai/eb'
44
45
  require 'sisimai/rfc1123'
45
46
  require 'sisimai/smtp/command'
46
47
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
@@ -84,7 +85,7 @@ module Sisimai::Lhost
84
85
  next
85
86
  end
86
87
 
87
- if cv == v["recipient"] || (curcommand == "MAIL" && e.start_with?("<<< "))
88
+ if cv == v["recipient"] || (curcommand == Sisimai::Eb::CeMAIL && e.start_with?("<<< "))
88
89
  # The recipient address is the same address with the last appeared address
89
90
  # like "550 <mikeneko@example.co.jp>... User unknown"
90
91
  # Append this line to the string which is keeping error messages
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Verizon
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  Indicators = Sisimai::Lhost.INDICATORS
8
9
 
@@ -37,7 +38,7 @@ module Sisimai::Lhost
37
38
  markingsof = {message: ['Error: ']}
38
39
  messagesof = {
39
40
  # The attempted recipient address does not exist.
40
- 'userunknown' => ['550 - Requested action not taken: no such user here'],
41
+ Sisimai::Eb::ReUSER => ['550 - Requested action not taken: no such user here'],
41
42
  }
42
43
  boundaries = [Sisimai::RFC2045.boundary(mhead['content-type'], 1)]
43
44
  emailparts = Sisimai::RFC5322.part(mbody, boundaries)
@@ -85,7 +86,7 @@ module Sisimai::Lhost
85
86
  else
86
87
  # vzwpix.com
87
88
  startingof = {message: ['Message could not be delivered to mobile']}
88
- messagesof = {'userunknown' => ['No valid recipients for this MM']}
89
+ messagesof = {Sisimai::Eb::ReUSER => ['No valid recipients for this MM']}
89
90
  boundaries = [Sisimai::RFC2045.boundary(mhead['content-type'], 1)]
90
91
  emailparts = Sisimai::RFC5322.part(mbody, boundaries)
91
92
  bodyslices = emailparts[0].split("\n")
@@ -1,6 +1,6 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::AuthFailure checks the bounce reason is "authfailure" or not. This class is
3
+ # Sisimai::Reason::AuthFailure checks the bounce reason is "AuthFailure" or not. This class is
4
4
  # called only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that an authenticaion failure related to SPF, DKIM, or DMARC was detected
@@ -12,6 +12,7 @@ module Sisimai
12
12
  # Diagnostic-Code: smtp; 550 5.7.1 Email rejected per DMARC policy for example.org
13
13
  module AuthFailure
14
14
  class << self
15
+ require 'sisimai/eb'
15
16
  Index = [
16
17
  "//spf.pobox.com",
17
18
  "5322.From address doesn't meet the authentication requirements",
@@ -27,7 +28,7 @@ module Sisimai
27
28
  ["is not allowed to send ", " spf "],
28
29
  ].freeze
29
30
 
30
- def text; return 'authfailure'; end
31
+ def text; return Sisimai::Eb::ReAUTH; end
31
32
  def description; return 'Email rejected due to SPF, DKIM, DMARC failure'; end
32
33
 
33
34
  # Try to match that the given text and regular expressions
@@ -40,14 +41,14 @@ module Sisimai
40
41
  return false
41
42
  end
42
43
 
43
- # The bounce reason is "authfailure" or not
44
+ # The bounce reason is "AuthFailure" or not
44
45
  # @param [Sisimai::Fact] argvs Object to be detected the reason
45
46
  # @return [Boolean] true: is AuthFailure, false: is not AuthFailure
46
47
  # @see http://www.ietf.org/rfc/rfc2822.txt
47
48
  def true(argvs)
48
49
  return false if argvs['deliverystatus'].empty?
49
- return true if argvs['reason'] == 'authfailure'
50
- return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'authfailure'
50
+ return true if argvs['reason'] == Sisimai::Eb::ReAUTH
51
+ return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReAUTH
51
52
  return match(argvs['diagnosticcode'].downcase)
52
53
  end
53
54
 
@@ -1,6 +1,6 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::BadReputation checks the bounce reason is "badreputation" or not. This class
3
+ # Sisimai::Reason::BadReputation checks the bounce reason is "BadReputation" or not. This class
4
4
  # is called only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that an email rejected due to a reputation score of the sender IP address.
@@ -14,6 +14,7 @@ module Sisimai
14
14
  # visit https://support.google.com/mail/answer/188131 for more information.
15
15
  module BadReputation
16
16
  class << self
17
+ require 'sisimai/eb'
17
18
  Index = [
18
19
  "has been temporarily rate limited due to ip reputation",
19
20
  "ip/domain reputation problems",
@@ -23,7 +24,7 @@ module Sisimai
23
24
  "sending mta's poor reputation",
24
25
  "temporarily deferred due to unexpected volume or user complaints", # Yahoo Inc.
25
26
  ].freeze
26
- def text; return 'badreputation'; end
27
+ def text; return Sisimai::Eb::ReFAMA; end
27
28
  def description; return 'Email rejected due to an IP address reputation'; end
28
29
 
29
30
  # Try to match that the given text and regular expressions
@@ -35,12 +36,12 @@ module Sisimai
35
36
  return false
36
37
  end
37
38
 
38
- # The bounce reason is "badreputation" or not
39
+ # The bounce reason is "BadReputation" or not
39
40
  # @param [Sisimai::Fact] argvs Object to be detected the reason
40
41
  # @return [Boolean] true: is BadReputation, false: is not BadReputation
41
42
  # @see http://www.ietf.org/rfc/rfc2822.txt
42
43
  def true(argvs)
43
- return true if argvs['reason'] == 'badreputation'
44
+ return true if argvs['reason'] == Sisimai::Eb::ReFAMA
44
45
  return match(argvs['diagnosticcode'].downcase)
45
46
  end
46
47
 
@@ -1,12 +1,13 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::Blocked checks the bounce reason is "blocked" or not. This class is called
3
+ # Sisimai::Reason::Blocked checks the bounce reason is "Blocked" or not. This class is called
4
4
  # only Sisimai::Reason class.
5
5
  #
6
6
  # This is the error that SMTP connection was rejected due to a client IP address or a hostname,
7
7
  # or the parameter of "HELO/EHLO" command. This reason has added in Sisimai 4.0.0.
8
8
  module Blocked
9
9
  class << self
10
+ require 'sisimai/eb'
10
11
  Index = [
11
12
  "bad sender ip address",
12
13
  "banned sending ip", # Office365
@@ -70,7 +71,7 @@ module Sisimai
70
71
  ["your sender's ip address is listed at ", ".abuseat.org"],
71
72
  ].freeze
72
73
 
73
- def text; return 'blocked'; end
74
+ def text; return Sisimai::Eb::ReBLOC; end
74
75
  def description; return 'Email rejected due to client IP address or a hostname'; end
75
76
 
76
77
  # Try to match that the given text and regular expressions
@@ -85,11 +86,11 @@ module Sisimai
85
86
 
86
87
  # Blocked due to client IP address or hostname
87
88
  # @param [Hash] argvs Hash to be detected the value of reason
88
- # @return [Boolean] true: is blocked, false: is not blocked by the client
89
+ # @return [Boolean] true: is Blocked, false: is not Blocked by the client
89
90
  # @see http://www.ietf.org/rfc/rfc2822.txt
90
91
  def true(argvs)
91
- return true if argvs['reason'] == 'blocked'
92
- return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'blocked'
92
+ return true if argvs['reason'] == Sisimai::Eb::ReBLOC
93
+ return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReBLOC
93
94
  return match(argvs['diagnosticcode'].downcase)
94
95
  end
95
96
 
@@ -1,13 +1,14 @@
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 = [
12
13
  "charset not supported",
13
14
  "executable files are not allowed in compressed files",
@@ -27,7 +28,7 @@ module Sisimai
27
28
  "we do not accept messages containing images or other attachments",
28
29
  ].freeze
29
30
 
30
- def text; return 'contenterror'; end
31
+ def text; return Sisimai::Eb::ReBODY; end
31
32
  def description; return 'Email rejected due to a header format of the email'; end
32
33
 
33
34
  # Try to match that the given text and regular expressions
@@ -46,9 +47,9 @@ module Sisimai
46
47
  # @see http://www.ietf.org/rfc/rfc2822.txt
47
48
  def true(argvs)
48
49
  require 'sisimai/reason/spamdetected'
49
- return true if argvs["reason"] == "blocked"
50
+ return true if argvs["reason"] == Sisimai::Eb::ReBLOC
50
51
  return false if Sisimai::Reason::SpamDetected.true(argvs)
51
- return true if Sisimai::SMTP::Status.name(argvs["deliverystatus"]) == "contenterror"
52
+ return true if Sisimai::SMTP::Status.name(argvs["deliverystatus"]) == Sisimai::Eb::ReBODY
52
53
  return match(argvs["diagnosticcode"].downcase)
53
54
  end
54
55