sisimai 4.25.16-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 +412 -393
  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 -326
  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 -45
  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
@@ -0,0 +1,124 @@
1
+ module Sisimai
2
+ module SMTP
3
+ # Sisimai::SMTP::Transcript is a parser for transcript logs of SMTP session
4
+ module Transcript
5
+ class << self
6
+ require 'sisimai/smtp/reply'
7
+ require 'sisimai/smtp/status'
8
+
9
+ # Parse a transcript of an SMTP session and makes structured data
10
+ # @param [String] argv0 A transcript text MTA returned
11
+ # @param [String] argv1 A label string of a SMTP client
12
+ # @apram [String] argv2 A label string of a SMTP server
13
+ # @return [Array] Structured data
14
+ # [Nil] Failed to parse or the 1st argument is missing
15
+ # @since v5.0.0
16
+ def rise(argv0 = '', argv1 = '>>>', argv2 = '<<<')
17
+ return nil if argv0.size == 0
18
+
19
+ # 1. Replace label strings of SMTP client/server at the each line
20
+ argv0.gsub!(/^[ ]+#{argv1}\s+/m, '>>> '); return nil unless argv0.include?('>>> ')
21
+ argv0.gsub!(/^[ ]+#{argv2}\s+/m, '<<< '); return nil unless argv0.include?('<<< ')
22
+
23
+ # 2. Remove strings until the first '<<<' or '>>>'
24
+ esmtp = []
25
+ table = lambda do
26
+ return {
27
+ 'command' => nil, # SMTP command
28
+ 'argument' => '', # An argument of each SMTP command sent from a client
29
+ 'parameter' => {}, # Parameter pairs of the SMTP command
30
+ 'response' => { # A Response from an SMTP server
31
+ 'reply' => '', # - SMTP reply code such as 550
32
+ 'status' => '', # - SMTP status such as 5.1.1
33
+ 'text' => [], # - Response text lines
34
+ }
35
+ }
36
+ end
37
+ parameters = '' # Command parameters of MAIL, RCPT
38
+ cursession = nil # Current session for $esmtp
39
+
40
+ cv = ''
41
+ p0 = argv0.index('<<<') || -1 # Server response
42
+ p1 = argv0.index('>>>') || -1 # Sent command
43
+ if p0 < p1
44
+ # An SMTP server response starting with '<<<' is the first
45
+ esmtp << table.call
46
+ cursession = esmtp[-1]
47
+ cursession['command'] = 'CONN'
48
+ argv0 = argv0[p0, argv0.size] if p0 > -1
49
+ else
50
+ # An SMTP command starting with '>>>' is the first
51
+ argv0 = argv0[p1, argv0.size] if p1 > -1
52
+ end
53
+
54
+ # 3. Remove unused lines, concatenate folded lines
55
+ argv0 = argv0[0, argv0.index("\n\n") - 1] # Remove strings from the first blank line to the tail
56
+ argv0.gsub!(/\n[ ]+/m, ' ') # Concatenate folded lines to each previous line
57
+
58
+ argv0.split("\n").each do |e|
59
+ # 4. Read each SMTP command and server response
60
+ if e.start_with?('>>> ')
61
+ # SMTP client sent a command ">>> SMTP-command arguments"
62
+ if cv = e.match(/\A>>>[ ]([A-Z]+)[ ]?(.*)\z/)
63
+ # >>> SMTP Command
64
+ thecommand = cv[1]
65
+ commandarg = cv[2]
66
+
67
+ esmtp << table.call
68
+ cursession = esmtp[-1]
69
+ cursession['command'] = thecommand.upcase
70
+
71
+ if thecommand =~ /\A(?:MAIL|RCPT|XFORWARD)/
72
+ # MAIL or RCPT
73
+ if cv = commandarg.match(/\A(?:FROM|TO):[ ]*<(.+[@].+)>[ ]*(.*)\z/)
74
+ # >>> MAIL FROM: <neko@example.com> SIZE=65535
75
+ # >>> RCPT TO: <kijitora@example.org>
76
+ cursession['argument'] = cv[1]
77
+ parameters = cv[2]
78
+
79
+ else
80
+ # >>> XFORWARD NAME=neko2-nyaan3.y.example.co.jp ADDR=230.0.113.2 PORT=53672
81
+ # <<< 250 2.0.0 Ok
82
+ # >>> XFORWARD PROTO=SMTP HELO=neko2-nyaan3.y.example.co.jp IDENT=2LYC6642BLzFK3MM SOURCE=REMOTE
83
+ # <<< 250 2.0.0 Ok
84
+ parameters = commandarg
85
+ commandarg = ''
86
+ end
87
+
88
+ parameters.split(" ").each do |p|
89
+ # SIZE=22022, PROTO=SMTP, and so on
90
+ if cv = p.match(/\A([^ =]+)=([^ =]+)\z/) then cursession['parameter'][cv[1].downcase] = cv[2] end
91
+ end
92
+ else
93
+ # HELO, EHLO, AUTH, DATA, QUIT or Other SMTP command
94
+ cursession['argument'] = commandarg
95
+ end
96
+ end
97
+ else
98
+ # SMTP server sent a response "<<< response text"
99
+ p = e.index('<<< '); next unless p == 0
100
+
101
+ e = e[4, e.size]
102
+
103
+ e.sub!(/\A<<<[ ]/, '')
104
+ if cv = e.match(/\A([2-5]\d\d)[ ]/) then cursession['response']['reply'] = cv[1] end
105
+ if cv = e.match(/\A[245]\d\d[ ]([245][.]\d{1,3}[.]\d{1,3})[ ]/) then cursession['response']['status'] = cv[1] end
106
+ cursession['response']['text'] << e
107
+ end
108
+ end
109
+
110
+ return nil if esmtp.size == 0
111
+ return esmtp
112
+ end
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+ end
121
+ end
122
+ end
123
+ end
124
+
data/lib/sisimai/smtp.rb CHANGED
@@ -2,7 +2,6 @@ module Sisimai
2
2
  # Sisimai::SMTP is a parent class of Sisimai::SMTP::Status and Sisimai::SMTP::Reply.
3
3
  module SMTP
4
4
  class << self
5
- # Imported from p5-Sisimail/lib/Sisimai/SMTP.pm
6
5
  end
7
6
  end
8
7
  end
@@ -1,7 +1,6 @@
1
1
  module Sisimai
2
2
  # Sisimai::String provide utilities for dealing string
3
3
  module String
4
- # Imported from p5-Sisimail/lib/Sisimai/String.pm
5
4
  class << self
6
5
  Match = {
7
6
  html: %r|<html[ >].+?</html>|im,
@@ -47,11 +46,81 @@ module Sisimai
47
46
  # sweep(' neko ') #=> 'neko'
48
47
  def sweep(argv1)
49
48
  return argv1 unless argv1.is_a?(::String)
50
- argv1 = argv1.chomp.squeeze(' ').delete("\t").strip
51
- argv1 = argv1.sub(/ [-]{2,}[^ \t].+\z/, '')
49
+ argv1 = argv1.chomp.squeeze(' ').strip
50
+ argv1 = argv1.sub(/ [-]{2,}[^ ].+\z/, '')
52
51
  return argv1
53
52
  end
54
53
 
54
+ # Check if each element of the 2nd argument is aligned in the 1st argument or not
55
+ # @param [String] argv1 String to be checked
56
+ # @param [Array] argv2 List including the ordered strings
57
+ # @return [Bool] 0, 1
58
+ # @since v5.0.0
59
+ def aligned(argv1, argv2)
60
+ return nil if argv1.to_s.empty?
61
+ return nil unless argv2.is_a? Array
62
+ return nil unless argv2.size > 1
63
+
64
+ align = -1
65
+ right = 0
66
+ argv2.each do |e|
67
+ # Get the position of each element in the 1st argument using index()
68
+ p = argv1.index(e, align + 1)
69
+ break unless p # Break this loop when there is no string in the 1st argument
70
+ align = e.length + p - 1 # There is an aligned string in the 1st argument
71
+ right += 1
72
+ end
73
+
74
+ return true if right == argv2.size
75
+ return false
76
+ end
77
+
78
+ # Find an IPv4 address from the given string
79
+ # @param [String] argv1 String including an IPv4 address
80
+ # @return [Array] List of IPv4 addresses
81
+ # @since v5.0.0
82
+ def ipv4(argv0)
83
+ return nil if argv0.to_s.empty?
84
+ return [] if argv0.size < 7
85
+
86
+ ipv4a = []
87
+ %w|( ) [ ]|.each do |e|
88
+ # Rewrite: "mx.example.jp[192.0.2.1]" => "mx.example.jp 192.0.2.1"
89
+ p0 = argv0.index(e); next unless p0
90
+ argv0[p0, 1] = ' '
91
+ end
92
+
93
+ argv0.split(' ').each do |e|
94
+ # Find string including an IPv4 address
95
+ next unless e.index('.') # IPv4 address must include "." character
96
+
97
+ lx = e.size; next if lx < 7 || lx > 17 # 0.0.0.0 = 7, [255.255.255.255] = 17
98
+ cu = 0 # Cursor for seeking each octet of an IPv4 address
99
+ as = '' # ASCII Code of each character
100
+ eo = '' # Buffer of each octet of IPv4 Address
101
+
102
+ while cu < lx
103
+ # Check whether each character is a number or "." or not
104
+ as = e[cu, 1].ord
105
+ cu += 1
106
+
107
+ if as < 48 || as > 57
108
+ # The character is not a number(0-9)
109
+ break if as != 46 # The character is not "."
110
+ next if eo == '' # The current buffer is empty
111
+ break if eo.to_i > 255 # The current buffer is greater than 255
112
+ eo = ''
113
+ next
114
+ end
115
+ eo << as.chr
116
+ break if eo.to_i > 255
117
+ end
118
+ ipv4a << e if eo.size > 0 && eo.to_i < 256
119
+ end
120
+
121
+ return ipv4a
122
+ end
123
+
55
124
  # Convert given HTML text to plain text
56
125
  # @param [String] argv1 HTML text
57
126
  # @param [Boolean] loose Loose check flag
@@ -66,8 +135,8 @@ module Sisimai
66
135
  # 3. <a href = 'http://...'>...</a> to " http://... "
67
136
  # 4. <a href = 'mailto:...'>...</a> to " Value <mailto:...> "
68
137
  plain.scrub!('?')
69
- plain.gsub!(%r|<head>.*?</head>|im, '')
70
- plain.gsub!(%r|<style.*?>.*?</style>|im, '')
138
+ plain.gsub!(%r|<head>.+</head>|im, '')
139
+ plain.gsub!(%r|<style.+?>.+</style>|im, '')
71
140
  plain.gsub!(%r|<a\s+href\s*=\s*['"](https?://.+?)['"].*?>(.*?)</a>|i, '[\2](\1)')
72
141
  plain.gsub!(%r|<a\s+href\s*=\s*["']mailto:([^\s]+?)["']>(.*?)</a>|i, '[\2](mailto:\1)')
73
142
 
data/lib/sisimai/time.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'date'
2
2
  module Sisimai
3
- # Sisimai::Time is a child class of Date for Sisimai::Data.
3
+ # Sisimai::Time is a child class of Date for Sisimai::Fact
4
4
  class Time < ::DateTime
5
- # Imported from p5-Sisimail/lib/Sisimai/Time.pm
6
5
  def to_json(*)
7
6
  return self.to_time.to_i
8
7
  end
@@ -1,4 +1,4 @@
1
1
  # Define the version number of Sisimai
2
2
  module Sisimai
3
- VERSION = '4.25.16'.freeze
3
+ VERSION = '5.0.0'.freeze
4
4
  end
data/lib/sisimai.rb CHANGED
@@ -1,46 +1,59 @@
1
- # Sisimai is the system formerly known as bounceHammer 4, is a Ruby module for
2
- # analyzing bounce mails and generate structured data in a JSON format (YAML is
3
- # also available if "YAML" module is installed on your system) from parsed bounce
4
- # messages. Sisimai is a coined word: Sisi (the number 4 is pronounced "Si" in
5
- # Japanese) and MAI (acronym of "Mail Analyzing Interface").
1
+ # Sisimai is a Ruby module for analyzing RFC5322 bounce emails and generating structured data from
2
+ # parsed results.
6
3
  require 'sisimai/version'
7
4
  module Sisimai
8
- # Imported from p5-Sisimail/lib/Sisimai.pm
9
5
  class << self
10
6
  def version(); return Sisimai::VERSION; end
11
- def sysname(); return 'bouncehammer'; end
12
7
  def libname(); return 'Sisimai'; end
13
8
 
9
+ # Emulate "rise" method for the backward compatible
10
+ def make(argv0, **argv1)
11
+ warn ' ***warning: Sisimai.make will be removed at v5.1.0. Use Sisimai.rise instead';
12
+ return Sisimai.rise(argv0, **argv1)
13
+ end
14
+
14
15
  # Wrapper method for parsing mailbox/maidir
15
16
  # @param [String] argv0 Path to mbox or Maildir/
16
17
  # @param [Hash] argv0 or Hash (decoded JSON)
17
18
  # @param [IO] argv0 or STDIN object
18
19
  # @param [Hash] argv1 Parser options(delivered=false)
19
20
  # @options argv1 [Boolean] delivered true: Include "delivered" reason
20
- # @options argv1 [Lambda] hook Lambda object to be called back
21
+ # @options argv1 [Boolean] vacation true: Include "vacation" reason
22
+ # @options argv1 [Array] c___ Proc object to a callback method for the message and each file
21
23
  # @return [Array] Parsed objects
22
24
  # @return [nil] nil if the argument was wrong or an empty array
23
- def make(argv0, **argv1)
25
+ def rise(argv0, **argv1)
24
26
  return nil unless argv0
25
- require 'sisimai/data'
26
- require 'sisimai/message'
27
27
  require 'sisimai/mail'
28
+ require 'sisimai/fact'
28
29
 
29
- list = []
30
30
  return nil unless mail = Sisimai::Mail.new(argv0)
31
+ kind = mail.kind
32
+ c___ = argv1[:c___].is_a?(Array) ? argv1[:c___] : [nil, nil]
33
+ sisi = []
34
+
31
35
  while r = mail.data.read do
32
36
  # Read and parse each email file
33
- methodargv = { data: r, hook: argv1[:hook] }
34
- mesg = Sisimai::Message.new(**methodargv)
35
- next if mesg.void
37
+ path = mail.data.path
38
+ args = { data: r, hook: c___[0], origin: path, delivered: argv1[:delivered], vacation: argv1[:vacation] }
39
+ fact = Sisimai::Fact.rise(**args) || []
40
+
41
+ if c___[1]
42
+ # Run the callback function specified with "c___" parameter of Sisimai.rise after reading
43
+ # each email file in Maildir/ every time
44
+ args = { 'kind' => kind, 'mail' => r, 'path' => path, 'fact' => fact }
45
+ begin
46
+ c___[1].call(args) if c___[1].is_a?(Proc)
47
+ rescue StandardError => ce
48
+ warn ' ***warning: Something is wrong in the second element of the ":c___":' << ce.to_s
49
+ end
50
+ end
36
51
 
37
- methodargv = { data: mesg, delivered: argv1[:delivered], origin: mail.data.path }
38
- next unless data = Sisimai::Data.make(**methodargv)
39
- list += data unless data.empty?
52
+ sisi += fact unless fact.empty?
40
53
  end
41
54
 
42
- return nil if list.empty?
43
- return list
55
+ return nil if sisi.empty?
56
+ return sisi
44
57
  end
45
58
 
46
59
  # Wrapper method to parse mailbox/Maildir and dump as JSON
@@ -49,12 +62,13 @@ module Sisimai
49
62
  # @param [IO] argv0 or STDIN object
50
63
  # @param [Hash] argv1 Parser options
51
64
  # @options argv1 [Integer] delivered true: Include "delivered" reason
65
+ # @options argv1 [Integer] vacation true: Include "vacation" reason
52
66
  # @options argv1 [Lambda] hook Lambda object to be called back
53
67
  # @return [String] Parsed data as JSON text
54
68
  def dump(argv0, **argv1)
55
69
  return nil unless argv0
70
+ nyaan = Sisimai.rise(argv0, **argv1) || []
56
71
 
57
- nyaan = Sisimai.make(argv0, **argv1) || []
58
72
  if RUBY_PLATFORM.start_with?('java')
59
73
  # java-based ruby environment like JRuby.
60
74
  require 'jrjackson'
@@ -16,7 +16,10 @@ Received: from mailgw.example.co.jp (mx [192.0.2.98])
16
16
  From: Postmaster@example.co.jp
17
17
  To: "Neko" <kijitora@example.org>
18
18
  Subject: DELIVERY FAILURE:
19
- ユーザー Neko (kijitora@example.co.jp) は Domino ディレクトリには見つかりません。
19
+ =?ISO-2022-JP?B?GyRCJWYhPCU2ITwbKEI=?= Neko (kijitora@example.co.jp)
20
+ =?US-ASCII?Q??=
21
+ =?ISO-2022-JP?B?GyRCJE8bKEI=?= Domino =?ISO-2022-JP?B?GyRCJUclIyVsGyhC?=
22
+ =?ISO-2022-JP?B?GyRCJS8lSCVqJEskTzgrJEQkKyRqJF4kOyRzISMbKEI=?=
20
23
  Date: Thu, 08 Jul 2012 00:03:54 +0800
21
24
  MIME-Version: 1.0
22
25
  X-Priority: 3 (Normal)
@@ -40,7 +43,7 @@ was not delivered to:
40
43
 
41
44
  because:
42
45
 
43
- ユーザー Neko (kijitora@example.co.jp) Domino ディレクトリには見つかりません。
46
+ $B%f!<%6!<(B Neko (kijitora@example.co.jp) $B$O(B Domino $B%G%#%l%/%H%j$K$O8+$D$+$j$^$;$s!#(B
44
47
 
45
48
 
46
49
  --==0000000000000000000000
@@ -51,7 +54,7 @@ Reporting-MTA: dns;mx.example.co.jp
51
54
  Final-Recipient: rfc822;kijitora@example.co.jp
52
55
  Action: failed
53
56
  Status: 5.0.0
54
- Diagnostic-Code: X-Notes; ユーザー Neko (kijitora@example.co.jp) Domino ディレクトリには見つかりません。
57
+ Diagnostic-Code: X-Notes; $B%f!<%6!<(BNeko (kijitora@example.co.jp) $B$O(B Domino $B%G%#%l%/%H%j$K$O8+$D$+$j$^$;$s!#(B
55
58
 
56
59
  --==0000000000000000000000
57
60
  Content-Type: message/rfc822
@@ -0,0 +1,174 @@
1
+ Delivered-To: kijitora-cat-neko-nyaan@google.example.com
2
+ Received: by 2002:ab2:1785:0:b0:19a:50ce:a944 with SMTP id x5csp577194lqe;
3
+ Thu, 26 Feb 2023 18:30:56 -0800 (PST)
4
+ X-Received: by 2002:a05:651c:2228:b0:295:9c2e:7324 with SMTP id y40-20020a05651c222800b002959c2e7324mr6911855ljq.4.1677465056139;
5
+ Thu, 26 Feb 2023 18:30:56 -0800 (PST)
6
+ ARC-Seal: i=1; a=rsa-sha256; t=1677465056; cv=none;
7
+ d=google.com; s=arc-20160816;
8
+ b=OP8D/87B1NpWlJIFLb1Ryp9sBLMQEn0UmitQx/lhOphS5Y7h5VMQdue/m03cyueBqh
9
+ zWoeGi5vFkSzfqkopcggWfv26ZjF7ECHEWTULvw1Ddf1XqErTWOR9zjoxI5U71Kjg3CA
10
+ 2JtSCWTN2JG81XAnspYKc2qX7UUPISnl6mP5NjKzuDyHQKE3AtCHaAvy+/zUIXNfGZC5
11
+ VQVXi8C0cYMPMkFfh6qBlU64K9D5H+m4XB12tkRYzhejyAVz1z0UkgPcazLiqvCIPf5d
12
+ 5AajrntYaTvOar/K8+F1X3TYucNmWfGyXzPcBfCy6OjsdF4WUJ+P4WyPkcC4ZMnQuzTF
13
+ eemA==
14
+ ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
15
+ h=in-reply-to:references:subject:from:date:message-id:auto-submitted
16
+ :to:dkim-signature;
17
+ bh=o7cpmqx+tgCx5m+g8oZRWsGCIo8X32S8zBkahP2egx0=;
18
+ b=qp3ixYdgDwSmM9zTspitM3aUqmuQqGf52SlCuvGRrjksgHbHoSY6jRljQpWPDkwUlR
19
+ LdN/dyIBBmx2HqnVEjcwaajj52M+wJdQAdGj7gu2g+SP06VpmW+szmuMtqC13cJqlNhd
20
+ VJ67sS7oBJVRm4Jy5RmE2lfpnPMduLKo4MKQc6Uj7yxkeQlP4iNCVPfp1McXyhxtFHns
21
+ KogLbkS8NFpA04RaC4tabvp4vDup1/bFS/JRPBE4IQiYyUqVrG8s7o/0U5DznTy3Zsgf
22
+ zpxCIWd9zYzzmWFeKdyJNmAaH6e7/s+5rQVGe/ryc2q4lPNadxPcsMjOoJ2d29RCyFMy
23
+ /q0A==
24
+ ARC-Authentication-Results: i=1; mx.google.com;
25
+ dkim=pass header.i=@googlemail.com header.s=20210112 header.b=PqBP51+l;
26
+ spf=none (google.com: mail-sor-f69.google.com does not designate permitted sender hosts) smtp.helo=mail-sor-f69.google.com;
27
+ dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com
28
+ Return-Path: <>
29
+ Received: from mail-sor-f69.google.com (mail-sor-f69.google.com. [209.85.220.69])
30
+ by mx.google.com with SMTPS id q4-20020a2e9144000000b002946a078ae0sor1225584ljg.16.2023.02.26.18.30.56
31
+ for <kijitora-cat-neko-nyaan@google.example.com>
32
+ (Google Transport Security);
33
+ Thu, 26 Feb 2023 18:30:56 -0800 (PST)
34
+ Received-SPF: none (google.com: mail-sor-f69.google.com does not designate permitted sender hosts) client-ip=209.85.220.69;
35
+ Authentication-Results: mx.google.com;
36
+ dkim=pass header.i=@googlemail.com header.s=20210112 header.b=PqBP51+l;
37
+ spf=none (google.com: mail-sor-f69.google.com does not designate permitted sender hosts) smtp.helo=mail-sor-f69.google.com;
38
+ dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com
39
+ DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
40
+ d=googlemail.com; s=20210112;
41
+ h=in-reply-to:references:subject:from:date:message-id:auto-submitted
42
+ :to:from:to:cc:subject:date:message-id:reply-to;
43
+ bh=o7cpmqx+tgCx5m+g8oZRWsGCIo8X32S8zBkahP2egx0=;
44
+ b=PqBP51+lcin2uB1zGXsK534CFC9hpjVMDQRkzfbcTLcn9dQoqN2Mqs+6yHelWNr4eX
45
+ iZ0EVsWqfkU10OngaL9ThubvJqbYhZbc2Gcn0LdiqGrhMxPNSQ34rh/nlEODsbbJf2VW
46
+ 693Q+Z2ZhhZEapenSlVZjt8yz4CRi0qTdXkUPMEAnBEMpNviY2RidqALyeGgZBO5bNCm
47
+ FJd6AqwcHWW39mkM/iogaQjVVuxS68j8RApvY45meW+2JU718KqwmjVbP2KZ/ITCjOtf
48
+ TvNrRnHviC5vlUQKpmgpA2O/IzohR+nLnZctyT0KmRFNT/64gIm0fXNtrBnO8H2h5guG
49
+ 9KEg==
50
+ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
51
+ d=1e100.net; s=20210112;
52
+ h=in-reply-to:references:subject:from:date:message-id:auto-submitted
53
+ :to:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
54
+ bh=o7cpmqx+tgCx5m+g8oZRWsGCIo8X32S8zBkahP2egx0=;
55
+ b=A5Pr4scyEyeQ8hEk1X/11Ny4vP9lDOgOFCbADSW8su0Rq9MpPOp9qzYd85NcptzYaJ
56
+ ppKYZKCmzxoyQ3ZpPjo2EE/hXov0uG8I2uyWRuLrZETzVfIrtuWcri7E4xevduA9kdhu
57
+ nNrB9v2oFGRP5+Qz250EP2JHQLr02yLBjk7Bjz4cQDWsxGoyKLXNmLIeef84O6CgwiSp
58
+ z47l7B0D6LeL3DsUn15BVi2dPE4WNy6WayLXectHuguPV0e0MAipvveS81atFaRlgn0M
59
+ ri1GaOyX1O482y53Dzp0CxpMn4ncGjy16fiIbCYWhM1zFXWlwE0gh0KUUvIi5Ufbu8Vw
60
+ qDPQ==
61
+ X-Gm-Message-State: AO0yUKUJaTXy+S83h8MMnRXh7sfSuZ7HejgVWHxgkbSYtw+QqlbGU2lF 7AXe9LaunF0Hpx5yxJZoRdluHO2zI0nVlH5Xf5XAZw==
62
+ X-Google-Smtp-Source: AK7set/UsC/BGtW9CgmWT8fuRPR2fZ9bqAPkWp9ktaIpWH7ZEk6t6+2qHXF6VAriVlypEme5zhNO1UrtaRrYckjLRErmeFA6MB/l9as=
63
+ X-Received: by 2002:a05:651c:1614:b0:293:27a9:ef34 with SMTP id f20-20020a05651c161400b0029327a9ef34mr2807111ljq.0.1677465056065;
64
+ Thu, 26 Feb 2023 18:30:56 -0800 (PST)
65
+ Content-Type: multipart/report; boundary="000000000000ca2d9205f5a5444d"; report-type=delivery-status
66
+ To: kijitora-cat-neko-nyaan@google.example.com
67
+ Received: by 2002:a05:651c:1614:b0:293:27a9:ef34 with SMTP id f20-20020a05651c161400b0029327a9ef34mr2834317ljq.0; Thu, 26 Feb 2023 18:30:56 -0800 (PST)
68
+ Return-Path: <>
69
+ Auto-Submitted: auto-replied
70
+ Message-ID: <63fc15e0.050a0220.58de0.183e.GMR@mx.google.com>
71
+ Date: Thu, 26 Feb 2023 18:30:56 -0800 (PST)
72
+ From: Mail Delivery Subsystem <mailer-daemon@googlemail.com>
73
+ Subject: Delivery Status Notification (Failure)
74
+ X-Failed-Recipients: neko-nyaan-cat-meeting@google-groups.example.com
75
+
76
+ --000000000000ca2d9205f5a5444d
77
+ Content-Type: multipart/related; boundary="000000000000ca332c05f5a5444e"
78
+
79
+ --000000000000ca332c05f5a5444e
80
+ Content-Type: multipart/alternative; boundary="000000000000ca333105f5a5444f"
81
+
82
+ --000000000000ca333105f5a5444f
83
+ Content-Type: text/plain; charset="UTF-8"
84
+
85
+
86
+ ** Message not delivered **
87
+
88
+ You're sending this from a different address or alias using the 'Send mail as' feature. The settings for your 'Send mail as' account are misconfigured or out of date. Check those settings and try resending.
89
+
90
+ Learn more here: https://support.google.com/mail/?p=CustomFromDenied
91
+
92
+ The response was:
93
+
94
+ Unspecified Error (SENT_SECOND_EHLO): Smtp server does not advertise AUTH capability
95
+
96
+ --000000000000ca333105f5a5444f
97
+ Content-Type: text/html; charset="UTF-8"
98
+
99
+
100
+ <html>
101
+ <head>
102
+ <style>
103
+ * {
104
+ font-family:Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
105
+ }
106
+ </style>
107
+ </head>
108
+ <body>
109
+ <table cellpadding="0" cellspacing="0" class="email-wrapper" style="padding-top:32px;background-color:#ffffff;"><tbody>
110
+ <tr><td>
111
+ <table cellpadding=0 cellspacing=0><tbody>
112
+ <tr><td style="max-width:560px;padding:24px 24px 32px;background-color:#fafafa;border:1px solid #e0e0e0;border-radius:2px">
113
+ <img style="padding:0 24px 16px 0;float:left" width=72 height=72 alt="Error Icon" src="cid:icon.png">
114
+ <table style="min-width:272px;padding-top:8px"><tbody>
115
+ <tr><td><h2 style="font-size:20px;color:#212121;font-weight:bold;margin:0">
116
+ Message not delivered
117
+ </h2></td></tr>
118
+ <tr><td style="padding-top:20px;color:#757575;font-size:16px;font-weight:normal;text-align:left">
119
+ You're sending this from a different address or alias using the 'Send mail as' feature. The settings for your 'Send mail as' account are misconfigured or out of date. Check those settings and try resending.
120
+ </td></tr>
121
+ <tr><td style="padding-top:24px;color:#4285F4;font-size:14px;font-weight:bold;text-align:left">
122
+ <a style="text-decoration:none" href="https://support.google.com/mail/?p=CustomFromDenied">LEARN MORE</a>
123
+ </td></tr>
124
+ </tbody></table>
125
+ </td></tr>
126
+ </tbody></table>
127
+ </td></tr>
128
+ <tr style="border:none;background-color:#fff;font-size:12.8px;width:90%">
129
+ <td align="left" style="padding:48px 10px">
130
+ The response was:<br/>
131
+ <p style="font-family:monospace">
132
+ Unspecified Error (SENT_SECOND_EHLO): Smtp server does not advertise AUTH capability
133
+ </p>
134
+ </td>
135
+ </tr>
136
+ </tbody></table>
137
+ </body>
138
+ </html>
139
+
140
+ --000000000000ca333105f5a5444f--
141
+ --000000000000ca332c05f5a5444e
142
+ Content-Type: image/png; name="icon.png"
143
+ Content-Disposition: attachment; filename="icon.png"
144
+ Content-Transfer-Encoding: base64
145
+ Content-ID: <icon.png>
146
+
147
+
148
+ --000000000000ca332c05f5a5444e--
149
+ --000000000000ca2d9205f5a5444d
150
+ Content-Type: message/delivery-status
151
+
152
+
153
+ --000000000000ca2d9205f5a5444d
154
+ Content-Type: message/rfc822
155
+
156
+ X-Gm-Message-State: AO0yUKVhi7hlxZPb1quoNAHFXZJYgxvbTGotZqnNumozCBfX0y128Dd7 ntdOGQFAIqeTt2XVskzfywmr4dxrTq5ZkcUjJd8=
157
+ X-Google-Smtp-Source: AK7set9BQ/++KfZD1JUmMUMiZsssix2NWMbSdwZ9fNTVQYWVFsuwS0n2iAfCxXwTBPTRWmYP524J/ncm2F65UJI4xAk=
158
+ X-Received: by 2002:a05:651c:1614:b0:293:27a9:ef34 with SMTP id f20-20020a05651c161400b0029327a9ef34mr2807080ljq.0.1677465053122; Thu, 26 Feb 2023 18:30:53 -0800 (PST)
159
+ MIME-Version: 1.0
160
+ In-Reply-To: <CAByYQsEaO0O4GgfWivReAX=r_OECkcwQgkgSbXJy7LeCm5vvNg@mail.gmail.com>
161
+ From: <michitsuna@example.jp>
162
+ Date: Mon, 27 Feb 2023 11:30:40 +0900
163
+ X-Gmail-Original-Message-ID: <CAByYQsF5qdTf_h-1AAVPW0RgR1YN+LE=+0Uv9LpQ4aA_myPtCw@mail.gmail.com>
164
+ Message-ID: <CAByYQsF5qdTf_h-1AAVPW0RgR1YN+LE=+0Uv9LpQ4aA_myPtCw@mail.gmail.com>
165
+ Subject: Nyaan
166
+ To: <nekochan@example.co.jp>
167
+ Content-Type: multipart/mixed; boundary="0000000000009d969b05f5a54484"
168
+
169
+ --0000000000009d969b05f5a54484
170
+
171
+ ----- Message truncated -----
172
+ --0000000000009d969b05f5a54484--
173
+
174
+ --000000000000ca2d9205f5a5444d--