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
@@ -23,8 +23,6 @@ module Sisimai
23
23
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
24
24
  }
25
25
  Indicators = Sisimai::MTA.INDICATORS
26
- LongFields = Sisimai::RFC5322.LONGFIELDS
27
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
28
26
 
29
27
  def description; return 'Java Apache Mail Enterprise Server'; end
30
28
  def smtpagent; return 'ApacheJames'; end
@@ -52,11 +50,10 @@ module Sisimai
52
50
  match += 1 if mhead['received'].find { |a| a =~ Re0[:received] }
53
51
  return if match == 0
54
52
 
55
- dscontents = []; dscontents << Sisimai::MTA.DELIVERYSTATUS
53
+ dscontents = [Sisimai::MTA.DELIVERYSTATUS]
56
54
  hasdivided = mbody.split("\n")
57
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
58
- rfc822part = '' # (String) message/rfc822-headers part
59
- previousfn = '' # (String) Previous field name
55
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
56
+ blanklines = 0 # (Integer) The number of blank lines
60
57
  readcursor = 0 # (Integer) Points the current cursor position
61
58
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
62
59
  diagnostic = '' # (String) Alternative diagnostic message
@@ -65,11 +62,10 @@ module Sisimai
65
62
  v = nil
66
63
 
67
64
  hasdivided.each do |e|
68
-
69
65
  if readcursor == 0
70
66
  # Beginning of the bounce message or delivery status part
71
67
  if e =~ Re1[:begin]
72
- readcursor |= Indicators[:'deliverystatus']
68
+ readcursor |= Indicators[:deliverystatus]
73
69
  next
74
70
  end
75
71
  end
@@ -84,30 +80,16 @@ module Sisimai
84
80
 
85
81
  if readcursor & Indicators[:'message-rfc822'] > 0
86
82
  # After "message/rfc822"
87
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
88
- # Get required headers only
89
- lhs = cv[1].downcase
90
- previousfn = ''
91
- next unless RFC822Head.key?(lhs)
92
-
93
- previousfn = lhs
94
- rfc822part += e + "\n"
95
-
96
- elsif e =~ /\A[ \t]+/
97
- # Continued line from the previous line
98
- next if rfc822next[previousfn]
99
- rfc822part += e + "\n" if LongFields.key?(previousfn)
100
-
101
- else
102
- # Check the end of headers in rfc822 part
103
- next unless LongFields.key?(previousfn)
104
- next unless e.empty?
105
- rfc822next[previousfn] = true
83
+ if e.empty?
84
+ blanklines += 1
85
+ break if blanklines > 1
86
+ next
106
87
  end
88
+ rfc822list << e
107
89
 
108
90
  else
109
91
  # Before "message/rfc822"
110
- next if readcursor & Indicators[:'deliverystatus'] == 0
92
+ next if readcursor & Indicators[:deliverystatus] == 0
111
93
  next if e.empty?
112
94
 
113
95
  # Message details:
@@ -164,26 +146,22 @@ module Sisimai
164
146
  end
165
147
  end
166
148
  end
167
-
168
149
  return nil if recipients == 0
169
150
  require 'sisimai/string'
170
- require 'sisimai/smtp/status'
151
+
152
+ unless rfc822list.find { |a| a =~ /^Subject:/ }
153
+ # Set the value of $subjecttxt as a Subject if there is no original
154
+ # message in the bounce mail.
155
+ rfc822list << sprintf('Subject: %s', subjecttxt)
156
+ end
171
157
 
172
158
  dscontents.map do |e|
173
- e['agent'] = Sisimai::MTA::ApacheJames.smtpagent
174
-
175
- if mhead['received'].size > 0
176
- # Get localhost and remote host name from Received header.
177
- r0 = mhead['received']
178
- %w|lhost rhost|.each { |a| e[a] ||= '' }
179
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
180
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
181
- end
159
+ e['agent'] = Sisimai::MTA::ApacheJames.smtpagent
182
160
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'] || diagnostic)
183
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
184
161
  e.each_key { |a| e[a] ||= '' }
185
162
  end
186
163
 
164
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
187
165
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
188
166
  end
189
167
 
@@ -34,24 +34,16 @@ module Sisimai
34
34
  }
35
35
  ReFailure = {
36
36
  # courier/module.esmtp/esmtpclient.c:526| hard_error(del, ctf, "No such domain.");
37
- 'hostunknown' => %r{
38
- \ANo[ ]such[ ]domain[.]\z
39
- }x,
37
+ hostunknown: %r/\ANo[ ]such[ ]domain[.]\z/x,
40
38
  # courier/module.esmtp/esmtpclient.c:531| hard_error(del, ctf,
41
39
  # courier/module.esmtp/esmtpclient.c:532| "This domain's DNS violates RFC 1035.");
42
- 'systemerror' => %r{
43
- \AThis[ ]domain's[ ]DNS[ ]violates[ ]RFC[ ]1035[.]\z
44
- }x,
40
+ systemerror: %r/\AThis[ ]domain's[ ]DNS[ ]violates[ ]RFC[ ]1035[.]\z/x,
45
41
  }
46
42
  ReDelayed = {
47
43
  # courier/module.esmtp/esmtpclient.c:535| soft_error(del, ctf, "DNS lookup failed.");
48
- 'networkerror' => %r{
49
- \ADNS[ ]lookup[ ]failed[.]\z
50
- },
44
+ networkerror: %r/\ADNS[ ]lookup[ ]failed[.]\z/x,
51
45
  }
52
46
  Indicators = Sisimai::MTA.INDICATORS
53
- LongFields = Sisimai::RFC5322.LONGFIELDS
54
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
55
47
 
56
48
  def description; return 'Courier MTA'; end
57
49
  def smtpagent; return 'Courier'; end
@@ -82,12 +74,11 @@ module Sisimai
82
74
  end
83
75
  return nil if match == 0
84
76
 
85
- dscontents = []; dscontents << Sisimai::MTA.DELIVERYSTATUS
77
+ dscontents = [Sisimai::MTA.DELIVERYSTATUS]
86
78
  hasdivided = mbody.split("\n")
87
- havepassed = [''];
88
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
89
- rfc822part = '' # (String) message/rfc822-headers part
90
- previousfn = '' # (String) Previous field name
79
+ havepassed = ['']
80
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
81
+ blanklines = 0 # (Integer) The number of blank lines
91
82
  readcursor = 0 # (Integer) Points the current cursor position
92
83
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
93
84
  commandtxt = '' # (String) SMTP Command name begin with the string '>>>'
@@ -101,12 +92,13 @@ module Sisimai
101
92
 
102
93
  hasdivided.each do |e|
103
94
  # Save the current line for the next loop
104
- havepassed << e; p = havepassed[-2]
95
+ havepassed << e
96
+ p = havepassed[-2]
105
97
 
106
98
  if readcursor == 0
107
99
  # Beginning of the bounce message or delivery status part
108
100
  if e =~ Re1[:begin]
109
- readcursor |= Indicators[:'deliverystatus']
101
+ readcursor |= Indicators[:deliverystatus]
110
102
  next
111
103
  end
112
104
  end
@@ -121,30 +113,16 @@ module Sisimai
121
113
 
122
114
  if readcursor & Indicators[:'message-rfc822'] > 0
123
115
  # After "message/rfc822"
124
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
125
- # Get required headers only
126
- lhs = cv[1].downcase
127
- previousfn = ''
128
- next unless RFC822Head.key?(lhs)
129
-
130
- previousfn = lhs
131
- rfc822part += e + "\n"
132
-
133
- elsif e =~ /\A[ \t]+/
134
- # Continued line from the previous line
135
- next if rfc822next[previousfn]
136
- rfc822part += e + "\n" if LongFields.key?(previousfn)
137
-
138
- else
139
- # Check the end of headers in rfc822 part
140
- next unless LongFields.key?(previousfn)
141
- next unless e.empty?
142
- rfc822next[previousfn] = true
116
+ if e.empty?
117
+ blanklines += 1
118
+ break if blanklines > 1
119
+ next
143
120
  end
121
+ rfc822list << e
144
122
 
145
123
  else
146
124
  # Before "message/rfc822"
147
- next if readcursor & Indicators[:'deliverystatus'] == 0
125
+ next if readcursor & Indicators[:deliverystatus] == 0
148
126
  next if e.empty?
149
127
 
150
128
  if connvalues == connheader.keys.size
@@ -159,7 +137,7 @@ module Sisimai
159
137
  # Final-Recipient: rfc822; kijitora@example.co.jp
160
138
  if v['recipient']
161
139
  # There are multiple recipient addresses in the message body.
162
- dscontents << Sisimai::MTA.DELIVERYSTATUS;
140
+ dscontents << Sisimai::MTA.DELIVERYSTATUS
163
141
  v = dscontents[-1]
164
142
  end
165
143
  v['recipient'] = cv[1]
@@ -250,28 +228,18 @@ module Sisimai
250
228
  end
251
229
  end
252
230
  end
253
-
254
231
  return nil if recipients == 0
255
232
  require 'sisimai/string'
256
- require 'sisimai/smtp/status'
257
233
 
258
234
  dscontents.map do |e|
259
235
  # Set default values if each value is empty.
260
236
  connheader.each_key { |a| e[a] ||= connheader[a] || '' }
261
237
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
262
238
 
263
- if mhead['received'].size > 0
264
- # Get localhost and remote host name from Received header.
265
- r0 = mhead['received']
266
- %w|lhost rhost|.each { |a| e[a] ||= '' }
267
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
268
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
269
- end
270
-
271
239
  ReFailure.each_key do |r|
272
240
  # Verify each regular expression of session errors
273
241
  next unless e['diagnosis'] =~ ReFailure[r]
274
- e['reason'] = r
242
+ e['reason'] = r.to_s
275
243
  e['softbounce'] = 0
276
244
  break
277
245
  end
@@ -280,23 +248,18 @@ module Sisimai
280
248
  ReDelayed.each_key do |r|
281
249
  # Verify each regular expression of session errors
282
250
  next unless e['diagnosis'] =~ ReDelayed[r]
283
- e['reason'] = r
251
+ e['reason'] = r.to_s
284
252
  e['softbounce'] = 1
285
253
  break
286
254
  end
287
255
  end
288
256
 
289
- if !e['status'] || e['status'] =~ /\d[.]0[.]0\z/
290
- # Get the status code from the respnse of remote MTA.
291
- f = Sisimai::SMTP::Status.find(e['diagnosis'])
292
- e['status'] = f if f.size > 0
293
- end
294
- e['spec'] = '' unless e['spec'] =~ /\A(?:SMTP|X-UNIX)\z/
295
257
  e['agent'] = Sisimai::MTA::Courier.smtpagent
296
258
  e['command'] ||= commandtxt || ''
297
259
  e.each_key { |a| e[a] ||= '' }
298
260
  end
299
261
 
262
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
300
263
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
301
264
  end
302
265
 
@@ -17,7 +17,7 @@ module Sisimai
17
17
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
18
18
  }
19
19
  ReFailure = {
20
- 'userunknown' => %r{(?>
20
+ userunknown: %r{(?>
21
21
  not[ ]listed[ ]in[ ](?:
22
22
  Domino[ ]Directory
23
23
  |public[ ]Name[ ][&][ ]Address[ ]Book
@@ -25,16 +25,10 @@ module Sisimai
25
25
  |Domino[ ]ディレクトリには見つかりません
26
26
  )
27
27
  }x,
28
- 'filtered' => %r{
29
- Cannot[ ]route[ ]mail[ ]to[ ]user
30
- }x,
31
- 'systemerror' => %r{
32
- Several[ ]matches[ ]found[ ]in[ ]Domino[ ]Directory
33
- }x,
28
+ filtered: %r/Cannot[ ]route[ ]mail[ ]to[ ]user/x,
29
+ systemerror: %r/Several[ ]matches[ ]found[ ]in[ ]Domino[ ]Directory/x,
34
30
  }
35
31
  Indicators = Sisimai::MTA.INDICATORS
36
- LongFields = Sisimai::RFC5322.LONGFIELDS
37
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
38
32
 
39
33
  def description; return 'IBM Domino Server'; end
40
34
  def smtpagent; return 'Domino'; end
@@ -57,25 +51,23 @@ module Sisimai
57
51
  return nil unless mbody
58
52
  return nil unless mhead['subject'] =~ Re0[:subject]
59
53
 
60
- dscontents = []; dscontents << Sisimai::MTA.DELIVERYSTATUS
54
+ require 'sisimai/address'
55
+ dscontents = [Sisimai::MTA.DELIVERYSTATUS]
61
56
  hasdivided = mbody.split("\n")
62
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
63
- rfc822part = '' # (String) message/rfc822-headers part
64
- previousfn = '' # (String) Previous field name
57
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
58
+ blanklines = 0 # (Integer) The number of blank lines
65
59
  readcursor = 0 # (Integer) Points the current cursor position
66
60
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
67
61
  subjecttxt = '' # (String) The value of Subject:
68
62
  v = nil
69
63
 
70
- require 'sisimai/address'
71
-
72
64
  hasdivided.each do |e|
73
65
  next if e.empty?
74
66
 
75
67
  if readcursor == 0
76
68
  # Beginning of the bounce message or delivery status part
77
69
  if e =~ Re1[:begin]
78
- readcursor |= Indicators[:'deliverystatus']
70
+ readcursor |= Indicators[:deliverystatus]
79
71
  next
80
72
  end
81
73
  end
@@ -90,30 +82,16 @@ module Sisimai
90
82
 
91
83
  if readcursor & Indicators[:'message-rfc822'] > 0
92
84
  # After "message/rfc822"
93
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
94
- # Get required headers only
95
- lhs = cv[1].downcase
96
- previousfn = ''
97
- next unless RFC822Head.key?(lhs)
98
-
99
- previousfn = lhs
100
- rfc822part += e + "\n"
101
-
102
- elsif e =~ /\A[ \t]+/
103
- # Continued line from the previous line
104
- next if rfc822next[previousfn]
105
- rfc822part += e + "\n" if LongFields.key?(previousfn)
106
-
107
- else
108
- # Check the end of headers in rfc822 part
109
- next unless LongFields.key?(previousfn)
110
- next unless e.empty?
111
- rfc822next[previousfn] = true
85
+ if e.empty?
86
+ blanklines += 1
87
+ break if blanklines > 1
88
+ next
112
89
  end
90
+ rfc822list << e
113
91
 
114
92
  else
115
93
  # Before "message/rfc822"
116
- next if readcursor & Indicators[:'deliverystatus'] == 0
94
+ next if readcursor & Indicators[:deliverystatus] == 0
117
95
 
118
96
  # Your message
119
97
  #
@@ -167,38 +145,28 @@ module Sisimai
167
145
  require 'sisimai/smtp/status'
168
146
 
169
147
  dscontents.map do |e|
170
- # Set default values if each value is empty.
171
- e['agent'] = Sisimai::MTA::Domino.smtpagent
172
-
173
- if mhead['received'].size > 0
174
- # Get localhost and remote host name from Received header.
175
- r0 = mhead['received']
176
- %w|lhost rhost|.each { |a| e[a] ||= '' }
177
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
178
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
179
- end
148
+ e['agent'] = Sisimai::MTA::Domino.smtpagent
180
149
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
181
150
  e['recipient'] = Sisimai::Address.s3s4(e['recipient'])
182
151
 
183
152
  ReFailure.each_key do |r|
184
153
  # Check each regular expression of Domino error messages
185
154
  next unless e['diagnosis'] =~ ReFailure[r]
186
- e['reason'] = r
187
- pseudostatus = Sisimai::SMTP::Status.code(r, false)
155
+ e['reason'] = r.to_s
156
+ pseudostatus = Sisimai::SMTP::Status.code(r.to_s, false)
188
157
  e['status'] = pseudostatus if pseudostatus.size > 0
189
158
  break
190
159
  end
191
-
192
- e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
193
- e['action'] = 'failed' if e['status'] =~ /\A[45]/
194
-
195
- unless rfc822part =~ /\bSubject:/
196
- # Fallback: Add the value of Subject as a Subject header
197
- rfc822part += sprintf("Subject: %s\n", subjecttxt)
198
- end
199
160
  e.each_key { |a| e[a] ||= '' }
200
161
  end
201
162
 
163
+ unless rfc822list.find { |a| a =~ /^Subject:/ }
164
+ # Set the value of $subjecttxt as a Subject if there is no original
165
+ # message in the bounce mail.
166
+ rfc822list << sprintf('Subject: %s', subjecttxt)
167
+ end
168
+
169
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
202
170
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
203
171
  end
204
172
 
@@ -27,35 +27,33 @@ module Sisimai
27
27
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
28
28
  }
29
29
  CodeTable = {
30
- 'onhold' => [
30
+ onhold: [
31
31
  '000B099C', # Host Unknown, Message exceeds size limit, ...
32
32
  '000B09AA', # Unable to relay for, Message exceeds size limit,...
33
33
  '000B09B6', # Error messages by remote MTA
34
34
  ],
35
- 'userunknown' => [
35
+ userunknown: [
36
36
  '000C05A6', # Unknown Recipient,
37
37
  ],
38
- 'systemerror' => [
38
+ systemerror: [
39
39
  '00010256', # Too many recipients.
40
40
  '000D06B5', # No proxy for recipient (non-smtp mail?)
41
41
  ],
42
- 'networkerror' => [
42
+ networkerror: [
43
43
  '00120270', # Too Many Hops
44
44
  ],
45
- 'contenterr' => [
45
+ contenterr: [
46
46
  '00050311', # Conversion to Internet format failed
47
47
  '000502CC', # Conversion to Internet format failed
48
48
  ],
49
- 'securityerr' => [
49
+ securityerr: [
50
50
  '000B0981', # 502 Server does not support AUTH
51
51
  ],
52
- 'filtered' => [
52
+ filtered: [
53
53
  '000C0595', # Ambiguous Recipient
54
54
  ],
55
55
  }
56
56
  Indicators = Sisimai::MTA.INDICATORS
57
- LongFields = Sisimai::RFC5322.LONGFIELDS
58
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
59
57
 
60
58
  def description; return 'Microsoft Exchange Server'; end
61
59
  def smtpagent; return 'Exchange'; end
@@ -108,11 +106,10 @@ module Sisimai
108
106
  end
109
107
  return nil if match == 0
110
108
 
111
- dscontents = []; dscontents << Sisimai::MTA.DELIVERYSTATUS
109
+ dscontents = [Sisimai::MTA.DELIVERYSTATUS]
112
110
  hasdivided = mbody.split("\n")
113
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
114
- rfc822part = '' # (String) message/rfc822-headers part
115
- previousfn = '' # (String) Previous field name
111
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
112
+ blanklines = 0 # (Integer) The number of blank lines
116
113
  readcursor = 0 # (Integer) Points the current cursor position
117
114
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
118
115
  statuspart = false # (Boolean) Flag, true = have got delivery status part.
@@ -128,7 +125,7 @@ module Sisimai
128
125
  if readcursor == 0
129
126
  # Beginning of the bounce message or delivery status part
130
127
  if e =~ Re1[:begin]
131
- readcursor |= Indicators[:'deliverystatus']
128
+ readcursor |= Indicators[:deliverystatus]
132
129
  next
133
130
  end
134
131
  end
@@ -143,30 +140,16 @@ module Sisimai
143
140
 
144
141
  if readcursor & Indicators[:'message-rfc822'] > 0
145
142
  # After "message/rfc822"
146
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
147
- # Get required headers only
148
- lhs = cv[1].downcase
149
- previousfn = ''
150
- next unless RFC822Head.key?(lhs)
151
-
152
- previousfn = lhs
153
- rfc822part += e + "\n"
154
-
155
- elsif e =~ /\A[ \t]+/
156
- # Continued line from the previous line
157
- next if rfc822next[previousfn]
158
- rfc822part += e + "\n" if LongFields.key?(previousfn)
159
-
160
- else
161
- # Check the end of headers in rfc822 part
162
- next unless LongFields.key?(previousfn)
163
- next unless e.empty?
164
- rfc822next[previousfn] = true
143
+ if e.empty?
144
+ blanklines += 1
145
+ break if blanklines > 1
146
+ next
165
147
  end
148
+ rfc822list << e
166
149
 
167
150
  else
168
151
  # Before "message/rfc822"
169
- next if readcursor & Indicators[:'deliverystatus'] == 0
152
+ next if readcursor & Indicators[:deliverystatus] == 0
170
153
  next if statuspart
171
154
 
172
155
  if connvalues == connheader.keys.size
@@ -185,7 +168,7 @@ module Sisimai
185
168
  v = dscontents[-1]
186
169
 
187
170
  if cv = e.match(/\A[ \t]*([^ ]+[@][^ ]+) on[ \t]*.*\z/) ||
188
- cv = e.match(/\A[ \t]*.+(?:SMTP|smtp)=([^ ]+[@][^ ]+) on[ \t]*.*\z/)
171
+ e.match(/\A[ \t]*.+(?:SMTP|smtp)=([^ ]+[@][^ ]+) on[ \t]*.*\z/)
189
172
  # kijitora@example.co.jp on Thu, 29 Apr 2007 16:51:51 -0500
190
173
  # kijitora@example.com on 4/29/99 9:19:59 AM
191
174
  if v['recipient']
@@ -254,15 +237,6 @@ module Sisimai
254
237
  require 'sisimai/smtp/status'
255
238
 
256
239
  dscontents.map do |e|
257
- if mhead['received'].size > 0
258
- # Get localhost and remote host name from Received header.
259
- r0 = mhead['received']
260
- %w|lhost rhost|.each { |a| e[a] ||= '' }
261
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
262
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
263
- end
264
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
265
-
266
240
  if cv = e['diagnosis'].match(/\AMSEXCH:.+[ \t]*[(]([0-9A-F]{8})[)][ \t]*(.*)\z/)
267
241
  # MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
268
242
  capturedcode = cv[1]
@@ -272,8 +246,8 @@ module Sisimai
272
246
  CodeTable.each_key do |r|
273
247
  # Find captured code from the error code table
274
248
  next unless CodeTable[r].index(capturedcode)
275
- e['reason'] = r
276
- pseudostatus = Sisimai::SMTP::Status.code(r)
249
+ e['reason'] = r.to_s
250
+ pseudostatus = Sisimai::SMTP::Status.code(r.to_s)
277
251
  e['status'] = pseudostatus if pseudostatus.size > 0
278
252
  break
279
253
  end
@@ -289,21 +263,19 @@ module Sisimai
289
263
  e.delete('alterrors')
290
264
  end
291
265
  end
292
-
293
- e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
294
- e['action'] = 'failed' if e['status'] =~ /\A[45]/
295
- e['agent'] = Sisimai::MTA::Exchange.smtpagent
266
+ e['agent'] = Sisimai::MTA::Exchange.smtpagent
296
267
  e.delete('msexch')
297
268
  e.each_key { |a| e[a] ||= '' }
298
269
  end
299
270
 
300
- if rfc822part.empty?
271
+ if rfc822list.empty?
301
272
  # When original message does not included in the bounce message
302
- rfc822part += sprintf("From: %s\n", connheader['to'])
303
- rfc822part += sprintf("Date: %s\n", connheader['date'])
304
- rfc822part += sprintf("Subject: %s\n", connheader['subject'])
273
+ rfc822list << sprintf('From: %s', connheader['to'])
274
+ rfc822list << sprintf('Date: %s', connheader['date'])
275
+ rfc822list << sprintf('Subject: %s', connheader['subject'])
305
276
  end
306
277
 
278
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
307
279
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
308
280
  end
309
281