sisimai 4.17.1-java → 4.17.2-java

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.

@@ -9,8 +9,10 @@ module Sisimai
9
9
  require 'sisimai/rfc5322'
10
10
 
11
11
  Re0 = {
12
- :subject => %r/Undeliverable:/,
13
- :received => %r/.+[.](?:outbound[.]protection|prod)[.]outlook[.]com\b/,
12
+ :'subject' => %r/Undeliverable:/,
13
+ :'received' => %r/.+[.](?:outbound[.]protection|prod)[.]outlook[.]com\b/,
14
+ :'message-id' => %r/.+[.](?:outbound[.]protection|prod)[.]outlook[.]com\b/,
15
+
14
16
  }
15
17
  Re1 = {
16
18
  :begin => %r{\A(?:
@@ -24,14 +26,31 @@ module Sisimai
24
26
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
25
27
  }
26
28
  CodeTable = {
27
- :'4.4.7' => 'expired',
28
- :'5.1.0' => 'rejected',
29
- :'5.1.1' => 'userunknown',
30
- :'5.1.10' => 'filtered',
31
- :'5.4.1' => 'networkerror',
32
- :'5.4.14' => 'networkerror',
33
- :'5.7.1' => 'rejected',
34
- :'5.7.133' => 'rejected',
29
+ # https://support.office.com/en-us/article/Email-non-delivery-reports-in-Office-365-51daa6b9-2e35-49c4-a0c9-df85bf8533c3
30
+ %r/\A4[.]4[.]7\z/ => 'expired',
31
+ %r/\A4[.]7[.]26\z/ => 'securityerror',
32
+ %r/\A4[.]7[.][56]\d\d\z/ => 'blocked',
33
+ %r/\A4[.]7[.]8[5-9]\d\z/ => 'blocked',
34
+ %r/\A5[.]1[.]0\z/ => 'rejected',
35
+ %r/\A5[.]4[.]1\z/ => 'norelaying',
36
+ %r/\A5[.]4[.]6\z/ => 'networkerror',
37
+ %r/\A5[.]6[.]11\z/ => 'contenterror',
38
+ %r/\A5[.]7[.]1\z/ => 'rejected',
39
+ %r/\A5[.]7[.]1[23]\z/ => 'rejected',
40
+ %r/\A5[.]7[.]124\z/ => 'rejected',
41
+ %r/\A5[.]7[.]13[3-6]\z/ => 'rejected',
42
+ %r/\A5[.]7[.]25\z/ => 'networkerror',
43
+ %r/\A5[.]7[.]50[1-3]\z/ => 'spamdetected',
44
+ %r/\A5[.]7[.]50[4-5]\z/ => 'filtered',
45
+ %r/\A5[.]7[.]50[6-7]\z/ => 'blocked',
46
+ %r/\A5[.]7[.]508\z/ => 'toomanyconn',
47
+ %r/\A5[.]7[.]509\z/ => 'securityerror',
48
+ %r/\A5[.]7[.]510\z/ => 'notaccept',
49
+ %r/\A5[.]7[.]511\z/ => 'rejected',
50
+ %r/\A5[.]7[.]512\z/ => 'securityerror',
51
+ %r/\A5[.]7[.]60[6-9]\z/ => 'blocked',
52
+ %r/\A5[.]7[.]6[1-4]\d\z/ => 'blocked',
53
+ %r/\A5[.]7[.]7[0-4]\d\z/ => 'toomanyconn',
35
54
  }
36
55
  Indicators = Sisimai::MSP.INDICATORS
37
56
 
@@ -83,6 +102,10 @@ module Sisimai
83
102
  match += 1 if mhead['x-ms-exchange-crosstenant-fromentityheader']
84
103
  match += 1 if mhead['x-ms-exchange-transport-crosstenantheadersstamped']
85
104
  match += 1 if mhead['received'].find { |a| a =~ Re0[:received] }
105
+ if mhead['message-id']
106
+ # Message-ID: <00000000-0000-0000-0000-000000000000@*.*.prod.outlook.com>
107
+ match += 1 if mhead['message-id'] =~ Re0[:'message-id']
108
+ end
86
109
  return nil if match < 2
87
110
 
88
111
  if mbody =~ /^Content-Transfer-Encoding: quoted-printable$/
@@ -233,7 +256,12 @@ module Sisimai
233
256
  end
234
257
 
235
258
  if e['status']
236
- e['reason'] = CodeTable[e['status'].to_sym] || ''
259
+ CodeTable.each_key do |f|
260
+ # Try to match with each key as a regular expression
261
+ next unless e['status'] =~ f
262
+ e['reason'] = CodeTable[f]
263
+ last
264
+ end
237
265
  end
238
266
  end
239
267
 
@@ -40,6 +40,7 @@ module Sisimai
40
40
  |domain[ ]does[ ]not[ ]exist:
41
41
  |domain[ ].+[ ]mismatches[ ]client[ ]ip
42
42
  |dns[ ]lookup[ ]failure:[ ].+[ ]try[ ]again[ ]later
43
+ |DNSBL:ATTRBL
43
44
  |Go[ ]away
44
45
  |hosts[ ]with[ ]dynamic[ ]ip
45
46
  |IP[ ]\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}[ ]is[ ]blocked[ ]by[ ]EarthLink # Earthlink
data/lib/sisimai/rhost.rb CHANGED
@@ -7,7 +7,8 @@ module Sisimai
7
7
  class << self
8
8
  # Imported from p5-Sisimail/lib/Sisimai/Rhost.pm
9
9
  RhostClass = {
10
- 'aspmx.l.google.com' => 'GoogleApps',
10
+ %r/\Aaspmx[.]l[.]google[.]com\z/ => 'GoogleApps',
11
+ %r/[.]protection[.]outlook[.]com\z/ => 'ExchangeOnline',
11
12
  }
12
13
 
13
14
  # Retrun the list of remote hosts Sisimai support
@@ -20,10 +21,20 @@ module Sisimai
20
21
  # @param [String] argvs Remote host name
21
22
  # @return [True,False] True: matched
22
23
  # False: did not match
23
- def match(host)
24
- return false unless host.is_a? ::String
25
- return true if RhostClass.key?(host.downcase)
26
- return false
24
+ def match(rhost)
25
+ return false unless rhost.is_a? ::String
26
+ return false if rhost.empty?
27
+
28
+ host0 = rhost.downcase
29
+ match = false
30
+
31
+ RhostClass.each_key do |e|
32
+ # Try to match with each key of RhostClass
33
+ next unless host0 =~ e
34
+ match = true
35
+ break
36
+ end
37
+ return match
27
38
  end
28
39
 
29
40
  # Detect the bounce reason from certain remote hosts
@@ -35,10 +46,19 @@ module Sisimai
35
46
  return argvs.reason if argvs.reason.size > 0
36
47
 
37
48
  remotehost = argvs.rhost.downcase
38
- modulename = 'Sisimai::Rhost::' + RhostClass[remotehost]
39
- rhostclass = modulename.gsub('::', '/').downcase
40
- require rhostclass
49
+ rhostclass = ''
50
+ reasontext = ''
51
+ modulename = ''
41
52
 
53
+ RhostClass.each_key do |e|
54
+ # Try to match with each key of $RhostClass
55
+ next unless remotehost =~ e
56
+ modulename = 'Sisimai::Rhost::' + RhostClass[e]
57
+ rhostclass = modulename.gsub('::', '/').downcase
58
+ break
59
+ end
60
+
61
+ require rhostclass
42
62
  reasontext = Module.const_get(modulename).get(argvs)
43
63
  return reasontext
44
64
  end
@@ -0,0 +1,268 @@
1
+ module Sisimai
2
+ module Rhost
3
+ # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Data
4
+ # object as an argument of get() method when the value of "rhost" of the object
5
+ # is "*.protection.outlook.com". This class is called only Sisimai::Data class.
6
+ module ExchangeOnline
7
+ class << self
8
+ # Imported from p5-Sisimail/lib/Sisimai/Rhost/ExchangeOnline.pm
9
+
10
+ # https://technet.microsoft.com/en-us/library/bb232118
11
+ CodeTable = {
12
+ %r/\A4[.]3[.]1\z/ => [
13
+ {
14
+ :reason => 'systemfull',
15
+ :regexp => %r/Insufficient system resources/,
16
+ },
17
+ ],
18
+ %r/\A4[.]3[.]2\z/ => [
19
+ {
20
+ :reason => 'notaccept',
21
+ :regexp => %r/System not accepting network messages/,
22
+ },
23
+ ],
24
+ %r/\A4[.]4[.][17]\z/ => [
25
+ {
26
+ :reason => 'expired',
27
+ :regexp => %r/(?:Connection[ ]timed[ ]out|Message[ ]expired)/x,
28
+ },
29
+ ],
30
+ %r/\A4[.]4[.]2\z/ => [
31
+ {
32
+ :reason => 'blocked',
33
+ :regexp => %r/Connection dropped/,
34
+ },
35
+ ],
36
+ %r/\A4[.]7[.]26\z/ => [
37
+ {
38
+ :reason => 'securityerror',
39
+ :regexp => %r/Access denied, a message sent over IPv6 .+ must pass either SPF or DKIM validation, this message is not signed/,
40
+ },
41
+ ],
42
+ %r/\A4[.]7[.][568]\d{2}\z/ => [
43
+ {
44
+ :reason => 'securityerror',
45
+ :regexp => %r/Access denied, please try again later/,
46
+ },
47
+ ],
48
+ %r/\A5[.]0[.]0\z/ => [
49
+ {
50
+ :reason => 'blocked',
51
+ :regexp => %r|HELO / EHLO requires domain address|,
52
+ },
53
+ ],
54
+ %r/\A5[.]1[.][07]\z/ => [
55
+ {
56
+ :reason => 'rejected',
57
+ :regexp => %r/(?:Sender[ ]denied|Invalid[ ]address)/x,
58
+ },
59
+ ],
60
+ %r/\A5[.]1[.][123]\z/ => [
61
+ {
62
+ :reason => 'userunknown',
63
+ :regexp => %r{(?:
64
+ Bad[ ]destination[ ]mailbox[ ]address
65
+ |Invalid[ ]X[.]400[ ]address
66
+ |Invalid[ ]recipient[ ]address
67
+ )
68
+ }x,
69
+ },
70
+ ],
71
+ %r/\A5[.]1[.]4\z/ => [
72
+ {
73
+ :reason => 'systemerror',
74
+ :regexp => %r/Destination mailbox address ambiguous/,
75
+ },
76
+ ],
77
+ %r/\A5[.]2[.]1\z/ => [
78
+ {
79
+ :reason => 'suspend',
80
+ :regexp => %r/Mailbox cannot be accessed/,
81
+ },
82
+ ],
83
+ %r/\A5[.]2[.]2\z/ => [
84
+ {
85
+ :reason => 'mailboxfull',
86
+ :regexp => %r/Mailbox full/,
87
+ },
88
+ ],
89
+ %r/\A5[.]2[.]3\z/ => [
90
+ {
91
+ :reason => 'exceedlimit',
92
+ :regexp => %r/Message too large/,
93
+ },
94
+ ],
95
+ %r/\A5[.]2[.]4\z/ => [
96
+ {
97
+ :reason => 'systemerror',
98
+ :regexp => %r/Mailing list expansion problem/,
99
+ },
100
+ ],
101
+ %r/\A5[.]3[.]3\z/ => [
102
+ {
103
+ :reason => 'systemfull',
104
+ :regexp => %r/Unrecognized command/,
105
+ },
106
+ ],
107
+ %r/\A5[.]3[.]4\z/ => [
108
+ {
109
+ :reason => 'mesgtoobig',
110
+ :regexp => %r/Message too big for system/,
111
+ },
112
+ ],
113
+ %r/\A5[.]3[.]5\z/ => [
114
+ {
115
+ :reason => 'systemerror',
116
+ :regexp => %r/System incorrectly configured/,
117
+ },
118
+ ],
119
+ %r/\A5[.]4[.][46]\z/ => [
120
+ {
121
+ :reason => 'networkerror',
122
+ :regexp => %r/(?:Invalid[ ]arguments|Routing[ ]loop[ ]detected)/x,
123
+ },
124
+ ],
125
+ %r/\A5[.]5[.]2\z/ => [
126
+ {
127
+ :reason => 'syntaxerror',
128
+ :regexp => %r/Send hello first/,
129
+ },
130
+ ],
131
+ %r/\A5[.]5[.]3\z/ => [
132
+ {
133
+ :reason => 'syntaxerror',
134
+ :regexp => %r/Too many recipients/,
135
+ },
136
+ ],
137
+ %r/\A5[.]5[.]4\z/ => [
138
+ {
139
+ :reason => 'filtered',
140
+ :regexp => %r/Invalid domain name/,
141
+ },
142
+ ],
143
+ %r/\A5[.]5[.]6\z/ => [
144
+ {
145
+ :reason => 'contenterror',
146
+ :regexp => %r/Invalid message content/,
147
+ },
148
+ ],
149
+ %r/\A5[.]7[.][13]\z/ => [
150
+ {
151
+ :reason => 'securityerror',
152
+ :regexp => %r/(?:Delivery[ ]not[ ]authorized|Not[ ]Authorized)/x,
153
+ },
154
+ ],
155
+ %r/\A5[.]7[.]1\z/ => [
156
+ {
157
+ :reason => 'securityerror',
158
+ :regexp => %r/(?:Delivery[ ]not[ ]authorized|Client[ ]was[ ]not[ ]authenticated)/x,
159
+ },
160
+ {
161
+ :reason => 'norelaying',
162
+ :regexp => %r/Unable to relay/,
163
+ },
164
+ ],
165
+ %r/\A5[.]7[.]25\z/ => [
166
+ {
167
+ :reason => 'securityerror',
168
+ :regexp => %r/Access denied, the sending IPv6 address .+ must have a reverse DNS record/,
169
+ },
170
+ ],
171
+ %r/\A5[.]7[.]50[1-3]\z/ => [
172
+ {
173
+ :reason => 'spamdetected',
174
+ :regexp => %r/Access[ ]denied,[ ](?:spam[ ]abuse[ ]detected|banned[ ]sender)/x,
175
+ },
176
+ ],
177
+ %r/\A5[.]7[.]50[457]\z/ => [
178
+ {
179
+ :reason => 'filtered',
180
+ :regexp => %r{(?>
181
+ Recipient[ ]address[ ]rejected:[ ]Access[ ]denied
182
+ |Access[ ]denied,[ ](?:banned[ ]recipient|rejected[ ]by[ ]recipient)
183
+ )
184
+ },
185
+ },
186
+ ],
187
+ %r/\A5[.]7[.]506\z/ => [
188
+ {
189
+ :reason => 'blocked',
190
+ :regexp => %r/Access Denied, Bad HELO/,
191
+ },
192
+ ],
193
+ %r/\A5[.]7[.]508\z/ => [
194
+ {
195
+ :reason => 'toomanyconn',
196
+ :regexp => %r/Access denied, .+ has exceeded permitted limits within .+ range/,
197
+ },
198
+ ],
199
+ %r/\A5[.]7[.]509\z/ => [
200
+ {
201
+ :reason => 'securityerror',
202
+ :regexp => %r/Access denied, sending domain .+ does not pass DMARC verification/,
203
+ },
204
+ ],
205
+ %r/\A5[.]7[.]510\z/ => [
206
+ {
207
+ :reason => 'notaccept',
208
+ :regexp => %r/Access denied, .+ does not accept email over IPv6/,
209
+ },
210
+ ],
211
+ %r/\A5[.]7[.]511\z/ => [
212
+ {
213
+ :reason => 'blocked',
214
+ :regexp => %r/Access denied, banned sender/,
215
+ },
216
+ ],
217
+ %r/\A5[.]7[.]512\z/ => [
218
+ {
219
+ :reason => 'contenterror',
220
+ :regexp => %r/Access denied, message must be RFC 5322 section 3[.]6[.]2 compliant/,
221
+ },
222
+ ],
223
+ %r/\A5[.]7[.]6\d{2}\z/ => [
224
+ {
225
+ :reason => 'blocked',
226
+ :regexp => %r/Access[ ]denied,[ ]banned[ ]sending[ ]IP[ ].+/,
227
+ },
228
+ ],
229
+ %r/\A5[.]7[.]7\d{2}\z/ => [
230
+ {
231
+ :reason => 'toomanyconn',
232
+ :regexp => %r/Access denied, tenant has exceeded threshold/,
233
+ },
234
+ ],
235
+ }
236
+
237
+ # Detect bounce reason from Google Apps
238
+ # @param [Sisimai::Data] argvs Parsed email object
239
+ # @return [String] The bounce reason for Exchange Online
240
+ # @see https://support.google.com/a/answer/3726730?hl=en
241
+ def get(argvs)
242
+ return nil unless argvs
243
+ return nil unless argvs.is_a? Sisimai::Data
244
+ return argvs.reason if argvs.reason.size > 0
245
+
246
+ statuscode = argvs.deliverystatus.sub(/\A\d[.](\d+[.]\d+)\z/, 'X.\1')
247
+ statusmesg = argvs.diagnosticcode
248
+ reasontext = ''
249
+
250
+ CodeTable.each_key do |e|
251
+ # Try to match with each regular expression of delivery status codes
252
+ next unless statuscode =~ e
253
+ Codetable[e].each do |f|
254
+ # Try to match with each regular expression of error messages
255
+ next unless statusmesg =~ f[:regexp]
256
+ reasontext = f[:reason]
257
+ break
258
+ end
259
+ end
260
+
261
+ return reasontext
262
+ end
263
+
264
+ end
265
+ end
266
+ end
267
+ end
268
+
@@ -6,7 +6,7 @@ module Sisimai
6
6
  module GoogleApps
7
7
  class << self
8
8
  # Imported from p5-Sisimail/lib/Sisimai/Rhost/GoogleApps.pm
9
- SMTPErrorSet = {
9
+ CodeTable = {
10
10
  :'X.1.1' => [
11
11
  {
12
12
  :reason => 'userunknown',
@@ -220,7 +220,7 @@ module Sisimai
220
220
  statuscode = argvs.deliverystatus.sub(/\A\d[.](\d+[.]\d+)\z/, 'X.\1')
221
221
  statusmesg = argvs.diagnosticcode
222
222
  reasontext = ''
223
- errortable = SMTPErrorSet[statuscode.to_sym] || []
223
+ errortable = CodeTable[statuscode.to_sym] || []
224
224
 
225
225
  errortable.each do |e|
226
226
  # Try to match
@@ -561,7 +561,7 @@ module Sisimai
561
561
  :'4.4.2' => 'networkerror', # Bad connection
562
562
  # :'4.4.3' => 'systemerror', # Directory server failure
563
563
  :'4.4.4' => 'networkerror', # Unable to route
564
- :'4.4.5' => 'toomanyconn', # Mail system congestion
564
+ :'4.4.5' => 'systemfull', # Mail system congestion
565
565
  :'4.4.6' => 'networkerror', # Routing loop detected
566
566
  :'4.4.7' => 'expired', # Delivery time expired
567
567
  # :'4.5.0' => 'networkerror', # Other or undefined protocol status
@@ -1,4 +1,4 @@
1
1
  # Define the version number of Sisimai
2
2
  module Sisimai
3
- VERSION = '4.17.1'
3
+ VERSION = '4.17.2'
4
4
  end
@@ -0,0 +1,73 @@
1
+ Return-Path: <>
2
+ Received: from nyaan.example.ed.jp (nyaan.example.ed.jp [198.51.100.222])
3
+ by aneyakoji.neko.example.co.jp (V8/cf) with ESMTP id t3BB0AAA00000
4
+ for <postmaster@neko.example.co.jp>; Thu, 29 Apr 2015 20:00:00 +0900
5
+ X-SenderID: Sendmail Sender-ID Filter v1.0.0 aneyakoji.neko.example.co.jp t3BB0AAA00000
6
+ Authentication-Results: aneyakoji.neko.example.co.jp; sender-id=none header.from=MAILER-DAEMON@nyaan.example.ed.jp
7
+ Received: from localhost (localhost)
8
+ by nyaan.example.ed.jp (V8/cf) id t3BB0AAA11111;
9
+ Thu, 29 Apr 2015 20:00:00 +0900
10
+ Date: Thu, 29 Apr 2015 20:00:00 +0900
11
+ From: Mail Delivery Subsystem <MAILER-DAEMON@nyaan.example.ed.jp>
12
+ Message-Id: <201505111100.t3BB0AAA11111@nyaan.example.ed.jp>
13
+ To: postmaster@nyaan.example.ed.jp
14
+ MIME-Version: 1.0
15
+ Content-Type: multipart/report; report-type=delivery-status;
16
+ boundary="t3BB0AAA11111.1400000000/nyaan.example.ed.jp"
17
+ Subject: Postmaster notify: see transcript for details
18
+ Auto-Submitted: auto-generated (postmaster-notification)
19
+
20
+ This is a MIME-encapsulated message
21
+
22
+ --t3BB0AAA11111.1400000000/nyaan.example.ed.jp
23
+
24
+ The original message was received at Thu, 29 Apr 2015 20:00:00 +0900
25
+ from localhost [127.0.0.1]
26
+ with id t3BB0AAA22222
27
+
28
+ ----- The following addresses had permanent fatal errors -----
29
+ <kijitora@example.com>
30
+ (reason: 550 5.7.606 Access denied, banned sending IP [198.51.100.222]. To request removal from this list plea...tions. For more information please go to http://go.microsoft.com/fwlink/?LinkID=526655 (AS16012609))
31
+
32
+ ----- Transcript of session follows -----
33
+ ... while talking to example.com.mail.protection.outlook.com.:
34
+ >>> DATA
35
+ <<< 550 5.7.606 Access denied, banned sending IP [198.51.100.222]. To request removal from this list please visit https://sender.office.com/ and follow the directions. For more information please go to http://go.microsoft.com/fwlink/?LinkID=526655 (AS16012609)
36
+ 550 5.1.1 <kijitora@example.com>... User unknown
37
+ <<< 503 5.5.2 Need rcpt command
38
+
39
+ --t3BB0AAA11111.1400000000/nyaan.example.ed.jp
40
+ Content-Type: message/delivery-status
41
+
42
+ Reporting-MTA: dns; nyaan.example.ed.jp
43
+ Received-From-MTA: DNS; localhost
44
+ Arrival-Date: Thu, 29 Apr 2015 20:00:00 +0900
45
+
46
+ Final-Recipient: RFC822; kijitora@example.com
47
+ Action: failed
48
+ Status: 5.7.606
49
+ Remote-MTA: DNS; example.com.mail.protection.outlook.com
50
+ Diagnostic-Code: SMTP; 550 5.7.606 Access denied, banned sending IP [198.51.100.222]. To request removal from this list please visit https://sender.office.com/ and follow the directions. For more information please go to http://go.microsoft.com/fwlink/?LinkID=526655 (AS16012609)
51
+ Last-Attempt-Date: Thu, 29 Apr 2015 20:00:00 +0900
52
+
53
+ --t3BB0AAA11111.1400000000/nyaan.example.ed.jp
54
+ Content-Type: text/rfc822-headers
55
+
56
+ Return-Path: <root@nyaan.example.ed.jp>
57
+ Received: from nyaan.example.ed.jp (localhost [127.0.0.1])
58
+ by nyaan.example.ed.jp (V8/cf) with ESMTP id t3BB0AAA22222
59
+ for <kijitora@example.com>; Thu, 29 Apr 2015 20:00:00 +0900
60
+ Received: (from root@localhost)
61
+ by nyaan.example.ed.jp (8.15.2/8.15.2/Submit) id t3BB0AAA23232;
62
+ Thu, 29 Apr 2015 20:00:00 +0900
63
+ Date: Thu, 29 Apr 2015 20:00:00 +0900
64
+ To: kijitora@example.com
65
+ Subject: Nyaan
66
+ From: Shironeko <shironeko@example.org>
67
+ Message-Id: <00000000000000000000000000000000000000000000000@example.net>
68
+ Content-Type: text/plain; charset="iso-2022-jp"
69
+ Content-Transfer-Encoding: 7bit
70
+ MIME-Version: 1.0
71
+
72
+ --t3BB0AAA11111.1400000000/nyaan.example.ed.jp--
73
+