sisimai 4.18.1 → 4.19.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sisimai might be problematic. Click here for more details.

Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/ANALYTICAL-PRECISION +9 -9
  3. data/Changes +8 -0
  4. data/README-JA.md +31 -2
  5. data/README.md +32 -3
  6. data/lib/sisimai.rb +20 -7
  7. data/lib/sisimai/data.rb +3 -0
  8. data/lib/sisimai/message.rb +39 -6
  9. data/lib/sisimai/mime.rb +5 -5
  10. data/lib/sisimai/msp/us/amazonses.rb +17 -4
  11. data/lib/sisimai/reason.rb +54 -0
  12. data/lib/sisimai/reason/systemerror.rb +1 -0
  13. data/lib/sisimai/reason/userunknown.rb +2 -1
  14. data/lib/sisimai/version.rb +1 -1
  15. data/set-of-emails/maildir/bsd/README.md +52 -0
  16. data/set-of-emails/maildir/bsd/exchange2007-03.eml +1178 -0
  17. data/set-of-emails/maildir/bsd/postfix-22.eml +73 -0
  18. data/set-of-emails/maildir/bsd/postfix-23.eml +75 -0
  19. data/set-of-emails/maildir/bsd/postfix-24.eml +73 -0
  20. data/set-of-emails/maildir/bsd/postfix-25.eml +73 -0
  21. data/set-of-emails/maildir/bsd/postfix-26.eml +73 -0
  22. data/set-of-emails/maildir/bsd/postfix-27.eml +66 -0
  23. data/set-of-emails/maildir/bsd/qmail-10.eml +32 -0
  24. data/set-of-emails/maildir/bsd/qmail-11.eml +73 -0
  25. data/set-of-emails/maildir/bsd/qmail-12.eml +24 -0
  26. data/set-of-emails/maildir/bsd/rfc3464-28.eml +0 -0
  27. data/set-of-emails/maildir/bsd/rfc3464-30.eml +1173 -0
  28. data/set-of-emails/maildir/bsd/rfc3834-04.eml +29 -0
  29. data/set-of-emails/maildir/bsd/rfc3834-05.eml +29 -0
  30. data/set-of-emails/maildir/bsd/sendmail-41.eml +125 -0
  31. data/set-of-emails/maildir/bsd/us-amazonses-05.eml +73 -0
  32. data/set-of-emails/maildir/bsd/us-amazonses-06.eml +73 -0
  33. data/set-of-emails/maildir/bsd/us-amazonses-07.eml +73 -0
  34. data/set-of-emails/maildir/bsd/us-amazonses-08.eml +73 -0
  35. data/set-of-emails/maildir/dos/exchange2003-01.eml +31 -0
  36. data/set-of-emails/maildir/dos/exchange2007-01.eml +151 -0
  37. data/set-of-emails/maildir/mac/exchange2003-01.eml +1 -0
  38. data/set-of-emails/maildir/mac/exchange2007-01.eml +1 -10
  39. metadata +24 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05d5dfaa42ebfce199971de5fdfb142f919808e2
4
- data.tar.gz: 6a717982fc25ecd357cc4b72a5d4f400b9e05c9a
3
+ metadata.gz: 86487325ab861bea9bb3cb7a20682bde85aafb3c
4
+ data.tar.gz: 57a722c34477947dcf2d899c4b5ff3a3bcf76bc1
5
5
  SHA512:
6
- metadata.gz: 994d8b5dbce9175cca99fb3e47c5c467103a1dd0e36fe0f2e7754f4c44ebb6061171e3dfcb002874ccda24f8cdbb28e1033da4f123bea19c60d147ddf06ea72b
7
- data.tar.gz: df977c81396ae06119e05995a76a9a5e9d8e3fbaadff0102ec1a5c9274f9e5d64866f62b7caabb5684bb6dbc691a425a023206c79915f179112c87767797ae0f
6
+ metadata.gz: f0f428825f76e9746aacfe0db95eab9f9540cb85ebda8557a13794178c6932f9ebd578a7d13948c1a3d4f859fd77bcd36ffef9e00e89e3ca98cc3369f8409180
7
+ data.tar.gz: 632fb856aac2a29bfd99ba5a7db435d3c33fb6ed0b2b7259c6c299ef0c050eef42ef702e986a903c83ff77f92e7d76c2b2c6b3268c5fb97cf22bd458912d51f3
data/ANALYTICAL-PRECISION CHANGED
@@ -6,7 +6,7 @@ MTA::ApacheJames ........ 0/0006 0.0000 Java Apache Mail Enterprise Server
6
6
  MTA::Courier ............ 14/0016 0.8750 Courier MTA
7
7
  MTA::Domino ............. 6/0015 0.4000 IBM Domino Server
8
8
  MTA::Exchange2003 ....... 1/0051 0.0196 Microsoft Exchange Server 2003
9
- MTA::Exchange2007 ....... 4/0006 0.6667 Microsoft Exchange Server 2007
9
+ MTA::Exchange2007 ....... 5/0007 0.7143 Microsoft Exchange Server 2007
10
10
  MTA::Exim ............... 144/0174 0.8276 Exim
11
11
  MTA::IMailServer ........ 0/0045 0.0000 IPSWITCH IMail Server
12
12
  MTA::InterScanMSS ....... 0/0009 0.0000 Trend Micro InterScan Messaging Security Suite
@@ -17,8 +17,8 @@ MTA::McAfee ............. 0/0010 0.0000 McAfee Email Appliance
17
17
  MTA::MessagingServer .... 19/0022 0.8636 Oracle Communications Messaging Server
18
18
  MTA::Notes .............. 0/0012 0.0000 Lotus Notes
19
19
  MTA::OpenSMTPD .......... 5/0023 0.2174 OpenSMTPD
20
- MTA::Postfix ............ 165/0183 0.9016 Postfix
21
- MTA::Sendmail ........... 330/0252 1.0000 V8Sendmail: /usr/sbin/sendmail
20
+ MTA::Postfix ............ 171/0189 0.9048 Postfix
21
+ MTA::Sendmail ........... 331/0253 1.0000 V8Sendmail: /usr/sbin/sendmail
22
22
  MTA::SurfControl ........ 6/0008 0.7500 WebSense SurfControl
23
23
  MTA::V5sendmail ......... 0/0386 0.0000 Sendmail version 5
24
24
  MTA::X1 ................. 0/0007 0.0000 Unknown MTA #1
@@ -27,7 +27,7 @@ MTA::X3 ................. 0/0012 0.0000 Unknown MTA #3
27
27
  MTA::X4 ................. 0/0029 0.0000 Unknown MTA #4 qmail clones
28
28
  MTA::X5 ................. 3/0003 1.0000 Unknown MTA #5
29
29
  MTA::mFILTER ............ 0/0009 0.0000 Digital Arts m-FILTER
30
- MTA::qmail .............. 52/0078 0.6667 qmail
30
+ MTA::qmail .............. 52/0082 0.6341 qmail
31
31
  MSP::DE::EinsUndEins .... 0/0003 0.0000 1&1: http://www.1and1.de
32
32
  MSP::DE::GMX ............ 0/0010 0.0000 GMX: http://www.gmx.net
33
33
  MSP::JP::Biglobe ........ 5/0007 0.7143 BIGLOBE: http://www.biglobe.ne.jp
@@ -36,7 +36,7 @@ MSP::JP::KDDI ........... 6/0006 1.0000 au by KDDI: http://www.au.kddi.com
36
36
  MSP::RU::MailRu ......... 4/0014 0.2857 @mail.ru: https://mail.ru
37
37
  MSP::RU::Yandex ......... 4/0007 0.5714 Yandex.Mail: http://www.yandex.ru
38
38
  MSP::UK::MessageLabs .... 2/0002 1.0000 Symantec.cloud http://www.messagelabs.com
39
- MSP::US::AmazonSES ...... 18/0018 1.0000 Amazon SES(Sending): http://aws.amazon.com/ses/
39
+ MSP::US::AmazonSES ...... 22/0022 1.0000 Amazon SES(Sending): http://aws.amazon.com/ses/
40
40
  MSP::US::AmazonWorkMail . 8/0012 0.6667 Amazon WorkMail: https://aws.amazon.com/workmail/
41
41
  MSP::US::Aol ............ 18/0021 0.8571 Aol Mail: http://www.aol.com
42
42
  MSP::US::Bigfoot ........ 2/0002 1.0000 Bigfoot: http://www.bigfoot.com
@@ -50,8 +50,8 @@ MSP::US::Verizon ........ 3/0003 1.0000 Verizon Wireless: http://www.verizo
50
50
  MSP::US::Yahoo .......... 0/0009 0.0000 Yahoo! MAIL: https://www.yahoo.com
51
51
  MSP::US::Zoho ........... 0/0011 0.0000 Zoho Mail: https://www.zoho.com
52
52
  ARF ..................... 9/0050 0.1800 Abuse Feedback Reporting Format
53
- RFC3464 ................. 135/0276 0.4891 Fallback Module for MTAs
54
- RFC3834 ................. 0/0004 0.0000 Detector for auto replied message
53
+ RFC3464 ................. 136/0277 0.4910 Fallback Module for MTAs
54
+ RFC3834 ................. 0/0006 0.0000 Detector for auto replied message
55
55
  -------------------------------------------------------------------------------
56
- bounceHammer 2.7.13p3 1188/2159 0.5503
57
- Sisimai 4.18.1 2159/2159 1.0000
56
+ bounceHammer 2.7.13p3 1201/2178 0.5514
57
+ Sisimai 4.19.0 2178/2178 1.0000
data/Changes CHANGED
@@ -1,5 +1,13 @@
1
1
  Revision history for Ruby version of Sisimai
2
2
 
3
+ 4.19.0 Tue, 18 Oct 2016 14:19:10 +0900 (JST)
4
+ - Implement a callback feature at Sisimai.make and Sisimai.dump methods.
5
+ More imformation about the feature are available at the following pages:
6
+ - http://libsisimai.org/en/usage#callback
7
+ - http://libsisimai.org/ja/usage#callback
8
+ - Implement Sisimai.match() method: issue #52.
9
+ - Minor bug fix in Sisimai::MSP::US::AmazonSES.scan() method.
10
+
3
11
  4.18.1 Sun, 11 Sep 2016 20:05:20 +0900 (JST)
4
12
  - Fix bug in Sisimai::Mail::STDIN.read() method reported at issue #61.
5
13
  Thanks to @yaegassy.
data/README-JA.md CHANGED
@@ -127,6 +127,35 @@ puts Sisimai.dump('/path/to/mbox', delivered: true)
127
127
  [{"recipient": "kijitora@example.jp", "addresser": "shironeko@1jo.example.org", "feedbacktype": "", "action": "failed", "subject": "Nyaaaaan", "smtpcommand": "DATA", "diagnosticcode": "550 Unknown user kijitora@example.jp", "listid": "", "destination": "example.jp", "smtpagent": "Courier", "lhost": "1jo.example.org", "deliverystatus": "5.0.0", "timestamp": 1291954879, "messageid": "201012100421.oBA4LJFU042012@1jo.example.org", "diagnostictype": "SMTP", "timezoneoffset": "+0900", "reason": "filtered", "token": "ce999a4c869e3f5e4d8a77b2e310b23960fb32ab", "alias": "", "senderdomain": "1jo.example.org", "rhost": "mfsmax.example.jp"}, {"diagnostictype": "SMTP", "timezoneoffset": "+0900", "reason": "userunknown", "timestamp": 1381900535, "messageid": "E1C50F1B-1C83-4820-BC36-AC6FBFBE8568@example.org", "token": "9fe754876e9133aae5d20f0fd8dd7f05b4e9d9f0", "alias": "", "senderdomain": "example.org", "rhost": "mx.bouncehammer.jp", "action": "failed", "addresser": "kijitora@example.org", "recipient": "userunknown@bouncehammer.jp", "feedbacktype": "", "smtpcommand": "DATA", "subject": "バウンスメールのテスト(日本語)", "destination": "bouncehammer.jp", "listid": "", "diagnosticcode": "550 5.1.1 <userunknown@bouncehammer.jp>... User Unknown", "deliverystatus": "5.1.1", "lhost": "p0000-ipbfpfx00kyoto.kyoto.example.co.jp", "smtpagent": "Sendmail"}]
128
128
  ```
129
129
 
130
+ コールバック機能
131
+ ----------------
132
+ Sisimai 4.19.0から、`Sisimai.make()`と`Sisimai.dump()`にLamda(Procオブジェクト)
133
+ を引数`hook`に指定できるようになりました。`hook`に指定したコードによって処理さ
134
+ れた結果は`Sisimai::Data.catch`メソッドで得ることができます。
135
+
136
+ ```ruby
137
+ #! /usr/bin/env ruby
138
+ require 'sisimai'
139
+ callbackto = lambda do |v|
140
+ r = { 'x-mailer' => '' }
141
+
142
+ if cv = v['message'].match(/^X-Mailer:\s*(.+)$/)
143
+ r['x-mailer'] = cv[1]
144
+ end
145
+ return r
146
+ end
147
+
148
+ data = Sisimai.make('/path/to/mbox', hook: callbackto)
149
+ json = Sisimai.dump('/path/to/mbox', hook: callbackto)
150
+
151
+ puts data[0].catch['x-mailer'] # Apple Mail (2.1283)
152
+ ```
153
+
154
+ コールバック機能のより詳細な使い方は
155
+ [Sisimai | 解析方法 - コールバック機能](http://libsisimai.org/ja/usage/#callback)
156
+ をご覧ください。
157
+
158
+
130
159
  ワンライナーで
131
160
  --------------
132
161
 
@@ -148,8 +177,8 @@ Perl版Sisimaiとの違い
148
177
  | メール解析速度(1000通のメール) | 3.30秒 | 2.33秒 |
149
178
  | インストール方法 | gem install | cpanm |
150
179
  | 依存モジュール数(コアモジュールを除く) | 1モジュール | 2モジュール |
151
- | LOC:ソースコードの行数 | 11600行 | 8500行 |
152
- | テスト件数(spec/,t/,xt/ディレクトリ) | 97000 | 177000件 |
180
+ | LOC:ソースコードの行数 | 11700行 | 8600行 |
181
+ | テスト件数(spec/,t/,xt/ディレクトリ) | 103800 | 184100件 |
153
182
  | ライセンス | 二条項BSD | 二条項BSD |
154
183
  | 開発会社によるサポート契約 | 準備中 | 提供中 |
155
184
 
data/README.md CHANGED
@@ -126,6 +126,35 @@ puts Sisimai.dump('/path/to/mbox', delivered: true)
126
126
  [{"recipient": "kijitora@example.jp", "addresser": "shironeko@1jo.example.org", "feedbacktype": "", "action": "failed", "subject": "Nyaaaaan", "smtpcommand": "DATA", "diagnosticcode": "550 Unknown user kijitora@example.jp", "listid": "", "destination": "example.jp", "smtpagent": "Courier", "lhost": "1jo.example.org", "deliverystatus": "5.0.0", "timestamp": 1291954879, "messageid": "201012100421.oBA4LJFU042012@1jo.example.org", "diagnostictype": "SMTP", "timezoneoffset": "+0900", "reason": "filtered", "token": "ce999a4c869e3f5e4d8a77b2e310b23960fb32ab", "alias": "", "senderdomain": "1jo.example.org", "rhost": "mfsmax.example.jp"}, {"diagnostictype": "SMTP", "timezoneoffset": "+0900", "reason": "userunknown", "timestamp": 1381900535, "messageid": "E1C50F1B-1C83-4820-BC36-AC6FBFBE8568@example.org", "token": "9fe754876e9133aae5d20f0fd8dd7f05b4e9d9f0", "alias": "", "senderdomain": "example.org", "rhost": "mx.bouncehammer.jp", "action": "failed", "addresser": "kijitora@example.org", "recipient": "userunknown@bouncehammer.jp", "feedbacktype": "", "smtpcommand": "DATA", "subject": "バウンスメールのテスト(日本語)", "destination": "bouncehammer.jp", "listid": "", "diagnosticcode": "550 5.1.1 <userunknown@bouncehammer.jp>... User Unknown", "deliverystatus": "5.1.1", "lhost": "p0000-ipbfpfx00kyoto.kyoto.example.co.jp", "smtpagent": "Sendmail"}]
127
127
  ```
128
128
 
129
+ Callback Feature
130
+ ----------------
131
+ Beginning with Sisimai 4.19.0, `make()` and `dump()` methods of Sisimai accept
132
+ a Lambda (Proc object) in `hook` argument for setting a callback method and
133
+ getting the results generated by the method via `Sisimai::Data.catch` method.
134
+
135
+ ```ruby
136
+ #! /usr/bin/env ruby
137
+ require 'sisimai'
138
+ callbackto = lambda do |v|
139
+ r = { 'x-mailer' => '' }
140
+
141
+ if cv = v['message'].match(/^X-Mailer:\s*(.+)$/)
142
+ r['x-mailer'] = cv[1]
143
+ end
144
+ return r
145
+ end
146
+
147
+ data = Sisimai.make('/path/to/mbox', hook: callbackto)
148
+ json = Sisimai.dump('/path/to/mbox', hook: callbackto)
149
+
150
+ puts data[0].catch['x-mailer'] # Apple Mail (2.1283)
151
+ ```
152
+
153
+ More information about the callback feature is available at
154
+ [Sisimai | How To Parse - Callback](http://libsisimai.org/en/usage/#callback)
155
+ Page.
156
+
157
+
129
158
  One-Liner
130
159
  ---------
131
160
 
@@ -147,9 +176,9 @@ and bounceHammer are available at
147
176
  | Analytical precision ratio(2000 emails)[1] | 1.00 | 1.00 |
148
177
  | The speed of parsing email(1000 emails) | 3.30s | 2.33s |
149
178
  | How to install | gem install | cpanm |
150
- | Dependencies (Except core modules) | 1 modules | 2 modules |
151
- | LOC:Source lines of code | 11600 lines | 8500 lines |
152
- | The number of tests(spec/,t/,xt/) directory | 97000 tests | 177000 tests |
179
+ | Dependencies (Except core modules) | 1 module | 2 modules |
180
+ | LOC:Source lines of code | 11750 lines | 8600 lines |
181
+ | The number of tests(spec/,t/,xt/) directory | 103800 tests | 184100 tests |
153
182
  | License | BSD 2-Clause | BSD 2-Clause |
154
183
  | Support Contract provided by Developer | Coming soon | Available |
155
184
 
data/lib/sisimai.rb CHANGED
@@ -16,6 +16,7 @@ module Sisimai
16
16
  # @param [String] path Path to mbox or Maildir/
17
17
  # @param [Hash] argvs Parser options(delivered=false)
18
18
  # @options argvs [Boolean] delivered true: Include "delivered" reason
19
+ # @options argvs [Lambda] hook Lambda object to be called back
19
20
  # @return [Array] Parsed objects
20
21
  # @return [nil] nil if the argument was wrong or an empty array
21
22
  def make(path, **argvs)
@@ -24,17 +25,19 @@ module Sisimai
24
25
  require 'sisimai/mail'
25
26
  mail = Sisimai::Mail.new(path)
26
27
  list = []
27
- opts = argvs[:delivered] || false
28
28
 
29
29
  return nil unless mail
30
30
  require 'sisimai/data'
31
31
  require 'sisimai/message'
32
32
 
33
+ methodargv = { :delivered => argvs[:delivered] || false }
34
+ hookmethod = argvs[:hook] || nil
35
+
33
36
  while r = mail.read do
34
37
  # Read and parse each mail file
35
- mesg = Sisimai::Message.new(data: r)
38
+ mesg = Sisimai::Message.new(data: r, hook: hookmethod)
36
39
  next if mesg.void
37
- data = Sisimai::Data.make(data: mesg, delivered: opts)
40
+ data = Sisimai::Data.make(data: mesg, delivered: methodargv)
38
41
  next unless data
39
42
  list.concat(data) if data.size > 0
40
43
  end
@@ -47,18 +50,19 @@ module Sisimai
47
50
  # @param [String] path Path to mbox or Maildir/
48
51
  # @param [Hash] argvs Parser options
49
52
  # @options argvs [Integer] delivered true: Include "delivered" reason
53
+ # @options argvs [Lambda] hook Lambda object to be called back
50
54
  # @return [String] Parsed data as JSON text
51
55
  def dump(path, **argvs)
52
56
  return nil unless path
53
57
 
54
- parseddata = Sisimai.make(path, argvs) || []
58
+ nyaan = Sisimai.make(path, argvs) || []
55
59
  if RUBY_PLATFORM =~ /java/
56
60
  # java-based ruby environment like JRuby.
57
61
  require 'jrjackson'
58
- jsonstring = JrJackson::Json.dump(parseddata)
62
+ jsonstring = JrJackson::Json.dump(nyaan)
59
63
  else
60
64
  require 'oj'
61
- jsonstring = Oj.dump(parseddata, :mode => :compat)
65
+ jsonstring = Oj.dump(nyaan, :mode => :compat)
62
66
  end
63
67
  return jsonstring
64
68
  end
@@ -104,11 +108,20 @@ module Sisimai
104
108
  # Call .description() method of Sisimai::Reason::*
105
109
  r = 'Sisimai::Reason::' + e
106
110
  require r.gsub('::', '/').downcase
107
- table[r.to_sym] = Module.const_get(r).send(:description)
111
+ table[e.to_sym] = Module.const_get(r).send(:description)
108
112
  end
109
113
 
110
114
  return table
111
115
  end
116
+
117
+ # Try to match with message patterns
118
+ # @param [String] Error message text
119
+ # @return [String] Reason text
120
+ def match(argvs = '')
121
+ return nil if argvs.empty?
122
+ require 'sisimai/reason'
123
+ return Sisimai::Reason.match(argvs)
124
+ end
112
125
  end
113
126
  end
114
127
 
data/lib/sisimai/data.rb CHANGED
@@ -14,6 +14,7 @@ module Sisimai
14
14
  require 'sisimai/datetime'
15
15
 
16
16
  @@rwaccessors = [
17
+ :catch, # [?] Results generated by hook method
17
18
  :token, # [String] Message token/MD5 Hex digest value
18
19
  :lhost, # [String] local host name/Local MTA
19
20
  :rhost, # [String] Remote host name/Remote MTA
@@ -83,6 +84,7 @@ module Sisimai
83
84
  @timezoneoffset = argvs['timezoneoffset'] || '+0000'
84
85
  @lhost = argvs['lhost'] || ''
85
86
  @rhost = argvs['rhost'] || ''
87
+ @catch = argvs['catch'] || nil
86
88
  @reason = argvs['reason'] || ''
87
89
  @listid = argvs['listid'] || ''
88
90
  @subject = argvs['subject'] || ''
@@ -148,6 +150,7 @@ module Sisimai
148
150
  o = nil # Sisimai::Data Object
149
151
  r = nil # Reason text
150
152
  p = {
153
+ 'catch' => messageobj.catch || nil,
151
154
  'lhost' => e['lhost'] || '',
152
155
  'rhost' => e['rhost'] || '',
153
156
  'alias' => e['alias'] || '',
@@ -17,6 +17,7 @@ module Sisimai
17
17
  :header, # [Hash] Header part of a email
18
18
  :ds, # [Array] Parsed data by Sisimai::MTA::*
19
19
  :rfc822, # [Hash] Header part of the original message
20
+ :catch, # [?] The results returned by hook method
20
21
  ]
21
22
  @@rwaccessors.each { |e| attr_accessor e }
22
23
 
@@ -41,7 +42,10 @@ module Sisimai
41
42
  # Constructor of Sisimai::Message
42
43
  # @param [String] data Email text data
43
44
  # @param [Hash] argvs Module to be loaded
44
- # @options argvs [String] data Entire email message
45
+ # @options argvs [String] :data Entire email message
46
+ # @options argvs [Array] :load User defined MTA module list
47
+ # @options argvs [Array] :order The order of MTA modules
48
+ # @options argvs [Code] :hook Reference to callback method
45
49
  # @return [Sisimai::Message] Structured email data or Undef if each
46
50
  # value of the arguments are missing
47
51
  def initialize(data: '', **argvs)
@@ -50,9 +54,9 @@ module Sisimai
50
54
  email = data
51
55
  email = email.scrub('?')
52
56
  email = email.gsub("\r\n", "\n")
53
- methodargv = { 'data' => email }
57
+ methodargv = { 'data' => email, 'hook' => argvs[:hook] || nil }
54
58
 
55
- [:'load', :'order'].each do |e|
59
+ [:load, :order].each do |e|
56
60
  # Order of MTA, MSP modules
57
61
  next unless argvs.key?(e)
58
62
  next unless argvs[e].is_a? Array
@@ -68,6 +72,7 @@ module Sisimai
68
72
  @header = parameters['header']
69
73
  @ds = parameters['ds']
70
74
  @rfc822 = parameters['rfc822']
75
+ @catch = parameters['catch'] || nil
71
76
  end
72
77
 
73
78
  # Check whether the object has valid content or not
@@ -80,11 +85,22 @@ module Sisimai
80
85
  # Make data structure from the email message(a body part and headers)
81
86
  # @param [Hash] argvs Email data
82
87
  # @options argvs [String] data Entire email message
88
+ # @options argvs [Array] load User defined MTA module list
89
+ # @options argvs [Array] order The order of MTA modules
90
+ # @options argvs [Code] hook Reference to callback method
83
91
  # @return [Hash] Resolved data structure
84
92
  def self.make(argvs)
85
93
  email = argvs['data']
86
94
 
87
95
  processing = { 'from' => '', 'header' => {}, 'rfc822' => '', 'ds' => [] }
96
+ hookmethod = argvs['hook'] || nil
97
+ processing = {
98
+ 'from' => '', # From_ line
99
+ 'header' => {}, # Email header
100
+ 'rfc822' => '', # Original message part
101
+ 'ds' => [], # Parsed data, Delivery Status
102
+ 'catch' => nil, # Data parsed by callback method
103
+ }
88
104
  mtamodules = []
89
105
  extheaders = ExtHeaders
90
106
  tobeloaded = []
@@ -124,11 +140,11 @@ module Sisimai
124
140
  tobeloaded << e
125
141
  end
126
142
 
127
- # 0. Split email data to headers and a body part.
143
+ # 1. Split email data to headers and a body part.
128
144
  aftersplit = Sisimai::Message.divideup(email)
129
145
  return nil if aftersplit.empty?
130
146
 
131
- # 1. Convert email headers from text to hash reference
147
+ # 2. Convert email headers from text to hash reference
132
148
  headerargv['extheaders'] = extheaders
133
149
  headerargv['tryonfirst'] = []
134
150
  processing['from'] = aftersplit['from']
@@ -141,6 +157,7 @@ module Sisimai
141
157
 
142
158
  # 4. Rewrite message body for detecting the bounce reason
143
159
  methodargv = {
160
+ 'hook' => hookmethod,
144
161
  'mail' => processing,
145
162
  'body' => aftersplit['body'],
146
163
  'tryonfirst' => headerargv['tryonfirst'],
@@ -150,7 +167,8 @@ module Sisimai
150
167
 
151
168
  return nil unless bouncedata
152
169
  return nil if bouncedata.empty?
153
- processing['ds'] = bouncedata['ds']
170
+ processing['ds'] = bouncedata['ds']
171
+ processing['catch'] = bouncedata['catch']
154
172
 
155
173
  # 5. Rewrite headers of the original message in the body part
156
174
  rfc822part = bouncedata['rfc822']
@@ -396,6 +414,8 @@ module Sisimai
396
414
  def self.parse(argvs)
397
415
  mesgentity = argvs['mail']
398
416
  bodystring = argvs['body']
417
+ hookmethod = argvs['hook'] || nil
418
+ havacaught = nil
399
419
  tryonfirst = argvs['tryonfirst'] || []
400
420
  tobeloaded = argvs['tobeloaded'] || []
401
421
  mailheader = mesgentity['header']
@@ -450,6 +470,17 @@ module Sisimai
450
470
  end
451
471
  end
452
472
 
473
+ # Call the hook method
474
+ if hookmethod.is_a? Proc
475
+ # Execute hook method
476
+ begin
477
+ p = { 'headers' => mailheader, 'message' => bodystring }
478
+ havecaught = hookmethod.call(p)
479
+ rescue StandardError => ce
480
+ warn sprintf(" ***warning: Something is wrong in hook method :%s", ce.to_s)
481
+ end
482
+ end
483
+
453
484
  # EXPAND_FORWARDED_MESSAGE:
454
485
  # Check whether or not the message is a bounce mail.
455
486
  # Pre-Process email body if it is a forwarded bounce message.
@@ -537,6 +568,8 @@ module Sisimai
537
568
  break
538
569
  end
539
570
  end
571
+
572
+ scannedset['catch'] = havecaught if scannedset
540
573
  return scannedset
541
574
  end
542
575
 
data/lib/sisimai/mime.rb CHANGED
@@ -29,17 +29,17 @@ module Sisimai
29
29
  return false unless argv1
30
30
 
31
31
  argv1 = argv1.delete('"')
32
- parts = []
32
+ piece = []
33
33
  isnot = false
34
34
 
35
35
  if argv1 =~ /[ ]/
36
36
  # Multiple MIME-Encoded strings in a line
37
- parts = argv1.split(' ')
37
+ piece = argv1.split(' ')
38
38
  else
39
- parts << argv1
39
+ piece << argv1
40
40
  end
41
41
 
42
- parts.each do |e|
42
+ piece.each do |e|
43
43
  # Check all the string in the array
44
44
  next if e =~ /[ \t]*=[?][-_0-9A-Za-z]+[?][BbQq][?].+[?]=?[ \t]*\z/
45
45
  isnot = true
@@ -224,7 +224,7 @@ module Sisimai
224
224
  return nil unless argv1
225
225
  value = ''
226
226
 
227
- if cv = argv1.match(/\bboundary=([^ ]+)/)
227
+ if cv = argv1.match(/\bboundary=([^ ]+)/i)
228
228
  # Content-Type: multipart/mixed; boundary=Apple-Mail-5--931376066
229
229
  # Content-Type: multipart/report; report-type=delivery-status;
230
230
  # boundary="n6H9lKZh014511.1247824040/mx.example.jp"
@@ -10,12 +10,17 @@ module Sisimai
10
10
  require 'sisimai/rfc5322'
11
11
 
12
12
  # http://aws.amazon.com/ses/
13
+ ReE = { :'x-mailer' => %r/Amazon[ ]WorkMail/ }
13
14
  Re0 = {
14
15
  :from => %r/\AMAILER-DAEMON[@]email[-]bounces[.]amazonses[.]com\z/,
15
16
  :subject => %r/\ADelivery Status Notification [(]Failure[)]\z/,
16
17
  }
17
18
  Re1 = {
18
- :begin => %r/\AThe following message to [<]/,
19
+ :begin => %r/\A(?:
20
+ The[ ]following[ ]message[ ]to[ ][<]
21
+ |An[ ]error[ ]occurred[ ]while[ ]trying[ ]to[ ]deliver[ ]the[ ]mail[ ]
22
+ )
23
+ /x,
19
24
  :rfc822 => %r|\Acontent-type: message/rfc822\z|,
20
25
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
21
26
  }
@@ -30,7 +35,8 @@ module Sisimai
30
35
  # X-SenderID: Sendmail Sender-ID Filter v1.0.0 nijo.example.jp p7V3i843003008
31
36
  # X-Original-To: 000001321defbd2a-788e31c8-2be1-422f-a8d4-cf7765cc9ed7-000000@email-bounces.amazonses.com
32
37
  # X-AWS-Outgoing: 199.255.192.156
33
- def headerlist; return ['X-AWS-Outgoing']; end
38
+ # X-SES-Outgoing: 2016.10.12-54.240.27.6
39
+ def headerlist; return ['X-AWS-Outgoing', 'X-SES-Outgoing']; end
34
40
  def pattern; return Re0; end
35
41
 
36
42
  # Parse bounce messages from Amazon SES
@@ -47,7 +53,14 @@ module Sisimai
47
53
  def scan(mhead, mbody)
48
54
  return nil unless mhead
49
55
  return nil unless mbody
50
- return nil unless mhead['x-aws-outgoing']
56
+
57
+ match = 0
58
+ xmail = mhead['x-mailer'] || ''
59
+
60
+ return nil if mhead['x-mailer'] =~ ReE[:'x-mailer']
61
+ match += 1 if mhead['x-aws-outgoing']
62
+ match += 1 if mhead['x-ses-outgoing']
63
+ return nil if match == 0
51
64
 
52
65
  dscontents = [Sisimai::MSP.DELIVERYSTATUS]
53
66
  hasdivided = mbody.split("\n")
@@ -168,7 +181,7 @@ module Sisimai
168
181
  #
169
182
  # Reporting-MTA: dns; a192-79.smtp-out.amazonses.com
170
183
  #
171
- if cv = e.match(/\A[Rr]eporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
184
+ if cv = e.match(/\A[Rr]eporting-MTA:[ ]*[DNSdns]+;[ ]*(.+)\z/)
172
185
  # Reporting-MTA: dns; mx.example.jp
173
186
  next if connheader['lhost'].size > 0
174
187
  connheader['lhost'] = cv[1].downcase