sisimai 4.25.15-java → 5.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +3 -3
  3. data/ANALYTICAL-PRECISION +2 -2
  4. data/Benchmarks.mk +3 -3
  5. data/CONTRIBUTING +1 -1
  6. data/ChangeLog.md +419 -388
  7. data/Developers.mk +5 -6
  8. data/Gemfile +1 -1
  9. data/Makefile +15 -15
  10. data/README-JA.md +140 -78
  11. data/README.md +290 -143
  12. data/Rakefile +9 -3
  13. data/Repository.mk +2 -3
  14. data/lib/sisimai/address.rb +118 -74
  15. data/lib/sisimai/arf.rb +84 -82
  16. data/lib/sisimai/datetime.rb +5 -52
  17. data/lib/sisimai/{data → fact}/json.rb +7 -9
  18. data/lib/sisimai/fact/yaml.rb +31 -0
  19. data/lib/sisimai/fact.rb +468 -0
  20. data/lib/sisimai/lhost/activehunter.rb +12 -14
  21. data/lib/sisimai/lhost/amavis.rb +11 -14
  22. data/lib/sisimai/lhost/amazonses.rb +37 -41
  23. data/lib/sisimai/lhost/amazonworkmail.rb +15 -18
  24. data/lib/sisimai/lhost/aol.rb +12 -14
  25. data/lib/sisimai/lhost/apachejames.rb +19 -21
  26. data/lib/sisimai/lhost/barracuda.rb +10 -12
  27. data/lib/sisimai/lhost/bigfoot.rb +21 -21
  28. data/lib/sisimai/lhost/biglobe.rb +15 -16
  29. data/lib/sisimai/lhost/courier.rb +20 -20
  30. data/lib/sisimai/lhost/domino.rb +23 -19
  31. data/lib/sisimai/lhost/einsundeins.rb +23 -18
  32. data/lib/sisimai/lhost/exchange2003.rb +30 -29
  33. data/lib/sisimai/lhost/exchange2007.rb +70 -58
  34. data/lib/sisimai/lhost/exim.rb +175 -161
  35. data/lib/sisimai/lhost/ezweb.rb +31 -56
  36. data/lib/sisimai/lhost/facebook.rb +21 -33
  37. data/lib/sisimai/lhost/fml.rb +43 -48
  38. data/lib/sisimai/lhost/gmail.rb +29 -29
  39. data/lib/sisimai/lhost/gmx.rb +18 -17
  40. data/lib/sisimai/lhost/googlegroups.rb +9 -10
  41. data/lib/sisimai/lhost/gsuite.rb +21 -27
  42. data/lib/sisimai/lhost/imailserver.rb +25 -39
  43. data/lib/sisimai/lhost/interscanmss.rb +28 -31
  44. data/lib/sisimai/lhost/kddi.rb +22 -28
  45. data/lib/sisimai/lhost/mailfoundry.rb +11 -12
  46. data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
  47. data/lib/sisimai/lhost/mailru.rb +33 -27
  48. data/lib/sisimai/lhost/mcafee.rb +21 -31
  49. data/lib/sisimai/lhost/messagelabs.rb +17 -20
  50. data/lib/sisimai/lhost/messagingserver.rb +40 -37
  51. data/lib/sisimai/lhost/mfilter.rb +15 -16
  52. data/lib/sisimai/lhost/mxlogic.rb +24 -23
  53. data/lib/sisimai/lhost/notes.rb +17 -17
  54. data/lib/sisimai/lhost/office365.rb +63 -27
  55. data/lib/sisimai/lhost/opensmtpd.rb +12 -13
  56. data/lib/sisimai/lhost/outlook.rb +12 -15
  57. data/lib/sisimai/lhost/postfix.rb +179 -129
  58. data/lib/sisimai/lhost/powermta.rb +12 -14
  59. data/lib/sisimai/lhost/qmail.rb +44 -47
  60. data/lib/sisimai/lhost/receivingses.rb +15 -20
  61. data/lib/sisimai/lhost/sendgrid.rb +34 -32
  62. data/lib/sisimai/lhost/sendmail.rb +66 -53
  63. data/lib/sisimai/lhost/surfcontrol.rb +19 -19
  64. data/lib/sisimai/lhost/v5sendmail.rb +45 -39
  65. data/lib/sisimai/lhost/verizon.rb +35 -39
  66. data/lib/sisimai/lhost/x1.rb +18 -17
  67. data/lib/sisimai/lhost/x2.rb +17 -14
  68. data/lib/sisimai/lhost/x3.rb +19 -19
  69. data/lib/sisimai/lhost/x4.rb +72 -57
  70. data/lib/sisimai/lhost/x5.rb +17 -19
  71. data/lib/sisimai/lhost/x6.rb +41 -17
  72. data/lib/sisimai/lhost/yahoo.rb +17 -16
  73. data/lib/sisimai/lhost/yandex.rb +16 -20
  74. data/lib/sisimai/lhost/zoho.rb +16 -15
  75. data/lib/sisimai/lhost.rb +8 -10
  76. data/lib/sisimai/mail/maildir.rb +1 -3
  77. data/lib/sisimai/mail/mbox.rb +3 -4
  78. data/lib/sisimai/mail/memory.rb +0 -1
  79. data/lib/sisimai/mail/stdin.rb +1 -3
  80. data/lib/sisimai/mail.rb +3 -7
  81. data/lib/sisimai/mda.rb +28 -42
  82. data/lib/sisimai/message.rb +435 -313
  83. data/lib/sisimai/order.rb +5 -5
  84. data/lib/sisimai/reason/authfailure.rb +64 -0
  85. data/lib/sisimai/reason/badreputation.rb +53 -0
  86. data/lib/sisimai/reason/blocked.rb +94 -160
  87. data/lib/sisimai/reason/contenterror.rb +8 -9
  88. data/lib/sisimai/reason/delivered.rb +4 -6
  89. data/lib/sisimai/reason/exceedlimit.rb +10 -12
  90. data/lib/sisimai/reason/expired.rb +6 -8
  91. data/lib/sisimai/reason/feedback.rb +2 -3
  92. data/lib/sisimai/reason/filtered.rb +17 -19
  93. data/lib/sisimai/reason/hasmoved.rb +9 -10
  94. data/lib/sisimai/reason/hostunknown.rb +15 -15
  95. data/lib/sisimai/reason/mailboxfull.rb +10 -12
  96. data/lib/sisimai/reason/mailererror.rb +18 -20
  97. data/lib/sisimai/reason/mesgtoobig.rb +9 -11
  98. data/lib/sisimai/reason/networkerror.rb +5 -8
  99. data/lib/sisimai/reason/norelaying.rb +8 -11
  100. data/lib/sisimai/reason/notaccept.rb +13 -14
  101. data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
  102. data/lib/sisimai/reason/onhold.rb +6 -9
  103. data/lib/sisimai/reason/policyviolation.rb +14 -12
  104. data/lib/sisimai/reason/rejected.rb +26 -24
  105. data/lib/sisimai/reason/requireptr.rb +69 -0
  106. data/lib/sisimai/reason/securityerror.rb +33 -36
  107. data/lib/sisimai/reason/spamdetected.rb +114 -147
  108. data/lib/sisimai/reason/speeding.rb +49 -0
  109. data/lib/sisimai/reason/suspend.rb +11 -11
  110. data/lib/sisimai/reason/syntaxerror.rb +11 -10
  111. data/lib/sisimai/reason/systemerror.rb +7 -9
  112. data/lib/sisimai/reason/systemfull.rb +7 -8
  113. data/lib/sisimai/reason/toomanyconn.rb +9 -11
  114. data/lib/sisimai/reason/undefined.rb +2 -3
  115. data/lib/sisimai/reason/userunknown.rb +129 -146
  116. data/lib/sisimai/reason/vacation.rb +3 -4
  117. data/lib/sisimai/reason/virusdetected.rb +10 -11
  118. data/lib/sisimai/reason.rb +59 -64
  119. data/lib/sisimai/rfc1894.rb +55 -28
  120. data/lib/sisimai/rfc2045.rb +373 -0
  121. data/lib/sisimai/rfc3464.rb +250 -308
  122. data/lib/sisimai/rfc3834.rb +42 -47
  123. data/lib/sisimai/rfc5322.rb +75 -100
  124. data/lib/sisimai/rfc5965.rb +31 -0
  125. data/lib/sisimai/rhost/cox.rb +5 -6
  126. data/lib/sisimai/rhost/franceptt.rb +6 -8
  127. data/lib/sisimai/rhost/godaddy.rb +12 -12
  128. data/lib/sisimai/rhost/{googleapps.rb → google.rb} +80 -72
  129. data/lib/sisimai/rhost/iua.rb +9 -10
  130. data/lib/sisimai/rhost/kddi.rb +6 -8
  131. data/lib/sisimai/rhost/{exchangeonline.rb → microsoft.rb} +115 -114
  132. data/lib/sisimai/rhost/mimecast.rb +42 -40
  133. data/lib/sisimai/rhost/nttdocomo.rb +12 -12
  134. data/lib/sisimai/rhost/spectrum.rb +10 -12
  135. data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
  136. data/lib/sisimai/rhost.rb +23 -31
  137. data/lib/sisimai/smtp/command.rb +59 -0
  138. data/lib/sisimai/smtp/error.rb +4 -7
  139. data/lib/sisimai/smtp/reply.rb +161 -74
  140. data/lib/sisimai/smtp/status.rb +504 -393
  141. data/lib/sisimai/smtp/transcript.rb +124 -0
  142. data/lib/sisimai/smtp.rb +0 -1
  143. data/lib/sisimai/string.rb +74 -5
  144. data/lib/sisimai/time.rb +1 -2
  145. data/lib/sisimai/version.rb +1 -1
  146. data/lib/sisimai.rb +35 -21
  147. data/set-of-emails/maildir/bsd/lhost-domino-02.eml +6 -3
  148. data/set-of-emails/maildir/bsd/lhost-googlegroups-15.eml +174 -0
  149. data/set-of-emails/maildir/bsd/lhost-gsuite-15.eml +229 -0
  150. data/set-of-emails/maildir/bsd/lhost-postfix-75.eml +51 -0
  151. data/set-of-emails/maildir/bsd/lhost-postfix-76.eml +101 -0
  152. data/set-of-emails/maildir/bsd/lhost-postfix-77.eml +74 -0
  153. data/set-of-emails/maildir/bsd/lhost-postfix-78.eml +91 -0
  154. data/set-of-emails/maildir/bsd/lhost-receivingses-08.eml +88 -0
  155. data/set-of-emails/maildir/bsd/rfc3464-43.eml +88 -0
  156. data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
  157. data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
  158. data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
  159. data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
  160. data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
  161. data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
  162. data/sisimai-java.gemspec +1 -1
  163. data/sisimai.gemspec +1 -1
  164. metadata +42 -22
  165. data/.rspec +0 -2
  166. data/lib/sisimai/data/yaml.rb +0 -33
  167. data/lib/sisimai/data.rb +0 -411
  168. data/lib/sisimai/mime.rb +0 -456
  169. /data/set-of-emails/maildir/bsd/{rfc3464-41.eml → rfc3834-05.eml} +0 -0
  170. /data/set-of-emails/maildir/bsd/{rhost-googleapps-01.eml → rhost-google-01.eml} +0 -0
  171. /data/set-of-emails/maildir/bsd/{rhost-googleapps-02.eml → rhost-google-02.eml} +0 -0
  172. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-01.eml → rhost-microsoft-01.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-02.eml → rhost-microsoft-02.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-03.eml → rhost-microsoft-03.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-01.eml → rhost-tencent-01.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-02.eml → rhost-tencent-02.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-03.eml → rhost-tencent-03.eml} +0 -0
@@ -1,11 +1,10 @@
1
1
  module Sisimai
2
2
  module Reason
3
- # Sisimai::Reason::VirusDetected checks the bounce reason is "virusdetected"
4
- # or not. This class is called only Sisimai::Reason class.
3
+ # Sisimai::Reason::VirusDetected checks the bounce reason is "virusdetected" or not. This class
4
+ # is called only Sisimai::Reason class.
5
5
  #
6
- # This is an error that any virus or trojan horse detected in the message by
7
- # a virus scanner program at a destination mail server. This reason has been
8
- # divided from "securityerror" at Sisimai 4.22.0.
6
+ # This is an error that any virus or trojan horse detected in the message by a virus scanner program
7
+ # at a destination mail server. This reason has been divided from "securityerror" at Sisimai 4.22.0.
9
8
  #
10
9
  # Your message was infected with a virus. You should download a virus
11
10
  # scanner and check your computer for viruses.
@@ -14,15 +13,15 @@ module Sisimai
14
13
  # Recipient: <kijitora@example.jp>
15
14
  #
16
15
  module VirusDetected
17
- # Imported from p5-Sisimail/lib/Sisimai/Reason/VirusDetected.pm
18
16
  class << self
19
17
  Index = [
20
18
  'it has a potentially executable attachment',
21
19
  'the message was rejected because it contains prohibited virus or spam content',
22
20
  'this form of attachment has been used by recent viruses or other malware',
23
21
  'virus detected',
22
+ 'virus phishing/malicious_url detected',
24
23
  'your message was infected with a virus',
25
- ]
24
+ ].freeze
26
25
 
27
26
  def text; return 'virusdetected'; end
28
27
  def description; return 'Email rejected due to a virus scanner on a destination host'; end
@@ -39,7 +38,7 @@ module Sisimai
39
38
  end
40
39
 
41
40
  # The bounce reason is "virusdetected" or not
42
- # @param [Sisimai::Data] argvs Object to be detected the reason
41
+ # @param [Sisimai::Fact] argvs Object to be detected the reason
43
42
  # @return [True,False] true: virus detected
44
43
  # false: virus was not detected
45
44
  # @since 4.22.0
@@ -48,9 +47,9 @@ module Sisimai
48
47
  # The value of "reason" isn't "visusdetected" when the value of "smtpcommand" is an SMTP
49
48
  # command to be sent before the SMTP DATA command because all the MTAs read the headers
50
49
  # and the entire message body after the DATA command.
51
- return true if argvs.reason == 'virusdetected'
52
- return false if %w[CONN EHLO HELO MAIL RCPT].include?(argvs.smtpcommand)
53
- return true if match(argvs.diagnosticcode.downcase)
50
+ return true if argvs['reason'] == 'virusdetected'
51
+ return false if %w[CONN EHLO HELO MAIL RCPT].include?(argvs['smtpcommand'])
52
+ return true if match(argvs['diagnosticcode'].downcase)
54
53
  return false
55
54
  end
56
55
 
@@ -1,18 +1,16 @@
1
1
  module Sisimai
2
- # Sisimai::Reason detects the bounce reason from the content of Sisimai::Data
3
- # object as an argument of get() method. This class is called only Sisimai::Data
4
- # class.
2
+ # Sisimai::Reason detects the bounce reason from the Hash table which is to be constructed to
3
+ # Sisimai::Fact object as an argument of get() method. This class is called only Sisimai::Fact class.
5
4
  module Reason
6
- # Imported from p5-Sisimail/lib/Sisimai/Reason.pm
7
5
  class << self
8
6
  # All the error reason list Sisimai support
9
7
  # @return [Array] Reason list
10
8
  def index
11
9
  return %w[
12
- Blocked ContentError ExceedLimit Expired Filtered HasMoved HostUnknown
13
- MailboxFull MailerError MesgTooBig NetworkError NotAccept OnHold
14
- Rejected NoRelaying SpamDetected VirusDetected PolicyViolation SecurityError
15
- Suspend SystemError SystemFull TooManyConn UserUnknown SyntaxError
10
+ AuthFailure BadReputation Blocked ContentError ExceedLimit Expired Filtered HasMoved
11
+ HostUnknown MailboxFull MailerError MesgTooBig NetworkError NotAccept NotCompliantRFC
12
+ OnHold Rejected NoRelaying Speeding SpamDetected VirusDetected PolicyViolation
13
+ SecurityError Suspend RequirePTR SystemError SystemFull TooManyConn UserUnknown SyntaxError
16
14
  ]
17
15
  end
18
16
 
@@ -27,55 +25,57 @@ module Sisimai
27
25
  end
28
26
 
29
27
  # Reason list better to retry detecting an error reason
30
- # @return [Array] Reason list
28
+ # @return [Hash] Reason list
31
29
  def retry
32
30
  return {
33
- 'undefined' => 1, 'onhold' => 1, 'systemerror' => 1, 'securityerror' => 1,
34
- 'networkerror' => 1, 'hostunknown' => 1, 'userunknown' => 1
31
+ 'undefined' => true, 'onhold' => true, 'systemerror' => true, 'securityerror' => true,
32
+ 'expired' => true, 'suspend' => true, 'networkerror' => true, 'hostunknown' => true,
33
+ 'userunknown' => true
35
34
  }.freeze
36
35
  end
37
36
  ModulePath = Sisimai::Reason.path
38
37
  GetRetried = Sisimai::Reason.retry
39
38
  ClassOrder = [
40
39
  %w[
41
- MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying UserUnknown
42
- Filtered Rejected HostUnknown SpamDetected TooManyConn Blocked
40
+ MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying AuthFailure UserUnknown
41
+ Filtered RequirePTR NotCompliantRFC Rejected HostUnknown SpamDetected Speeding TooManyConn
42
+ Blocked
43
43
  ],
44
44
  %w[
45
- MailboxFull SpamDetected PolicyViolation VirusDetected NoRelaying
46
- SecurityError SystemError NetworkError Suspend Expired ContentError
45
+ MailboxFull SpamDetected PolicyViolation VirusDetected NoRelaying AuthFailure
46
+ BadReputation SecurityError SystemError NetworkError Speeding Suspend Expired ContentError
47
47
  SystemFull NotAccept MailerError
48
48
  ],
49
49
  %w[
50
- MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected
51
- HostUnknown SpamDetected TooManyConn Blocked SpamDetected SecurityError
52
- SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull
53
- NotAccept MailerError NoRelaying SyntaxError OnHold
50
+ MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected HostUnknown
51
+ SpamDetected Speeding TooManyConn Blocked SpamDetected AuthFailure SecurityError
52
+ SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull NotAccept
53
+ MailerError NoRelaying SyntaxError OnHold
54
54
  ]
55
55
  ]
56
56
 
57
57
  # Detect the bounce reason
58
- # @param [Sisimai::Data] argvs Parsed email object
59
- # @return [String, Nil] Bounce reason or Nil if the argument
60
- # is missing or invalid object
58
+ # @param [Hash] argvs Parsed email object
59
+ # @return [String, nil] Bounce reason or nil if the argument is missing or not Hash
61
60
  # @see anotherone
62
61
  def get(argvs)
63
62
  return nil unless argvs
64
- return nil unless argvs.is_a? Sisimai::Data
65
-
66
- unless GetRetried[argvs.reason]
67
- # Return reason text already decided except reason match with the
68
- # regular expression of retry() method.
69
- return argvs.reason unless argvs.reason.empty?
63
+ unless GetRetried[argvs['reason']]
64
+ # Return reason text already decided except reason match with the regular expression of
65
+ # retry() method.
66
+ return argvs['reason'] unless argvs['reason'].empty?
70
67
  end
71
- return 'delivered' if argvs.deliverystatus.start_with?('2.')
68
+ return 'delivered' if argvs['deliverystatus'].start_with?('2.')
72
69
 
73
70
  reasontext = ''
74
- if argvs.diagnostictype == 'SMTP' || argvs.diagnostictype == ''
71
+ issuedcode = argvs['diagnosticcode'] || ''
72
+ codeformat = argvs['diagnostictype'] || ''
73
+
74
+ if codeformat == 'SMTP' || codeformat == ''
75
75
  # Diagnostic-Code: SMTP; ... or empty value
76
76
  ClassOrder[0].each do |e|
77
- # Check the value of Diagnostic-Code: and the value of Status:, it is a
78
- # deliverystats, with true() method in each Sisimai::Reason::* class.
77
+ # Check the value of Diagnostic-Code: and the value of Status:, it is a deliverystats,
78
+ # with true() method in each Sisimai::Reason::* class.
79
79
  p = 'Sisimai::Reason::' << e
80
80
  r = nil
81
81
  begin
@@ -98,13 +98,13 @@ module Sisimai
98
98
  if reasontext == 'undefined' || reasontext.empty?
99
99
  # Action: delayed => "expired"
100
100
  reasontext = nil
101
- reasontext ||= 'expired' if argvs.action == 'delayed'
101
+ reasontext ||= 'expired' if argvs['action'] == 'delayed'
102
102
  return reasontext if reasontext
103
103
 
104
104
  # Try to match with message patterns in Sisimai::Reason::Vacation
105
105
  require 'sisimai/reason/vacation'
106
- reasontext = 'vacation' if Sisimai::Reason::Vacation.match(argvs.diagnosticcode.downcase)
107
- reasontext ||= 'onhold' unless argvs.diagnosticcode.empty?
106
+ reasontext = 'vacation' if Sisimai::Reason::Vacation.match(issuedcode.downcase)
107
+ reasontext ||= 'onhold' unless issuedcode.empty?
108
108
  reasontext ||= 'undefined'
109
109
  end
110
110
  end
@@ -112,24 +112,24 @@ module Sisimai
112
112
  end
113
113
 
114
114
  # Detect the other bounce reason, fall back method for get()
115
- # @param [Sisimai::Data] argvs Parsed email object
116
- # @return [String, Nil] Bounce reason or nli if the argument
117
- # is missing or invalid object
115
+ # @param [Hash] argvs Parsed email object
116
+ # @return [String, Nil] Bounce reason or nli if the argument is missing or not Hash
118
117
  # @see get
119
118
  def anotherone(argvs)
120
- return nil unless argvs.is_a? Sisimai::Data
121
- return argvs.reason unless argvs.reason.empty?
119
+ return argvs['reason'] unless argvs['reason'].empty?
122
120
 
123
121
  require 'sisimai/smtp/status'
124
- statuscode = argvs.deliverystatus || ''
122
+ issuedcode = argvs['diagnosticcode'].downcase || ''
123
+ codeformat = argvs['diagnostictype'] || ''
124
+ actiontext = argvs['action'] || ''
125
+ statuscode = argvs['deliverystatus'] || ''
125
126
  reasontext = Sisimai::SMTP::Status.name(statuscode) || ''
126
127
 
127
128
  catch :TRY_TO_MATCH do
128
129
  while true
129
- diagnostic = argvs.diagnosticcode.downcase || ''
130
130
  trytomatch = reasontext.empty? ? true : false
131
131
  trytomatch ||= true if GetRetried[reasontext]
132
- trytomatch ||= true if argvs.diagnostictype != 'SMTP'
132
+ trytomatch ||= true if codeformat != 'SMTP'
133
133
  throw :TRY_TO_MATCH unless trytomatch
134
134
 
135
135
  # Could not decide the reason by the value of Status:
@@ -145,25 +145,26 @@ module Sisimai
145
145
  next
146
146
  end
147
147
 
148
- next unless r.match(diagnostic)
148
+ next unless r.match(issuedcode)
149
149
  reasontext = e.downcase
150
150
  break
151
151
  end
152
152
  throw :TRY_TO_MATCH unless reasontext.empty?
153
153
 
154
154
  # Check the value of Status:
155
- v = statuscode[0, 3]
156
- if v == '5.6' || v == '4.6'
155
+ code2digit = statuscode[0, 3] || ''
156
+ if code2digit == '5.6' || code2digit == '4.6'
157
157
  # X.6.0 Other or undefined media error
158
158
  reasontext = 'contenterror'
159
159
 
160
- elsif v == '5.7' || v == '4.7'
160
+ elsif code2digit == '5.7' || code2digit == '4.7'
161
161
  # X.7.0 Other or undefined security status
162
162
  reasontext = 'securityerror'
163
163
 
164
- elsif %w[X-UNIX X-POSTFIX].include?(argvs.diagnostictype)
164
+ elsif codeformat.start_with?('X-UNIX')
165
165
  # Diagnostic-Code: X-UNIX; ...
166
166
  reasontext = 'mailererror'
167
+
167
168
  else
168
169
  # 50X Syntax Error?
169
170
  require 'sisimai/reason/syntaxerror'
@@ -172,13 +173,13 @@ module Sisimai
172
173
  throw :TRY_TO_MATCH unless reasontext.empty?
173
174
 
174
175
  # Check the value of Action: field, first
175
- if argvs.action.start_with?('delayed', 'expired')
176
+ if actiontext.start_with?('delayed', 'expired')
176
177
  # Action: delayed, expired
177
178
  reasontext = 'expired'
178
179
  else
179
180
  # Rejected at connection or after EHLO|HELO
180
- commandtxt = argvs.smtpcommand || ''
181
- reasontext = 'blocked' if %w[HELO EHLO].index(commandtxt)
181
+ thecommand = argvs['smtpcommand'] || ''
182
+ reasontext = 'blocked' if %w[HELO EHLO].index(thecommand)
182
183
  end
183
184
  throw :TRY_TO_MATCH
184
185
  end
@@ -193,12 +194,12 @@ module Sisimai
193
194
  return nil unless argv1
194
195
 
195
196
  reasontext = ''
196
- diagnostic = argv1.downcase
197
+ issuedcode = argv1.downcase
197
198
 
198
199
  # Diagnostic-Code: SMTP; ... or empty value
199
200
  ClassOrder[2].each do |e|
200
- # Check the value of Diagnostic-Code: and the value of Status:, it is a
201
- # deliverystats, with true() method in each Sisimai::Reason::* class.
201
+ # Check the value of Diagnostic-Code: and the value of Status:, it is a deliverystats, with
202
+ # true() method in each Sisimai::Reason::* class.
202
203
  p = 'Sisimai::Reason::' << e
203
204
  r = nil
204
205
  begin
@@ -209,26 +210,20 @@ module Sisimai
209
210
  next
210
211
  end
211
212
 
212
- next unless r.match(diagnostic)
213
+ next unless r.match(issuedcode)
213
214
  reasontext = r.text
214
215
  break
215
216
  end
216
217
  return reasontext unless reasontext.empty?
217
218
 
218
- typestring = ''
219
- if cv = argv1.match(/\A(SMTP|X-.+);/i)
220
- # Check the value of typestring
221
- typestring = cv[1].upcase
222
- end
223
-
224
- if typestring == 'X-UNIX'
219
+ if issuedcode.upcase == 'X-UNIX'
225
220
  # X-Unix; ...
226
221
  reasontext = 'mailererror'
227
222
  else
228
223
  # Detect the bounce reason from "Status:" code
229
224
  require 'sisimai/smtp/status'
230
- statuscode = Sisimai::SMTP::Status.find(argv1) || ''
231
- reasontext = Sisimai::SMTP::Status.name(statuscode) || 'undefined'
225
+ cv = Sisimai::SMTP::Status.find(argv1) || ''
226
+ reasontext = Sisimai::SMTP::Status.name(cv) || 'undefined'
232
227
  end
233
228
  return reasontext
234
229
  end
@@ -1,14 +1,13 @@
1
1
  module Sisimai
2
2
  # Sisimai::RFC1894 DSN field defined in RFC3464 (obsoletes RFC1894)
3
3
  module RFC1894
4
- # Imported from p5-Sisimail/lib/Sisimai/RFC1894.pm
5
4
  class << self
6
- FieldNames = [
5
+ FieldNames = {
7
6
  # https://tools.ietf.org/html/rfc3464#section-2.2
8
- # Some fields of a DSN apply to all of the delivery attempts described by
9
- # that DSN. At most, these fields may appear once in any DSN. These fields
10
- # are used to correlate the DSN with the original message transaction and
11
- # to provide additional information which may be useful to gateways.
7
+ # Some fields of a DSN apply to all of the delivery attempts described by that DSN. At
8
+ # most, these fields may appear once in any DSN. These fields are used to correlate the
9
+ # DSN with the original message transaction and to provide additional information which
10
+ # may be useful to gateways.
12
11
  #
13
12
  # The following fields (not defined in RFC 3464) are used in Sisimai
14
13
  # - X-Original-Message-ID: <....> (GSuite)
@@ -16,13 +15,16 @@ module Sisimai
16
15
  # The following fields are not used in Sisimai:
17
16
  # - Original-Envelope-Id
18
17
  # - DSN-Gateway
19
- %w[Reporting-MTA Received-From-MTA Arrival-Date X-Original-Message-ID],
18
+ 'arrival-date' => ':',
19
+ 'received-from-mta' => ';',
20
+ 'reporting-mta' => ';',
21
+ 'x-original-message-id' => '@',
20
22
 
21
23
  # https://tools.ietf.org/html/rfc3464#section-2.3
22
- # A DSN contains information about attempts to deliver a message to one or
23
- # more recipients. The delivery information for any particular recipient is
24
- # contained in a group of contiguous per-recipient fields.
25
- # Each group of per-recipient fields is preceded by a blank line.
24
+ # A DSN contains information about attempts to deliver a message to one or more recipi-
25
+ # ents. The delivery information for any particular recipient is contained in a group of
26
+ # contiguous per-recipient fields. Each group of per-recipient fields is preceded by a
27
+ # blank line.
26
28
  #
27
29
  # The following fields (not defined in RFC 3464) are used in Sisimai
28
30
  # - X-Actual-Recipient: RFC822; ....
@@ -30,18 +32,24 @@ module Sisimai
30
32
  # The following fields are not used in Sisimai:
31
33
  # - Will-Retry-Until
32
34
  # - Final-Log-ID
33
- %w[Original-Recipient Final-Recipient Action Status Remote-MTA
34
- Diagnostic-Code Last-Attempt-Date X-Actual-Recipient],
35
- ].freeze
35
+ 'action' => 'e',
36
+ 'diagnostic-code' => ';',
37
+ 'final-recipient' => ';',
38
+ 'last-attempt-date' => ':',
39
+ 'original-recipient' => ';',
40
+ 'remote-mta' => ';',
41
+ 'status' => '.',
42
+ 'x-actual-recipient' => ';',
43
+ }.freeze
36
44
 
37
45
  CapturesOn = {
38
- 'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ]*(.+?);[ ]*(.+)/,
39
- 'code' => %r/\A(Diagnostic-Code):[ ]*(.+?);[ ]*(.*)/,
40
- 'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ]*(.+)/,
41
- 'host' => %r/\A((?:Received-From|Remote|Reporting)-MTA):[ ]*(.+?);[ ]*(.+)/,
42
- 'list' => %r/\A(Action):[ ]*(delayed|deliverable|delivered|expanded|expired|failed|failure|relayed)/i,
43
- 'stat' => %r/\A(Status):[ ]*([245][.]\d+[.]\d+)/,
44
- 'text' => %r/\A(X-Original-Message-ID):[ ]*(.+)/,
46
+ 'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ](.+?);[ ]*(.+)/,
47
+ 'code' => %r/\A(Diagnostic-Code):[ ](.+?);[ ]*(.*)/,
48
+ 'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ](.+)/,
49
+ 'host' => %r/\A((?:Received-From|Remote|Reporting)-MTA):[ ](.+?);[ ]*(.+)/,
50
+ 'list' => %r/\A(Action):[ ](delayed|deliverable|delivered|expanded|expired|failed|failure|relayed)/i,
51
+ 'stat' => %r/\A(Status):[ ]([245][.]\d+[.]\d+)/,
52
+ 'text' => %r/\A(X-Original-Message-ID):[ ](.+)/,
45
53
  #'text' => %r/\A(Final-Log-ID|Original-Envelope-Id):[ ]*(.+)/,
46
54
  }.freeze
47
55
 
@@ -61,6 +69,13 @@ module Sisimai
61
69
  'x-original-message-id' => 'text',
62
70
  }.freeze
63
71
 
72
+ def FIELDINDEX
73
+ return %w[
74
+ Action Arrival-Date Diagnostic-Code Final-Recipient Last-Attempt-Date Original-Recipient
75
+ Received-From-MTA Remote-MTA Reporting-MTA Status X-Actual-Recipienet X-Original-Message-ID
76
+ ]
77
+ end
78
+
64
79
  # Table to be converted to key name defined in Sisimai::Lhost class
65
80
  # @param [Symbol] group RFC822 Header group name
66
81
  # @return [Array,Hash] RFC822 Header list
@@ -81,23 +96,35 @@ module Sisimai
81
96
  end
82
97
 
83
98
  # Check the argument matches with a field defined in RFC3464
84
- # @param [String] argv0 A line inlcuding field and value defined in RFC3464
85
- # @return [Integer] 0: did not matched, 1,2: matched
99
+ # @param [String] argv0 A line including field and value defined in RFC3464
100
+ # @return [Boolean] false: did not matched, true: matched
86
101
  # @since v4.25.0
87
102
  def match(argv0 = '')
103
+ label = Sisimai::RFC1894.label(argv0)
104
+
105
+ return false unless label
106
+ return false unless FieldNames.has_key?(label)
107
+ return false unless argv0.include?(FieldNames[label])
108
+ return true
109
+ end
110
+
111
+ # Returns a field name as a lqbel from the given string
112
+ # @param [String] argv0 A line including field and value defined in RFC3464
113
+ # @return [String] Field name as a label
114
+ # @since v4.25.15
115
+ def label(argv0 = '')
88
116
  return nil if argv0.empty?
89
- return 1 if FieldNames[0].any? { |a| argv0.start_with?(a) }
90
- return 2 if FieldNames[1].any? { |a| argv0.start_with?(a) }
91
- return nil
117
+ return argv0.split(':', 2).shift.downcase
92
118
  end
93
119
 
94
120
  # Check the argument is including field defined in RFC3464 and return values
95
- # @param [String] argv0 A line inlcuding field and value defined in RFC3464
121
+ # @param [String] argv0 A line including field and value defined in RFC3464
96
122
  # @return [Array] ['field-name', 'value-type', 'Value', 'field-group']
97
123
  # @since v4.25.0
98
124
  def field(argv0 = '')
99
125
  return nil if argv0.empty?
100
- group = FieldGroup[argv0.split(':',2).shift.downcase] || ''
126
+ label = Sisimai::RFC1894.label(argv0)
127
+ group = FieldGroup[label] || ''
101
128
 
102
129
  return nil if group.empty?
103
130
  return nil unless CapturesOn[group]