sisimai 4.16.0-java → 4.17.0-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.

Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/ANALYTICAL-PRECISION +7 -7
  4. data/Changes +15 -0
  5. data/Makefile +1 -1
  6. data/README.md +30 -28
  7. data/lib/sisimai.rb +20 -1
  8. data/lib/sisimai/address.rb +28 -9
  9. data/lib/sisimai/arf.rb +37 -46
  10. data/lib/sisimai/data.rb +67 -43
  11. data/lib/sisimai/datetime.rb +210 -210
  12. data/lib/sisimai/mda.rb +30 -30
  13. data/lib/sisimai/message.rb +3 -5
  14. data/lib/sisimai/msp/de/einsundeins.rb +14 -42
  15. data/lib/sisimai/msp/de/gmx.rb +17 -44
  16. data/lib/sisimai/msp/jp/biglobe.rb +15 -44
  17. data/lib/sisimai/msp/jp/ezweb.rb +20 -50
  18. data/lib/sisimai/msp/jp/kddi.rb +16 -43
  19. data/lib/sisimai/msp/ru/mailru.rb +20 -48
  20. data/lib/sisimai/msp/ru/yandex.rb +16 -50
  21. data/lib/sisimai/msp/uk/messagelabs.rb +17 -51
  22. data/lib/sisimai/msp/us/amazonses.rb +18 -40
  23. data/lib/sisimai/msp/us/amazonworkmail.rb +17 -35
  24. data/lib/sisimai/msp/us/aol.rb +17 -41
  25. data/lib/sisimai/msp/us/bigfoot.rb +15 -48
  26. data/lib/sisimai/msp/us/facebook.rb +63 -90
  27. data/lib/sisimai/msp/us/google.rb +15 -44
  28. data/lib/sisimai/msp/us/office365.rb +21 -46
  29. data/lib/sisimai/msp/us/outlook.rb +17 -50
  30. data/lib/sisimai/msp/us/receivingses.rb +20 -43
  31. data/lib/sisimai/msp/us/sendgrid.rb +13 -37
  32. data/lib/sisimai/msp/us/verizon.rb +30 -74
  33. data/lib/sisimai/msp/us/yahoo.rb +12 -40
  34. data/lib/sisimai/msp/us/zoho.rb +14 -42
  35. data/lib/sisimai/mta/activehunter.rb +11 -40
  36. data/lib/sisimai/mta/apachejames.rb +18 -40
  37. data/lib/sisimai/mta/courier.rb +20 -57
  38. data/lib/sisimai/mta/domino.rb +24 -56
  39. data/lib/sisimai/mta/exchange.rb +26 -54
  40. data/lib/sisimai/mta/exim.rb +20 -39
  41. data/lib/sisimai/mta/imailserver.rb +26 -71
  42. data/lib/sisimai/mta/interscanmss.rb +26 -44
  43. data/lib/sisimai/mta/mailfoundry.rb +12 -42
  44. data/lib/sisimai/mta/mailmarshalsmtp.rb +13 -43
  45. data/lib/sisimai/mta/mcafee.rb +17 -46
  46. data/lib/sisimai/mta/messagingserver.rb +14 -47
  47. data/lib/sisimai/mta/mfilter.rb +12 -35
  48. data/lib/sisimai/mta/mxlogic.rb +18 -42
  49. data/lib/sisimai/mta/notes.rb +22 -45
  50. data/lib/sisimai/mta/opensmtpd.rb +18 -48
  51. data/lib/sisimai/mta/postfix.rb +15 -45
  52. data/lib/sisimai/mta/qmail.rb +32 -60
  53. data/lib/sisimai/mta/sendmail.rb +13 -38
  54. data/lib/sisimai/mta/surfcontrol.rb +15 -44
  55. data/lib/sisimai/mta/userdefined.rb +14 -30
  56. data/lib/sisimai/mta/v5sendmail.rb +18 -40
  57. data/lib/sisimai/mta/x1.rb +12 -41
  58. data/lib/sisimai/mta/x2.rb +12 -41
  59. data/lib/sisimai/mta/x3.rb +12 -39
  60. data/lib/sisimai/mta/x4.rb +33 -66
  61. data/lib/sisimai/mta/x5.rb +15 -42
  62. data/lib/sisimai/reason.rb +8 -71
  63. data/lib/sisimai/reason/blocked.rb +3 -0
  64. data/lib/sisimai/reason/contenterror.rb +3 -0
  65. data/lib/sisimai/reason/delivered.rb +27 -0
  66. data/lib/sisimai/reason/exceedlimit.rb +3 -0
  67. data/lib/sisimai/reason/expired.rb +3 -0
  68. data/lib/sisimai/reason/feedback.rb +18 -0
  69. data/lib/sisimai/reason/filtered.rb +4 -0
  70. data/lib/sisimai/reason/hasmoved.rb +3 -0
  71. data/lib/sisimai/reason/hostunknown.rb +3 -0
  72. data/lib/sisimai/reason/mailboxfull.rb +3 -0
  73. data/lib/sisimai/reason/mailererror.rb +3 -0
  74. data/lib/sisimai/reason/mesgtoobig.rb +3 -0
  75. data/lib/sisimai/reason/networkerror.rb +3 -0
  76. data/lib/sisimai/reason/norelaying.rb +3 -0
  77. data/lib/sisimai/reason/notaccept.rb +3 -0
  78. data/lib/sisimai/reason/onhold.rb +3 -0
  79. data/lib/sisimai/reason/rejected.rb +3 -0
  80. data/lib/sisimai/reason/securityerror.rb +3 -0
  81. data/lib/sisimai/reason/spamdetected.rb +3 -0
  82. data/lib/sisimai/reason/suspend.rb +3 -0
  83. data/lib/sisimai/reason/syntaxerror.rb +41 -0
  84. data/lib/sisimai/reason/systemerror.rb +3 -0
  85. data/lib/sisimai/reason/systemfull.rb +3 -0
  86. data/lib/sisimai/reason/toomanyconn.rb +3 -0
  87. data/lib/sisimai/reason/undefined.rb +18 -0
  88. data/lib/sisimai/reason/userunknown.rb +3 -0
  89. data/lib/sisimai/reason/vacation.rb +18 -0
  90. data/lib/sisimai/rfc3464.rb +15 -40
  91. data/lib/sisimai/rfc3834.rb +1 -10
  92. data/lib/sisimai/rfc5322.rb +57 -19
  93. data/lib/sisimai/rhost/googleapps.rb +82 -82
  94. data/lib/sisimai/smtp/reply.rb +2 -1
  95. data/lib/sisimai/smtp/status.rb +154 -152
  96. data/lib/sisimai/string.rb +2 -3
  97. data/lib/sisimai/version.rb +1 -1
  98. data/set-of-emails/maildir/bsd/rfc3464-29.eml +60 -0
  99. data/set-of-emails/maildir/bsd/us-amazonworkmail-06.eml +156 -0
  100. data/set-of-emails/maildir/bsd/us-amazonworkmail-07.eml +158 -0
  101. data/set-of-emails/maildir/bsd/us-google-15.eml +97 -0
  102. data/set-of-emails/maildir/bsd/us-google-16.eml +99 -0
  103. data/set-of-emails/maildir/bsd/us-google-17.eml +104 -0
  104. data/set-of-emails/maildir/dos/apachejames-01.eml +4 -4
  105. data/set-of-emails/maildir/dos/us-amazonworkmail-01.eml +156 -0
  106. data/set-of-emails/maildir/dos/us-office365-01.eml +102 -0
  107. data/set-of-emails/maildir/mac/apachejames-01.eml +1 -9
  108. data/set-of-emails/maildir/mac/us-amazonworkmail-01.eml +1 -7
  109. data/set-of-emails/maildir/mac/us-office365-01.eml +1 -4
  110. metadata +17 -2
@@ -55,21 +55,21 @@ module Sisimai
55
55
  ReSMTP = {
56
56
  # Error text regular expressions which defined in qmail-remote.c
57
57
  # qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
58
- 'conn' => %r/(?:Error:)?Connected[ ]to[ ].+[ ]but[ ]greeting[ ]failed[.]/x,
58
+ conn: %r/(?:Error:)?Connected[ ]to[ ].+[ ]but[ ]greeting[ ]failed[.]/x,
59
59
  # qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
60
- 'ehlo' => %r/(?:Error:)?Connected[ ]to[ ].+[ ]but[ ]my[ ]name[ ]was[ ]rejected[.]/x,
60
+ ehlo: %r/(?:Error:)?Connected[ ]to[ ].+[ ]but[ ]my[ ]name[ ]was[ ]rejected[.]/x,
61
61
  # qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
62
62
  # reason = rejected
63
- 'mail' => %r/(?:Error:)?Connected[ ]to[ ].+[ ]but[ ]sender[ ]was[ ]rejected[.]/x,
63
+ mail: %r/(?:Error:)?Connected[ ]to[ ].+[ ]but[ ]sender[ ]was[ ]rejected[.]/x,
64
64
  # qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
65
65
  # qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
66
66
  # reason = userunknown
67
- 'rcpt' => %r/(?:Error:)?.+[ ]does[ ]not[ ]like[ ]recipient[.]/x,
67
+ rcpt: %r/(?:Error:)?.+[ ]does[ ]not[ ]like[ ]recipient[.]/x,
68
68
  # qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
69
69
  # qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
70
70
  # qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
71
71
  # qmail-remote.c:272| if (code >= 400) quit("Z"," failed after I sent the message");
72
- 'data' => %r{(?:
72
+ data: %r{(?:
73
73
  (?:Error:)?.+[ ]failed[ ]on[ ]DATA[ ]command[.]
74
74
  |(?:Error:)?.+[ ]failed[ ]after[ ]I[ ]sent[ ]the[ ]message[.]
75
75
  )
@@ -84,10 +84,10 @@ module Sisimai
84
84
  }x
85
85
  # qmail-ldap-1.03-20040101.patch:19817 - 19866
86
86
  ReLDAP = {
87
- 'suspend' => %r/Mailaddress is administrative?le?y disabled/, # 5.2.1
88
- 'userunknown' => %r/[Ss]orry, no mailbox here by that name/, # 5.1.1
89
- 'exceedlimit' => %r/The message exeeded the maximum size the user accepts/, # 5.2.3
90
- 'systemerror' => %r{(?>
87
+ suspend: %r/Mailaddress is administrative?le?y disabled/, # 5.2.1
88
+ userunknown: %r/[Ss]orry, no mailbox here by that name/, # 5.1.1
89
+ exceedlimit: %r/The message exeeded the maximum size the user accepts/, # 5.2.3
90
+ systemerror: %r{(?>
91
91
  Automatic[ ]homedir[ ]creator[ ]crashed # 4.3.0
92
92
  |Illegal[ ]value[ ]in[ ]LDAP[ ]attribute # 5.3.5
93
93
  |LDAP[ ]attribute[ ]is[ ]not[ ]given[ ]but[ ]mandatory # 5.3.5
@@ -115,40 +115,36 @@ module Sisimai
115
115
  ReFailure = {
116
116
  # qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
117
117
  # qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
118
- 'userunknown' => %r{(?:
118
+ userunknown: %r{(?:
119
119
  no[ ]mailbox[ ]here[ ]by[ ]that[ ]name
120
120
  |[ ]does[ ]not[ ]like[ ]recipient[.]
121
121
  )
122
122
  }x,
123
123
  # error_str.c:192| X(EDQUOT,"disk quota exceeded")
124
- 'mailboxfull' => %r/disk[ ]quota[ ]exceeded/x,
124
+ mailboxfull: %r/disk[ ]quota[ ]exceeded/x,
125
125
  # qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
126
126
  # qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
127
- 'mesgtoobig' => %r/Message[ ]size[ ]exceeds[ ]fixed[ ]maximum[ ]message[ ]size:/x,
127
+ mesgtoobig: %r/Message[ ]size[ ]exceeds[ ]fixed[ ]maximum[ ]message[ ]size:/x,
128
128
  # qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
129
129
  # qmail-remote.c:78| Sorry, I couldn't find any host named ");
130
- 'hostunknown' => %r/\ASorry[,][ ]I[ ]couldn[']t[ ]find[ ]any[ ]host[ ]/x,
131
- 'systemerror' => %r{(?>
130
+ hostunknown: %r/\ASorry[,][ ]I[ ]couldn[']t[ ]find[ ]any[ ]host[ ]/x,
131
+ systemerror: %r{(?>
132
132
  bad[ ]interpreter:[ ]No[ ]such[ ]file[ ]or[ ]directory
133
133
  |system[ ]error
134
134
  |Unable[ ]to\b
135
135
  )
136
136
  }x,
137
- 'networkerror' => %r{Sorry(?:
137
+ networkerror: %r{Sorry(?:
138
138
  [,][ ]I[ ]wasn[']t[ ]able[ ]to[ ]establish[ ]an[ ]SMTP[ ]connection
139
139
  |[,][ ]I[ ]couldn[']t[ ]find[ ]a[ ]mail[ ]exchanger[ ]or[ ]IP[ ]address
140
140
  |[.][ ]Although[ ]I[']m[ ]listed[ ]as[ ]a[ ]best[-]preference[ ]MX[ ]or[ ]A[ ]for[ ]that[ ]host
141
141
  )
142
142
  }x,
143
- 'systemfull' => %r/Requested action not taken: mailbox unavailable [(]not enough free space[)]/,
143
+ systemfull: %r/Requested action not taken: mailbox unavailable [(]not enough free space[)]/,
144
144
  }
145
-
146
145
  # qmail-send.c:922| ... (&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
147
- ReDelayed = %r/this[ ]message[ ]has[ ]been[ ]in[ ]the[ ]queue[ ]too[ ]long[.]\z/x
148
-
146
+ ReDelayed = %r/this[ ]message[ ]has[ ]been[ ]in[ ]the[ ]queue[ ]too[ ]long[.]\z/x
149
147
  Indicators = Sisimai::MTA.INDICATORS
150
- LongFields = Sisimai::RFC5322.LONGFIELDS
151
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
152
148
 
153
149
  def description; return 'Unknown MTA #4'; end
154
150
  def smtpagent; return 'X4'; end
@@ -179,11 +175,10 @@ module Sisimai
179
175
  match += 1 if mhead['received'].find { |a| a =~ Re0[:received] }
180
176
  return nil if match == 0
181
177
 
182
- dscontents = []; dscontents << Sisimai::MTA.DELIVERYSTATUS
178
+ dscontents = [Sisimai::MTA.DELIVERYSTATUS]
183
179
  hasdivided = mbody.split("\n")
184
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
185
- rfc822part = '' # (String) message/rfc822-headers part
186
- previousfn = '' # (String) Previous field name
180
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
181
+ blanklines = 0 # (Integer) The number of blank lines
187
182
  readcursor = 0 # (Integer) Points the current cursor position
188
183
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
189
184
  v = nil
@@ -192,7 +187,7 @@ module Sisimai
192
187
  if readcursor == 0
193
188
  # Beginning of the bounce message or delivery status part
194
189
  if e =~ Re1[:begin]
195
- readcursor |= Indicators[:'deliverystatus']
190
+ readcursor |= Indicators[:deliverystatus]
196
191
  next
197
192
  end
198
193
  end
@@ -207,30 +202,16 @@ module Sisimai
207
202
 
208
203
  if readcursor & Indicators[:'message-rfc822'] > 0
209
204
  # After "message/rfc822"
210
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
211
- # Get required headers only
212
- lhs = cv[1].downcase
213
- previousfn = ''
214
- next unless RFC822Head.key?(lhs)
215
-
216
- previousfn = lhs
217
- rfc822part += e + "\n"
218
-
219
- elsif e =~ /\A[ \t]+/
220
- # Continued line from the previous line
221
- next if rfc822next[previousfn]
222
- rfc822part += e + "\n" if LongFields.key?(previousfn)
223
-
224
- else
225
- # Check the end of headers in rfc822 part
226
- next unless LongFields.key?(previousfn)
227
- next unless e.empty?
228
- rfc822next[previousfn] = true
205
+ if e.empty?
206
+ blanklines += 1
207
+ break if blanklines > 1
208
+ next
229
209
  end
210
+ rfc822list << e
230
211
 
231
212
  else
232
213
  # Before "message/rfc822"
233
- next if readcursor & Indicators[:'deliverystatus'] == 0
214
+ next if readcursor & Indicators[:deliverystatus] == 0
234
215
  next if e.empty?
235
216
 
236
217
  # <kijitora@example.jp>:
@@ -266,23 +247,12 @@ module Sisimai
266
247
  end
267
248
  end
268
249
  end
269
-
270
250
  end
271
-
272
251
  return nil if recipients == 0
273
252
  require 'sisimai/string'
274
- require 'sisimai/smtp/status'
275
253
 
276
254
  dscontents.map do |e|
277
- e['agent'] = Sisimai::MTA::X4.smtpagent
278
-
279
- if mhead['received'].size > 0
280
- # Get localhost and remote host name from Received header.
281
- r0 = mhead['received']
282
- %w|lhost rhost|.each { |a| e[a] ||= '' }
283
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
284
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
285
- end
255
+ e['agent'] = Sisimai::MTA::X4.smtpagent
286
256
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
287
257
 
288
258
  unless e['command']
@@ -290,7 +260,7 @@ module Sisimai
290
260
  ReSMTP.each_key do |r|
291
261
  # Verify each regular expression of SMTP commands
292
262
  next unless e['diagnosis'] =~ ReSMTP[r]
293
- e['command'] = r.upcase
263
+ e['command'] = r.to_s.upcase
294
264
  break
295
265
  end
296
266
 
@@ -325,12 +295,12 @@ module Sisimai
325
295
  if e['alterrors']
326
296
  # Check the value of "alterrors"
327
297
  next unless e['alterrors'] =~ ReFailure[r]
328
- e['reason'] = r
298
+ e['reason'] = r.to_s
329
299
  end
330
300
  break if e['reason']
331
301
 
332
302
  next unless e['diagnosis'] =~ ReFailure[r]
333
- e['reason'] = r
303
+ e['reason'] = r.to_s
334
304
  break
335
305
  end
336
306
 
@@ -338,7 +308,7 @@ module Sisimai
338
308
  ReLDAP.each_key do |r|
339
309
  # Verify each regular expression of LDAP errors
340
310
  next unless e['diagnosis'] =~ ReLDAP[r]
341
- e['reason'] = r
311
+ e['reason'] = r.to_s
342
312
  break
343
313
  end
344
314
  end
@@ -348,13 +318,10 @@ module Sisimai
348
318
  end
349
319
  end
350
320
  end
351
-
352
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
353
- e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
354
- e['action'] = 'failed' if e['status'] =~ /\A[45]/
355
321
  e.each_key { |a| e[a] ||= '' }
356
322
  end
357
323
 
324
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
358
325
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
359
326
  end
360
327
 
@@ -18,8 +18,6 @@ module Sisimai
18
18
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
19
19
  }
20
20
  Indicators = Sisimai::MTA.INDICATORS
21
- LongFields = Sisimai::RFC5322.LONGFIELDS
22
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
23
21
 
24
22
  def description; return 'Unknown MTA #5'; end
25
23
  def smtpagent; return 'X5'; end
@@ -64,24 +62,24 @@ module Sisimai
64
62
  end
65
63
  return nil if match < 2
66
64
 
67
- dscontents = []; dscontents << Sisimai::MTA.DELIVERYSTATUS
65
+ dscontents = [Sisimai::MTA.DELIVERYSTATUS]
68
66
  hasdivided = mbody.split("\n")
69
67
  havepassed = ['']
70
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
71
- rfc822part = '' # (String) message/rfc822-headers part
72
- previousfn = '' # (String) Previous field name
68
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
69
+ blanklines = 0 # (Integer) The number of blank lines
73
70
  readcursor = 0 # (Integer) Points the current cursor position
74
71
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
75
72
  v = nil
76
73
 
77
74
  hasdivided.each do |e|
78
75
  # Save the current line for the next loop
79
- havepassed << e; p = havepassed[-2]
76
+ havepassed << e
77
+ p = havepassed[-2]
80
78
 
81
79
  if readcursor == 0
82
80
  # Beginning of the bounce message or delivery status part
83
81
  if e =~ Re1[:begin]
84
- readcursor |= Indicators[:'deliverystatus']
82
+ readcursor |= Indicators[:deliverystatus]
85
83
  next
86
84
  end
87
85
  end
@@ -110,7 +108,7 @@ module Sisimai
110
108
  recipients += 1
111
109
 
112
110
  elsif cv = e.match(/\A[Xx]-[Aa]ctual-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/) ||
113
- cv = e.match(/\A[Oo]riginal-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
111
+ e.match(/\A[Oo]riginal-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
114
112
  # X-Actual-Recipient: RFC822; kijitora@example.co.jp
115
113
  # Original-Recipient: rfc822;kijitora@example.co.jp
116
114
  v['alias'] = cv[1]
@@ -154,50 +152,25 @@ module Sisimai
154
152
  next if recipients == 0
155
153
  next if readcursor & Indicators['deliverystatus'] == 0
156
154
 
157
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
158
- # Get required headers only
159
- lhs = cv[1].downcase
160
- previousfn = ''
161
- next unless RFC822Head.key?(lhs)
162
-
163
- previousfn = lhs
164
- rfc822part += e + "\n"
165
-
166
- elsif e =~ /\A[ \t]+/
167
- # Continued line from the previous line
168
- next if rfc822next[previousfn]
169
- rfc822part += e + "\n" if LongFields.key?(previousfn)
170
-
171
- else
172
- # Check the end of headers in rfc822 part
173
- next unless LongFields.key?(previousfn)
174
- next unless e.empty?
175
- rfc822next[previousfn] = true
155
+ if e.empty?
156
+ blanklines += 1
157
+ break if blanklines > 1
158
+ next
176
159
  end
160
+ rfc822list << e
161
+
177
162
  end
178
163
  end
179
-
180
164
  return nil if recipients == 0
181
165
  require 'sisimai/string'
182
- require 'sisimai/smtp/status'
183
166
 
184
167
  dscontents.map do |e|
185
- e['agent'] = Sisimai::MTA::X5.smtpagent
186
-
187
- if mhead['received'].size > 0
188
- # Get localhost and remote host name from Received header.
189
- r0 = mhead['received']
190
- %w|lhost rhost|.each { |a| e[a] ||= '' }
191
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
192
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
193
- end
168
+ e['agent'] = Sisimai::MTA::X5.smtpagent
194
169
  e['diagnosis'] ||= Sisimai::String.sweep(e['diagnosis'])
195
- e['status'] ||= Sisimai::SMTP::Status.find(e['diagnosis'])
196
- e['spec'] ||= e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
197
- e['action'] ||= 'failed' if e['status'] =~ /\A[45]/
198
170
  e.each_key { |a| e[a] ||= '' }
199
171
  end
200
172
 
173
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
201
174
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
202
175
  end
203
176
 
@@ -19,13 +19,13 @@ module Sisimai
19
19
  Blocked ContentError ExceedLimit Expired Filtered HasMoved HostUnknown
20
20
  MailboxFull MailerError MesgTooBig NetworkError NotAccept OnHold
21
21
  Rejected NoRelaying SpamDetected SecurityError Suspend SystemError
22
- SystemFull TooManyConn UserUnknown
22
+ SystemFull TooManyConn UserUnknown SyntaxError
23
23
  ]
24
24
  end
25
25
 
26
26
  # Detect the bounce reason
27
27
  # @param [Sisimai::Data] argvs Parsed email object
28
- # @return [String, Undef] Bounce reason or Undef if the argument
28
+ # @return [String, Nil] Bounce reason or Nil if the argument
29
29
  # is missing or invalid object
30
30
  # @see anotherone
31
31
  def get(argvs)
@@ -68,22 +68,7 @@ module Sisimai
68
68
 
69
69
  if reasontext.empty? || reasontext == 'undefined'
70
70
  # Bounce reason is not detected yet.
71
- loop do
72
- p = 'Sisimai::Reason::OnHold' # Onhold ?
73
- r = nil
74
- begin
75
- require p.downcase.gsub('::', '/')
76
- r = Module.const_get(p)
77
- reasontext = r.text if r.true(argvs)
78
- rescue
79
- warn ' ***warning: Failed to load ' + p
80
- end
81
- break if reasontext.size > 0
82
-
83
- # Other reason ?
84
- reasontext = self.anotherone(argvs)
85
- break
86
- end
71
+ reasontext = self.anotherone(argvs)
87
72
 
88
73
  if reasontext == 'undefined' || reasontext.empty?
89
74
  # Action: delayed => "expired"
@@ -154,6 +139,11 @@ module Sisimai
154
139
  elsif argvs.diagnostictype =~ /\AX-(?:UNIX|POSTFIX)\z/
155
140
  # Diagnostic-Code: X-UNIX; ...
156
141
  reasontext = 'mailererror'
142
+
143
+ else
144
+ # 50X Syntax Error?
145
+ require 'sisimai/reason/syntaxerror'
146
+ reasontext = 'syntaxerror' if Sisimai::Reason::SyntaxError.true(argvs)
157
147
  end
158
148
  end
159
149
 
@@ -175,59 +165,6 @@ module Sisimai
175
165
  return reasontext
176
166
  end
177
167
 
178
- # Detect the bounce reason from given text
179
- # @param [String] argv1 Error message
180
- # @return [String] Bounce reason
181
- def match(argv1)
182
- return nil unless argv1
183
- require 'sisimai/smtp/status'
184
-
185
- reasontext = ''
186
- typestring = ''
187
- classorder = %w|
188
- MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected
189
- HostUnknown SpamDetected TooManyConn Blocked SpamDetected SecurityError
190
- SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull
191
- NotAccept MailerError NoRelaying OnHold
192
- |
193
-
194
- statuscode = Sisimai::SMTP::Status.find(argv1)
195
- if cv = argv1.match(/\A(SMTP|X-.+);/i)
196
- typestring = cv[1].upcase
197
- end
198
-
199
- # Diagnostic-Code: SMTP; ... or empty value
200
- classorder.each do |e|
201
- # Check the value of Diagnostic-Code: and the value of Status:, it is a
202
- # deliverystats, with true() method in each Sisimai::Reason::* class.
203
- p = 'Sisimai::Reason::' + e
204
- r = nil
205
- begin
206
- require p.downcase.gsub('::', '/')
207
- r = Module.const_get(p)
208
- rescue
209
- warn ' ***warning: Failed to load ' + p
210
- next
211
- end
212
-
213
- next unless r.match(argv1)
214
- reasontext = r.text
215
- break
216
- end
217
-
218
- if reasontext.empty?
219
- # Check the value of $typestring
220
- if typestring == 'X-UNIX'
221
- # X-Unix; ...
222
- reasontext = 'mailererror'
223
- else
224
- # Detect the bounce reason from "Status:" code
225
- reasontext = Sisimai::SMTP::Status.name(statuscode) || 'undefined'
226
- end
227
- end
228
- return reasontext
229
- end
230
-
231
168
  end
232
169
  end
233
170
  end
@@ -10,6 +10,9 @@ module Sisimai
10
10
  # Imported from p5-Sisimail/lib/Sisimai/Reason/Blocked.pm
11
11
  class << self
12
12
  def text; return 'blocked'; end
13
+ def description
14
+ return 'Email rejected due to client IP address or a hostname'
15
+ end
13
16
 
14
17
  # Try to match that the given text and regular expressions
15
18
  # @param [String] argv1 String to be matched with regular expressions
@@ -11,6 +11,9 @@ module Sisimai
11
11
  # Imported from p5-Sisimail/lib/Sisimai/Reason/ContentError.pm
12
12
  class << self
13
13
  def text; return 'contenterror'; end
14
+ def description
15
+ return 'Email rejected due to a header format of the email'
16
+ end
14
17
 
15
18
  # Try to match that the given text and regular expressions
16
19
  # @param [String] argv1 String to be matched with regular expressions