sisimai 4.25.16-java → 5.0.2-java

Sign up to get free protection for your applications and to get access to all the features.
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