sisimai 4.25.16-java → 5.0.2-java

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 (180) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rake-test.yml +55 -0
  3. data/.travis.yml +3 -3
  4. data/ANALYTICAL-PRECISION +2 -2
  5. data/Benchmarks.mk +3 -3
  6. data/CONTRIBUTING +1 -1
  7. data/ChangeLog.md +451 -393
  8. data/Developers.mk +5 -6
  9. data/Gemfile +1 -1
  10. data/Makefile +15 -15
  11. data/README-JA.md +323 -149
  12. data/README.md +319 -149
  13. data/Rakefile +9 -3
  14. data/Repository.mk +2 -3
  15. data/lib/sisimai/address.rb +118 -74
  16. data/lib/sisimai/arf.rb +84 -82
  17. data/lib/sisimai/datetime.rb +5 -52
  18. data/lib/sisimai/{data → fact}/json.rb +7 -9
  19. data/lib/sisimai/fact/yaml.rb +31 -0
  20. data/lib/sisimai/fact.rb +506 -0
  21. data/lib/sisimai/lhost/activehunter.rb +12 -14
  22. data/lib/sisimai/lhost/amavis.rb +11 -14
  23. data/lib/sisimai/lhost/amazonses.rb +37 -42
  24. data/lib/sisimai/lhost/amazonworkmail.rb +15 -19
  25. data/lib/sisimai/lhost/aol.rb +12 -15
  26. data/lib/sisimai/lhost/apachejames.rb +19 -21
  27. data/lib/sisimai/lhost/barracuda.rb +10 -12
  28. data/lib/sisimai/lhost/bigfoot.rb +21 -22
  29. data/lib/sisimai/lhost/biglobe.rb +15 -16
  30. data/lib/sisimai/lhost/courier.rb +20 -20
  31. data/lib/sisimai/lhost/domino.rb +23 -20
  32. data/lib/sisimai/lhost/einsundeins.rb +23 -18
  33. data/lib/sisimai/lhost/exchange2003.rb +30 -29
  34. data/lib/sisimai/lhost/exchange2007.rb +70 -58
  35. data/lib/sisimai/lhost/exim.rb +179 -174
  36. data/lib/sisimai/lhost/ezweb.rb +31 -56
  37. data/lib/sisimai/lhost/facebook.rb +21 -34
  38. data/lib/sisimai/lhost/fml.rb +43 -48
  39. data/lib/sisimai/lhost/gmail.rb +29 -29
  40. data/lib/sisimai/lhost/gmx.rb +18 -17
  41. data/lib/sisimai/lhost/googlegroups.rb +11 -11
  42. data/lib/sisimai/lhost/gsuite.rb +21 -28
  43. data/lib/sisimai/lhost/imailserver.rb +25 -39
  44. data/lib/sisimai/lhost/interscanmss.rb +28 -31
  45. data/lib/sisimai/lhost/kddi.rb +22 -28
  46. data/lib/sisimai/lhost/mailfoundry.rb +11 -12
  47. data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
  48. data/lib/sisimai/lhost/mailru.rb +37 -40
  49. data/lib/sisimai/lhost/mcafee.rb +21 -31
  50. data/lib/sisimai/lhost/messagelabs.rb +17 -21
  51. data/lib/sisimai/lhost/messagingserver.rb +40 -37
  52. data/lib/sisimai/lhost/mfilter.rb +16 -17
  53. data/lib/sisimai/lhost/mxlogic.rb +24 -33
  54. data/lib/sisimai/lhost/notes.rb +17 -17
  55. data/lib/sisimai/lhost/office365.rb +64 -28
  56. data/lib/sisimai/lhost/opensmtpd.rb +12 -13
  57. data/lib/sisimai/lhost/outlook.rb +12 -16
  58. data/lib/sisimai/lhost/postfix.rb +179 -130
  59. data/lib/sisimai/lhost/powermta.rb +12 -14
  60. data/lib/sisimai/lhost/qmail.rb +44 -47
  61. data/lib/sisimai/lhost/receivingses.rb +15 -21
  62. data/lib/sisimai/lhost/sendgrid.rb +34 -34
  63. data/lib/sisimai/lhost/sendmail.rb +65 -53
  64. data/lib/sisimai/lhost/surfcontrol.rb +19 -19
  65. data/lib/sisimai/lhost/v5sendmail.rb +45 -39
  66. data/lib/sisimai/lhost/verizon.rb +35 -39
  67. data/lib/sisimai/lhost/x1.rb +18 -17
  68. data/lib/sisimai/lhost/x2.rb +17 -14
  69. data/lib/sisimai/lhost/x3.rb +19 -19
  70. data/lib/sisimai/lhost/x4.rb +72 -57
  71. data/lib/sisimai/lhost/x5.rb +17 -19
  72. data/lib/sisimai/lhost/x6.rb +41 -17
  73. data/lib/sisimai/lhost/yahoo.rb +17 -16
  74. data/lib/sisimai/lhost/yandex.rb +16 -21
  75. data/lib/sisimai/lhost/zoho.rb +16 -15
  76. data/lib/sisimai/lhost.rb +8 -10
  77. data/lib/sisimai/mail/maildir.rb +1 -3
  78. data/lib/sisimai/mail/mbox.rb +3 -4
  79. data/lib/sisimai/mail/memory.rb +0 -1
  80. data/lib/sisimai/mail/stdin.rb +1 -3
  81. data/lib/sisimai/mail.rb +3 -7
  82. data/lib/sisimai/mda.rb +28 -42
  83. data/lib/sisimai/message.rb +444 -326
  84. data/lib/sisimai/order.rb +5 -5
  85. data/lib/sisimai/reason/authfailure.rb +65 -0
  86. data/lib/sisimai/reason/badreputation.rb +53 -0
  87. data/lib/sisimai/reason/blocked.rb +96 -160
  88. data/lib/sisimai/reason/contenterror.rb +8 -9
  89. data/lib/sisimai/reason/delivered.rb +4 -6
  90. data/lib/sisimai/reason/exceedlimit.rb +10 -12
  91. data/lib/sisimai/reason/expired.rb +7 -8
  92. data/lib/sisimai/reason/feedback.rb +2 -3
  93. data/lib/sisimai/reason/filtered.rb +17 -19
  94. data/lib/sisimai/reason/hasmoved.rb +9 -10
  95. data/lib/sisimai/reason/hostunknown.rb +15 -15
  96. data/lib/sisimai/reason/mailboxfull.rb +11 -12
  97. data/lib/sisimai/reason/mailererror.rb +18 -20
  98. data/lib/sisimai/reason/mesgtoobig.rb +9 -11
  99. data/lib/sisimai/reason/networkerror.rb +5 -8
  100. data/lib/sisimai/reason/norelaying.rb +8 -11
  101. data/lib/sisimai/reason/notaccept.rb +13 -14
  102. data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
  103. data/lib/sisimai/reason/onhold.rb +6 -9
  104. data/lib/sisimai/reason/policyviolation.rb +14 -12
  105. data/lib/sisimai/reason/rejected.rb +26 -24
  106. data/lib/sisimai/reason/requireptr.rb +69 -0
  107. data/lib/sisimai/reason/securityerror.rb +34 -36
  108. data/lib/sisimai/reason/spamdetected.rb +115 -147
  109. data/lib/sisimai/reason/speeding.rb +49 -0
  110. data/lib/sisimai/reason/suspend.rb +12 -11
  111. data/lib/sisimai/reason/syntaxerror.rb +11 -10
  112. data/lib/sisimai/reason/systemerror.rb +7 -9
  113. data/lib/sisimai/reason/systemfull.rb +7 -8
  114. data/lib/sisimai/reason/toomanyconn.rb +9 -11
  115. data/lib/sisimai/reason/undefined.rb +2 -3
  116. data/lib/sisimai/reason/userunknown.rb +129 -146
  117. data/lib/sisimai/reason/vacation.rb +3 -4
  118. data/lib/sisimai/reason/virusdetected.rb +10 -11
  119. data/lib/sisimai/reason.rb +59 -64
  120. data/lib/sisimai/rfc1894.rb +55 -28
  121. data/lib/sisimai/rfc2045.rb +373 -0
  122. data/lib/sisimai/rfc3464.rb +250 -308
  123. data/lib/sisimai/rfc3834.rb +42 -45
  124. data/lib/sisimai/rfc5322.rb +177 -146
  125. data/lib/sisimai/rfc5965.rb +31 -0
  126. data/lib/sisimai/rhost/cox.rb +5 -6
  127. data/lib/sisimai/rhost/franceptt.rb +6 -8
  128. data/lib/sisimai/rhost/godaddy.rb +12 -12
  129. data/lib/sisimai/rhost/google.rb +530 -0
  130. data/lib/sisimai/rhost/iua.rb +9 -10
  131. data/lib/sisimai/rhost/kddi.rb +6 -8
  132. data/lib/sisimai/rhost/{exchangeonline.rb → microsoft.rb} +115 -114
  133. data/lib/sisimai/rhost/mimecast.rb +51 -42
  134. data/lib/sisimai/rhost/nttdocomo.rb +12 -12
  135. data/lib/sisimai/rhost/spectrum.rb +10 -12
  136. data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
  137. data/lib/sisimai/rhost.rb +23 -31
  138. data/lib/sisimai/smtp/command.rb +59 -0
  139. data/lib/sisimai/smtp/error.rb +4 -7
  140. data/lib/sisimai/smtp/reply.rb +161 -74
  141. data/lib/sisimai/smtp/status.rb +507 -393
  142. data/lib/sisimai/smtp/transcript.rb +124 -0
  143. data/lib/sisimai/smtp.rb +0 -1
  144. data/lib/sisimai/string.rb +74 -5
  145. data/lib/sisimai/time.rb +1 -2
  146. data/lib/sisimai/version.rb +1 -1
  147. data/lib/sisimai.rb +46 -31
  148. data/set-of-emails/maildir/bsd/lhost-domino-02.eml +6 -3
  149. data/set-of-emails/maildir/bsd/lhost-googlegroups-15.eml +174 -0
  150. data/set-of-emails/maildir/bsd/lhost-gsuite-15.eml +229 -0
  151. data/set-of-emails/maildir/bsd/lhost-postfix-75.eml +51 -0
  152. data/set-of-emails/maildir/bsd/lhost-postfix-76.eml +101 -0
  153. data/set-of-emails/maildir/bsd/lhost-postfix-77.eml +74 -0
  154. data/set-of-emails/maildir/bsd/lhost-postfix-78.eml +91 -0
  155. data/set-of-emails/maildir/bsd/lhost-receivingses-08.eml +88 -0
  156. data/set-of-emails/maildir/bsd/lhost-sendmail-60.eml +85 -0
  157. data/set-of-emails/maildir/bsd/rfc3464-43.eml +88 -0
  158. data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
  159. data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
  160. data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
  161. data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
  162. data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
  163. data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
  164. data/sisimai-java.gemspec +1 -1
  165. data/sisimai.gemspec +1 -1
  166. metadata +48 -26
  167. data/.rspec +0 -2
  168. data/lib/sisimai/data/yaml.rb +0 -33
  169. data/lib/sisimai/data.rb +0 -411
  170. data/lib/sisimai/mime.rb +0 -456
  171. data/lib/sisimai/rhost/googleapps.rb +0 -261
  172. /data/set-of-emails/maildir/bsd/{rfc3464-41.eml → rfc3834-05.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{rhost-googleapps-01.eml → rhost-google-01.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{rhost-googleapps-02.eml → rhost-google-02.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-01.eml → rhost-microsoft-01.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-02.eml → rhost-microsoft-02.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-03.eml → rhost-microsoft-03.eml} +0 -0
  178. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-01.eml → rhost-tencent-01.eml} +0 -0
  179. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-02.eml → rhost-tencent-02.eml} +0 -0
  180. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-03.eml → rhost-tencent-03.eml} +0 -0
@@ -1,18 +1,16 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::MessageLabs parses a bounce email which created by
3
- # Symantec.cloud: formerly MessageLabs. Methods in the module are called
4
- # from only Sisimai::Message.
2
+ # Sisimai::Lhost::MessageLabs parses a bounce email which created by Symantec.cloud: formerly MessageLabs.
3
+ # Methods in the module are called from only Sisimai::Message.
5
4
  module MessageLabs
6
5
  class << self
7
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/MessageLabs.pm
8
6
  require 'sisimai/lhost'
9
7
 
10
8
  Indicators = Sisimai::Lhost.INDICATORS
11
- ReBackbone = %r|^Content-Type:[ ]text/rfc822-headers|.freeze
9
+ Boundaries = ['Content-Type: text/rfc822-headers'].freeze
12
10
  StartingOf = { message: ['Content-Type: message/delivery-status'] }.freeze
13
- ReFailures = {
14
- 'userunknown' => %r/(?:542 .+ Rejected|No such user)/,
15
- 'securityerror' => %r/Please turn on SMTP Authentication in your mail client/,
11
+ MessagesOf = {
12
+ 'userunknown' => ['542 ', ' Rejected', 'No such user'],
13
+ 'securityerror' => ['Please turn on SMTP Authentication in your mail client'],
16
14
  }.freeze
17
15
 
18
16
  # Parse bounce messages from Symantec.cloud(MessageLabs)
@@ -20,7 +18,7 @@ module Sisimai::Lhost
20
18
  # @param [String] mbody Message body of a bounce email
21
19
  # @return [Hash] Bounce data list and message/rfc822 part
22
20
  # @return [Nil] it failed to parse or the arguments are missing
23
- def make(mhead, mbody)
21
+ def inquire(mhead, mbody)
24
22
  # X-Msg-Ref: server-11.tower-143.messagelabs.com!1419367175!36473369!1
25
23
  # X-Originating-IP: [10.245.230.38]
26
24
  # X-StarScan-Received:
@@ -30,13 +28,12 @@ module Sisimai::Lhost
30
28
  return nil unless mhead['from'].include?('MAILER-DAEMON@messagelabs.com')
31
29
  return nil unless mhead['subject'].start_with?('Mail Delivery Failure')
32
30
 
33
- require 'sisimai/rfc1894'
34
31
  fieldtable = Sisimai::RFC1894.FIELDTABLE
35
32
  permessage = {} # (Hash) Store values of each Per-Message field
36
33
 
37
34
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
38
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
39
- bodyslices = emailsteak[0].split("\n")
35
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
36
+ bodyslices = emailparts[0].split("\n")
40
37
  readslices = ['']
41
38
  readcursor = 0 # (Integer) Points the current cursor position
42
39
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
@@ -44,8 +41,8 @@ module Sisimai::Lhost
44
41
  v = nil
45
42
 
46
43
  while e = bodyslices.shift do
47
- # Read error messages and delivery status lines from the head of the email
48
- # to the previous line of the beginning of the original message.
44
+ # Read error messages and delivery status lines from the head of the email to the previous
45
+ # line of the beginning of the original message.
49
46
  readslices << e # Save the current line for the next loop
50
47
 
51
48
  if readcursor == 0
@@ -86,14 +83,14 @@ module Sisimai::Lhost
86
83
  next unless fieldtable[o[0]]
87
84
  v[fieldtable[o[0]]] = o[2]
88
85
 
89
- next unless f == 1
86
+ next unless f
90
87
  permessage[fieldtable[o[0]]] = o[2]
91
88
  end
92
89
  else
93
90
  # Continued line of the value of Diagnostic-Code field
94
91
  next unless readslices[-2].start_with?('Diagnostic-Code:')
95
- next unless cv = e.match(/\A[ \t]+(.+)\z/)
96
- v['diagnosis'] << ' ' << cv[1]
92
+ next unless e.start_with?(' ')
93
+ v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
97
94
  readslices[-1] = 'Diagnostic-Code: ' << e
98
95
  end
99
96
  end
@@ -101,20 +98,19 @@ module Sisimai::Lhost
101
98
 
102
99
  dscontents.each do |e|
103
100
  # Set default values if each value is empty.
104
- e['lhost'] ||= permessage['rhost']
105
101
  permessage.each_key { |a| e[a] ||= permessage[a] || '' }
106
102
  e['command'] = commandset.shift || ''
107
103
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
108
104
 
109
- ReFailures.each_key do |r|
105
+ MessagesOf.each_key do |r|
110
106
  # Verify each regular expression of session errors
111
- next unless e['diagnosis'] =~ ReFailures[r]
107
+ next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
112
108
  e['reason'] = r
113
109
  break
114
110
  end
115
111
  end
116
112
 
117
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
113
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
118
114
  end
119
115
  def description; return 'Symantec.cloud http://www.messagelabs.com'; end
120
116
  end
@@ -1,14 +1,12 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::MessagingServer parses a bounce email which created
3
- # by Oracle Communications Messaging Server and Sun Java System Messaging
4
- # Server. Methods in the module are called from only Sisimai::Message.
2
+ # Sisimai::Lhost::MessagingServer parses a bounce email which created by Oracle Communications Messaging
3
+ # Server and Sun Java System Messaging Server. Methods in the module are called from only Sisimai::Message.
5
4
  module MessagingServer
6
5
  class << self
7
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/MessagingServer.pm
8
6
  require 'sisimai/lhost'
9
7
 
10
8
  Indicators = Sisimai::Lhost.INDICATORS
11
- ReBackbone = %r<^(?:Content-type:[ ]*message/rfc822|Return-path:[ ]*)>.freeze
9
+ Boundaries = ['Content-Type: message/rfc822', 'Return-path: '].freeze
12
10
  StartingOf = { message: ['This report relates to a message you sent with the following header fields:'] }.freeze
13
11
  MessagesOf = { 'hostunknown' => ['Illegal host/domain name found'] }.freeze
14
12
 
@@ -17,23 +15,22 @@ module Sisimai::Lhost
17
15
  # @param [String] mbody Message body of a bounce email
18
16
  # @return [Hash] Bounce data list and message/rfc822 part
19
17
  # @return [Nil] it failed to parse or the arguments are missing
20
- def make(mhead, mbody)
21
- # :received => %r/[ ][(]MessagingServer[)][ ]with[ ]/,
18
+ def inquire(mhead, mbody)
22
19
  match = 0
23
20
  match += 1 if mhead['content-type'].include?('Boundary_(ID_')
24
21
  match += 1 if mhead['subject'].start_with?('Delivery Notification: ')
25
22
  return nil unless match > 0
26
23
 
27
24
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
28
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
29
- bodyslices = emailsteak[0].split("\n")
25
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
26
+ bodyslices = emailparts[0].split("\n")
30
27
  readcursor = 0 # (Integer) Points the current cursor position
31
28
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
32
29
  v = nil
33
30
 
34
31
  while e = bodyslices.shift do
35
- # Read error messages and delivery status lines from the head of the email
36
- # to the previous line of the beginning of the original message.
32
+ # Read error messages and delivery status lines from the head of the email to the previous
33
+ # line of the beginning of the original message.
37
34
  if readcursor == 0
38
35
  # Beginning of the bounce message or delivery status part
39
36
  readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
@@ -62,45 +59,49 @@ module Sisimai::Lhost
62
59
  # Remote system: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25) (6jo.example.jp ESMTP SENDMAIL-VM)
63
60
  v = dscontents[-1]
64
61
 
65
- if cv = e.match(/\A[ \t]+Recipient address:[ \t]*([^ ]+[@][^ ]+)\z/)
62
+ if e.start_with?(' Recipient address: ') && e.index('@') > 1
66
63
  # Recipient address: kijitora@example.jp
67
64
  if v['recipient']
68
65
  # There are multiple recipient addresses in the message body.
69
66
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
70
67
  v = dscontents[-1]
71
68
  end
72
- v['recipient'] = Sisimai::Address.s3s4(cv[1])
69
+ v['recipient'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
73
70
  recipients += 1
74
71
 
75
- elsif cv = e.match(/\A[ \t]+Original address:[ \t]*([^ ]+[@][^ ]+)\z/)
72
+ elsif e.start_with?(' Original address: ') && e.index('@') > 1
76
73
  # Original address: kijitora@example.jp
77
- v['recipient'] = Sisimai::Address.s3s4(cv[1])
74
+ v['recipient'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
78
75
 
79
- elsif cv = e.match(/\A[ \t]+Date:[ \t]*(.+)\z/)
76
+ elsif e.start_with?(' Date: ')
80
77
  # Date: Fri, 21 Nov 2014 23:34:45 +0900
81
- v['date'] = cv[1]
78
+ v['date'] = e[e.index(':') + 2, e.size]
82
79
 
83
- elsif cv = e.match(/\A[ \t]+Reason:[ \t]*(.+)\z/)
80
+ elsif e.start_with?(' Reason: ')
84
81
  # Reason: Remote SMTP server has rejected address
85
- v['diagnosis'] = cv[1]
82
+ v['diagnosis'] = e[e.index(':') + 2, e.size]
86
83
 
87
- elsif cv = e.match(/\A[ \t]+Diagnostic code:[ \t]*([^ ]+);(.+)\z/)
84
+ elsif e.start_with?(' Diagnostic code: ')
88
85
  # Diagnostic code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
89
- v['spec'] = cv[1].upcase
90
- v['diagnosis'] = cv[2]
86
+ p1 = e.index(':')
87
+ p2 = e.index(';')
88
+ v['spec'] = e[p1 + 2, p2 - p1 - 2].upcase
89
+ v['diagnosis'] = e[p2 + 1, e.size]
91
90
 
92
- elsif cv = e.match(/\A[ \t]+Remote system:[ ]*dns;([^ ]+)[ ]*([^ ]+)[ ]*.+\z/)
91
+ elsif e.start_with?(' Remote system: ')
93
92
  # Remote system: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25)
94
93
  # (6jo.example.jp ESMTP SENDMAIL-VM)
95
- remotehost = cv[1] # remote host
96
- sessionlog = cv[2] # smtp session
94
+ p1 = e.index(';')
95
+ p2 = e.index('(')
96
+ remotehost = e[p1 + 1, p2 - p1 - 2]
97
+ sessionlog = e[p2, e.size].split('|')
97
98
  v['rhost'] = remotehost
98
99
 
99
100
  # The value does not include ".", use IP address instead.
100
101
  # (TCP|17.111.174.67|47323|192.0.2.225|25)
101
- next unless cv = sessionlog.match(/\A[(]TCP|(.+)|\d+|(.+)|\d+[)]/)
102
- v['lhost'] = cv[1]
103
- v['rhost'] = cv[2] unless remotehost =~ /[^.]+[.][^.]+/
102
+ next unless sessionlog[0] == '(TCP'
103
+ v['lhost'] = sessionlog[1]
104
+ v['rhost'] = sessionlog[3] unless remotehost.index('.') > 1
104
105
  else
105
106
  # Original-envelope-id: 0NFC009FLKOUVMA0@mr21p30im-asmtp004.me.com
106
107
  # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
@@ -114,20 +115,22 @@ module Sisimai::Lhost
114
115
  # (6jo.example.jp ESMTP SENDMAIL-VM)
115
116
  # Diagnostic-code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
116
117
  #
117
- if cv = e.match(/\AStatus:[ ]*(\d[.]\d[.]\d)[ ]*[(](.+)[)]\z/)
118
+ if e.start_with?('Status: ')
118
119
  # Status: 5.1.1 (Remote SMTP server has rejected address)
119
- v['status'] = cv[1]
120
- v['diagnosis'] ||= cv[2]
120
+ p1 = e.index(':')
121
+ p2 = e.index('(')
122
+ v['status'] = e[p1 + 2, p2 - p1 - 3]
123
+ v['diagnosis'] ||= e[p2 + 1, e[e.index(')') - p2 - 1]]
121
124
 
122
- elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
125
+ elsif e.start_with?('Arrival-Date: ')
123
126
  # Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT)
124
- v['date'] ||= cv[1]
127
+ v['date'] ||= e[e.index(':') + 2, e.size]
125
128
 
126
- elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
129
+ elsif e.start_with?('Reporting-MTA: ')
127
130
  # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
128
- localhost = cv[1]
131
+ localhost = e[e.index(';') + 1, e.size]
129
132
  v['lhost'] ||= localhost
130
- v['lhost'] = localhost unless v['lhost'] =~ /[^.]+[.][^ ]+/
133
+ v['lhost'] = localhost unless v['lhost'].index('.') > 0
131
134
  end
132
135
  end
133
136
  end
@@ -143,7 +146,7 @@ module Sisimai::Lhost
143
146
  end
144
147
  end
145
148
 
146
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
149
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
147
150
  end
148
151
  def description; return 'Oracle Communications Messaging Server'; end
149
152
  end
@@ -1,44 +1,43 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::mFILTER parses a bounce email which created by
3
- # Digital Arts m-FILTER.
4
- # Methods in the module are called from only Sisimai::Message.
2
+ # Sisimai::Lhost::mFILTER parses a bounce email which created by Digital Arts m-FILTER. Methods in
3
+ # the module are called from only Sisimai::Message.
5
4
  module MFILTER
6
5
  class << self
7
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/mFILTER.pm
8
6
  require 'sisimai/lhost'
9
7
 
10
8
  Indicators = Sisimai::Lhost.INDICATORS
11
- ReBackbone = %r/^-------original[ ](?:message|mail[ ]info)/.freeze
9
+ Boundaries = ['-------original message', '-------original mail info'].freeze
12
10
  StartingOf = {
13
11
  error: ['-------server message'],
14
12
  command: ['-------SMTP command'],
15
13
  }.freeze
16
- MarkingsOf = { message: %r/\A[^ ]+[@][^ ]+[.][a-zA-Z]+\z/ }.freeze
17
14
 
18
15
  # Parse bounce messages from Digital Arts m-FILTER
19
16
  # @param [Hash] mhead Message headers of a bounce email
20
17
  # @param [String] mbody Message body of a bounce email
21
18
  # @return [Hash] Bounce data list and message/rfc822 part
22
19
  # @return [Nil] it failed to parse or the arguments are missing
23
- def make(mhead, mbody)
20
+ def inquire(mhead, mbody)
24
21
  # X-Mailer: m-FILTER
25
22
  return nil unless mhead['x-mailer'].to_s == 'm-FILTER'
26
23
  return nil unless mhead['subject'] == 'failure notice'
27
24
 
28
25
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
29
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
30
- bodyslices = emailsteak[0].split("\n")
26
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
27
+ bodyslices = emailparts[0].split("\n")
31
28
  readcursor = 0 # (Integer) Points the current cursor position
32
29
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
33
30
  markingset = { 'diagnosis' => false, 'command' => false }
34
31
  v = nil
35
32
 
36
33
  while e = bodyslices.shift do
37
- # Read error messages and delivery status lines from the head of the email
38
- # to the previous line of the beginning of the original message.
34
+ # Read error messages and delivery status lines from the head of the email to the previous
35
+ # line of the beginning of the original message.
39
36
  if readcursor == 0
40
37
  # Beginning of the bounce message or delivery status part
41
- readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
38
+ if e.include?('@') && e.include?(' ') == false && Sisimai::Address.is_emailaddress(e)
39
+ readcursor |= Indicators[:deliverystatus]
40
+ end
42
41
  end
43
42
  next if (readcursor & Indicators[:deliverystatus]) == 0
44
43
  next if e.empty?
@@ -60,7 +59,7 @@ module Sisimai::Lhost
60
59
  # -------original message
61
60
  v = dscontents[-1]
62
61
 
63
- if cv = e.match(/\A([^ ]+[@][^ ]+)\z/)
62
+ if e.include?('@') && e.include?(' ') == false
64
63
  # 以下のメールアドレスへの送信に失敗しました。
65
64
  # kijitora@example.jp
66
65
  if v['recipient']
@@ -68,10 +67,10 @@ module Sisimai::Lhost
68
67
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
69
68
  v = dscontents[-1]
70
69
  end
71
- v['recipient'] = cv[1]
70
+ v['recipient'] = e
72
71
  recipients += 1
73
72
 
74
- elsif e =~ /\A[A-Z]{4}/
73
+ elsif e.size == 4 && e.index(' ').nil?
75
74
  # -------SMTP command
76
75
  # DATA
77
76
  next if v['command']
@@ -105,13 +104,13 @@ module Sisimai::Lhost
105
104
  rhosts = Sisimai::RFC5322.received(rheads[-1])
106
105
 
107
106
  e['lhost'] ||= Sisimai::RFC5322.received(rheads[0]).shift
108
- while ee = rhosts.shift do
107
+ [rhosts[0], rhosts[1]].each do |ee|
109
108
  # Avoid "... by m-FILTER"
110
109
  next unless ee.include?('.')
111
110
  e['rhost'] = ee
112
111
  end
113
112
  end
114
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
113
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
115
114
  end
116
115
  def description; return 'Digital Arts m-FILTER'; end
117
116
  end
@@ -1,22 +1,20 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::MXLogic parses a bounce email which created by
3
- # McAfee SaaS (formerly MX Logic).
2
+ # Sisimai::Lhost::MXLogic parses a bounce email which created by McAfee SaaS (formerly MX Logic).
4
3
  # Methods in the module are called from only Sisimai::Message.
5
4
  module MXLogic
6
5
  class << self
7
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/MXLogic.pm
8
6
  # Based on Sisimai::Lhost::Exim
9
7
  require 'sisimai/lhost'
10
8
 
11
9
  Indicators = Sisimai::Lhost.INDICATORS
12
- ReBackbone = %r|^Included is a copy of the message header:|.freeze
10
+ Boundaries = ['Included is a copy of the message header:'].freeze
13
11
  StartingOf = { message: ['This message was created automatically by mail delivery software.'] }.freeze
14
12
  ReCommands = [
15
13
  %r/SMTP error from remote (?:mail server|mailer) after ([A-Za-z]{4})/,
16
14
  %r/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,
17
15
  ].freeze
18
16
  MessagesOf = {
19
- # find exim/ -type f -exec grep 'message = US' {} /dev/null \;
17
+ # % find exim/ -type f -exec grep 'message = US' {} /dev/null \;
20
18
  # route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
21
19
  'userunknown' => ['user not found'],
22
20
  # transports/smtp.c:3524| addr->message = US"all host address lookups failed permanently";
@@ -74,7 +72,7 @@ module Sisimai::Lhost
74
72
  # @param [String] mbody Message body of a bounce email
75
73
  # @return [Hash] Bounce data list and message/rfc822 part
76
74
  # @return [Nil] it failed to parse or the arguments are missing
77
- def make(mhead, mbody)
75
+ def inquire(mhead, mbody)
78
76
  # X-MX-Bounce: mta/src/queue/bounce
79
77
  # X-MXL-NoteHash: ffffffffffffffff-0000000000000000000000000000000000000000
80
78
  # X-MXL-Hash: 4c9d4d411993da17-bbd4212b6c887f6c23bab7db4bd87ef5edc00758
@@ -83,25 +81,19 @@ module Sisimai::Lhost
83
81
  match += 1 if mhead['x-mxl-hash']
84
82
  match += 1 if mhead['x-mxl-notehash']
85
83
  match += 1 if mhead['from'].start_with?('Mail Delivery System')
86
- match += 1 if mhead['subject'] =~ %r{(?:
87
- Mail[ ]delivery[ ]failed(:[ ]returning[ ]message[ ]to[ ]sender)?
88
- |Warning:[ ]message[ ][^ ]+[ ]delayed[ ]+
89
- |Delivery[ ]Status[ ]Notification
90
- )
91
- }x
84
+ match += 1 if ['Delivery Status Notification', 'Mail delivery failed', 'Warning: message '].any? { |a| mhead['subject'].include?(a) }
92
85
  return nil unless match > 0
93
86
 
94
87
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
95
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
96
- bodyslices = emailsteak[0].split("\n")
88
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
89
+ bodyslices = emailparts[0].split("\n")
97
90
  readcursor = 0 # (Integer) Points the current cursor position
98
91
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
99
- localhost0 = '' # (String) Local MTA
100
92
  v = nil
101
93
 
102
94
  while e = bodyslices.shift do
103
- # Read error messages and delivery status lines from the head of the email
104
- # to the previous line of the beginning of the original message.
95
+ # Read error messages and delivery status lines from the head of the email to the previous
96
+ # line of the beginning of the original message.
105
97
  if readcursor == 0
106
98
  # Beginning of the bounce message or delivery status part
107
99
  readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
@@ -120,7 +112,7 @@ module Sisimai::Lhost
120
112
  # host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
121
113
  v = dscontents[-1]
122
114
 
123
- if cv = e.match(/\A[ \t]*[<]([^ ]+[@][^ ]+)[>]:(.+)\z/)
115
+ if e.start_with?(' <') && e.include?('@') && e.include?('>:')
124
116
  # A message that you have sent could not be delivered to one or more
125
117
  # recipients. This is a permanent error. The following address failed:
126
118
  #
@@ -130,8 +122,8 @@ module Sisimai::Lhost
130
122
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
131
123
  v = dscontents[-1]
132
124
  end
133
- v['recipient'] = cv[1]
134
- v['diagnosis'] = cv[2]
125
+ v['recipient'] = e[3, e.index('>:') - 3]
126
+ v['diagnosis'] = e[e.index('>:') + 3, e.size]
135
127
  recipients += 1
136
128
 
137
129
  elsif dscontents.size == recipients
@@ -142,25 +134,24 @@ module Sisimai::Lhost
142
134
  end
143
135
  return nil unless recipients > 0
144
136
 
145
- unless mhead['received'].empty?
146
- # Get the name of local MTA
147
- # Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
148
- if cv = mhead['received'][-1].match(/from[ ]([^ ]+) /) then localhost0 = cv[1] end
149
- end
137
+ # Get the name of the local MTA
138
+ # Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
139
+ receivedby = mhead['received'] || []
140
+ recvdtoken = Sisimai::RFC5322.received(receivedby[-1])
150
141
 
151
142
  dscontents.each do |e|
152
- e['lhost'] = localhost0
143
+ # Check the error message, the rhost, the lhost, and the smtp command.
144
+ e['lhost'] = recvdtoken[0]
153
145
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].gsub(/[-]{2}.*\z/, ''))
154
146
 
155
147
  unless e['rhost']
156
148
  # Get the remote host name
157
- # host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
158
- if cv = e['diagnosis'].match(/host[ ]+([^ \t]+)[ ]\[.+\]:[ ]/) then e['rhost'] = cv[1] end
149
+ p1 = e['diagnosis'].index('host ') || -1
150
+ p2 = e['diagnosis'].index(' ', p1 + 5)
159
151
 
160
- unless e['rhost']
161
- # Get localhost and remote host name from Received header.
162
- e['rhost'] = Sisimai::RFC5322.received(mhead['received'][-1]).pop unless mhead['received'].empty?
163
- end
152
+ # host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
153
+ e['rhost'] = e['diagnosis'][p1 + 5, p2 - p1 - 5] if p1 > -1
154
+ e['rhost'] ||= recvdtoken[1]
164
155
  end
165
156
 
166
157
  unless e['command']
@@ -198,7 +189,7 @@ module Sisimai::Lhost
198
189
  end
199
190
  end
200
191
 
201
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
192
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
202
193
  end
203
194
  def description; return 'McAfee SaaS'; end
204
195
  end
@@ -1,13 +1,12 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::Notes parses a bounce email which created by Lotus
3
- # Notes Server. Methods in the module are called from only Sisimai::Message.
2
+ # Sisimai::Lhost::Notes parses a bounce email which created by Lotus Notes Server. Methods in the
3
+ # module are called from only Sisimai::Message.
4
4
  module Notes
5
5
  class << self
6
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/Notes.pm
7
6
  require 'sisimai/lhost'
8
7
 
9
8
  Indicators = Sisimai::Lhost.INDICATORS
10
- ReBackbone = %r|^-------[ ]Returned[ ]Message[ ]--------|.freeze
9
+ Boundaries = ['------- Returned Message --------'].freeze
11
10
  StartingOf = { message: ['------- Failure Reasons '] }.freeze
12
11
  MessagesOf = {
13
12
  'userunknown' => [
@@ -22,12 +21,12 @@ module Sisimai::Lhost
22
21
  # @param [String] mbody Message body of a bounce email
23
22
  # @return [Hash] Bounce data list and message/rfc822 part
24
23
  # @return [Nil] it failed to parse or the arguments are missing
25
- def make(mhead, mbody)
24
+ def inquire(mhead, mbody)
26
25
  return nil unless mhead['subject'].start_with?('Undeliverable message')
27
26
 
28
27
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
29
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
30
- bodyslices = emailsteak[0].split("\n")
28
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
29
+ bodyslices = emailparts[0].split("\n")
31
30
  readcursor = 0 # (Integer) Points the current cursor position
32
31
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
33
32
  characters = '' # (String) Character set name of the bounce mail
@@ -35,15 +34,14 @@ module Sisimai::Lhost
35
34
  encodedmsg = ''
36
35
  v = nil
37
36
 
38
- if cv = mhead['content-type'].match(/\A.+;[ ]*charset=(.+)\z/)
39
- # Get character set name
40
- # Content-Type: text/plain; charset=ISO-2022-JP
41
- characters = cv[1].downcase
37
+ if mhead['content-type'].include?('charset=')
38
+ # Get character set name, Content-Type: text/plain; charset=ISO-2022-JP
39
+ characters = mhead['content-type'][mhead['content-type'].index('charset=') + 8, mhead['content-type'].size].downcase
42
40
  end
43
41
 
44
42
  while e = bodyslices.shift do
45
- # Read error messages and delivery status lines from the head of the email
46
- # to the previous line of the beginning of the original message.
43
+ # Read error messages and delivery status lines from the head of the email to the previous
44
+ # line of the beginning of the original message.
47
45
  if readcursor == 0
48
46
  # Beginning of the bounce message or delivery status part
49
47
  readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
@@ -58,7 +56,7 @@ module Sisimai::Lhost
58
56
  #
59
57
  # ------- Returned Message --------
60
58
  v = dscontents[-1]
61
- if e =~ /\A[^ ]+[@][^ ]+/
59
+ if e.include?('@') && e.index(' ').nil?
62
60
  # kijitora@notes.example.jp
63
61
  if v['recipient']
64
62
  # There are multiple recipient addresses in the message body.
@@ -97,8 +95,10 @@ module Sisimai::Lhost
97
95
 
98
96
  unless recipients > 0
99
97
  # Fallback: Get the recpient address from RFC822 part
100
- if cv = emailsteak[1].match(/^To:[ ]*(.+)$/)
101
- v['recipient'] = Sisimai::Address.s3s4(cv[1])
98
+ p1 = emailparts[1].index("\nTo: ") || -1
99
+ p2 = emailparts[1].index("\n", p1 + 6) || -1
100
+ if p1 > 0
101
+ v['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1 + 5, p2 - p1 - 5]) || ''
102
102
  recipients += 1 unless v['recipient'].empty?
103
103
  end
104
104
  end
@@ -117,7 +117,7 @@ module Sisimai::Lhost
117
117
  end
118
118
  end
119
119
 
120
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
120
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
121
121
  end
122
122
  def description; return 'Lotus Notes'; end
123
123
  end