sisimai 4.14.2 → 4.15.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +19 -2
  3. data/.travis.yml +0 -1
  4. data/Changes +16 -0
  5. data/README.md +69 -17
  6. data/appveyor.yml +23 -0
  7. data/lib/sisimai.rb +9 -7
  8. data/lib/sisimai/address.rb +8 -2
  9. data/lib/sisimai/arf.rb +1 -6
  10. data/lib/sisimai/data.rb +35 -47
  11. data/lib/sisimai/data/json.rb +16 -12
  12. data/lib/sisimai/datetime.rb +1 -8
  13. data/lib/sisimai/mail/maildir.rb +0 -3
  14. data/lib/sisimai/mail/mbox.rb +1 -1
  15. data/lib/sisimai/mail/stdin.rb +2 -1
  16. data/lib/sisimai/message.rb +46 -31
  17. data/lib/sisimai/mime.rb +2 -2
  18. data/lib/sisimai/msp.rb +3 -3
  19. data/lib/sisimai/msp/de/einsundeins.rb +1 -1
  20. data/lib/sisimai/msp/de/gmx.rb +1 -1
  21. data/lib/sisimai/msp/jp/biglobe.rb +2 -2
  22. data/lib/sisimai/msp/jp/ezweb.rb +10 -10
  23. data/lib/sisimai/msp/jp/kddi.rb +1 -1
  24. data/lib/sisimai/msp/ru/yandex.rb +1 -1
  25. data/lib/sisimai/msp/uk/messagelabs.rb +1 -1
  26. data/lib/sisimai/msp/us/amazonses.rb +1 -1
  27. data/lib/sisimai/msp/us/amazonworkmail.rb +224 -0
  28. data/lib/sisimai/msp/us/aol.rb +1 -1
  29. data/lib/sisimai/msp/us/bigfoot.rb +1 -1
  30. data/lib/sisimai/msp/us/facebook.rb +1 -1
  31. data/lib/sisimai/msp/us/google.rb +1 -1
  32. data/lib/sisimai/msp/us/office365.rb +273 -0
  33. data/lib/sisimai/msp/us/outlook.rb +2 -3
  34. data/lib/sisimai/msp/us/receivingses.rb +1 -1
  35. data/lib/sisimai/msp/us/sendgrid.rb +2 -2
  36. data/lib/sisimai/msp/us/verizon.rb +7 -7
  37. data/lib/sisimai/msp/us/yahoo.rb +1 -1
  38. data/lib/sisimai/msp/us/zoho.rb +1 -1
  39. data/lib/sisimai/mta.rb +8 -9
  40. data/lib/sisimai/mta/activehunter.rb +1 -1
  41. data/lib/sisimai/mta/apachejames.rb +1 -1
  42. data/lib/sisimai/mta/courier.rb +1 -1
  43. data/lib/sisimai/mta/domino.rb +1 -1
  44. data/lib/sisimai/mta/exchange.rb +15 -15
  45. data/lib/sisimai/mta/imailserver.rb +1 -1
  46. data/lib/sisimai/mta/interscanmss.rb +1 -1
  47. data/lib/sisimai/mta/mailfoundry.rb +1 -1
  48. data/lib/sisimai/mta/mailmarshalsmtp.rb +1 -1
  49. data/lib/sisimai/mta/mcafee.rb +1 -1
  50. data/lib/sisimai/mta/messagingserver.rb +1 -1
  51. data/lib/sisimai/mta/mxlogic.rb +2 -2
  52. data/lib/sisimai/mta/notes.rb +1 -1
  53. data/lib/sisimai/mta/opensmtpd.rb +1 -1
  54. data/lib/sisimai/mta/postfix.rb +2 -2
  55. data/lib/sisimai/mta/qmail.rb +1 -1
  56. data/lib/sisimai/mta/sendmail.rb +2 -2
  57. data/lib/sisimai/mta/surfcontrol.rb +1 -1
  58. data/lib/sisimai/mta/v5sendmail.rb +1 -1
  59. data/lib/sisimai/mta/x1.rb +1 -1
  60. data/lib/sisimai/mta/x2.rb +1 -1
  61. data/lib/sisimai/mta/x3.rb +1 -1
  62. data/lib/sisimai/mta/x4.rb +1 -1
  63. data/lib/sisimai/mta/x5.rb +1 -1
  64. data/lib/sisimai/order.rb +4 -1
  65. data/lib/sisimai/reason.rb +15 -18
  66. data/lib/sisimai/reason/hostunknown.rb +5 -0
  67. data/lib/sisimai/reason/mesgtoobig.rb +5 -0
  68. data/lib/sisimai/reason/userunknown.rb +1 -1
  69. data/lib/sisimai/rfc3464.rb +3 -3
  70. data/lib/sisimai/rfc3834.rb +1 -1
  71. data/lib/sisimai/time.rb +1 -1
  72. data/lib/sisimai/version.rb +1 -1
  73. data/set-of-emails/maildir/bsd/us-amazonworkmail-01.eml +156 -0
  74. data/set-of-emails/maildir/bsd/us-amazonworkmail-02.eml +160 -0
  75. data/set-of-emails/maildir/bsd/us-amazonworkmail-03.eml +161 -0
  76. data/set-of-emails/maildir/bsd/us-amazonworkmail-04.eml +156 -0
  77. data/set-of-emails/maildir/bsd/us-amazonworkmail-05.eml +157 -0
  78. data/set-of-emails/maildir/bsd/us-office365-01.eml +102 -0
  79. data/sisimai.gemspec +7 -0
  80. metadata +26 -3
@@ -5,8 +5,6 @@ module Sisimai
5
5
  module JSON
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Data/JSON.pm
7
7
  class << self
8
- require 'json'
9
-
10
8
  # Data dumper(JSON)
11
9
  # @param [Sisimai::Data] argvs Object
12
10
  # @return [String, Nil] Dumped data or Undef if the argument
@@ -15,16 +13,22 @@ module Sisimai
15
13
  return nil unless argvs
16
14
  return nil unless argvs.is_a? Sisimai::Data
17
15
 
18
- damneddata = argvs.damn
19
- jsonstring = nil
20
- jsonoption = ::JSON::state.new
21
-
22
- begin
23
- jsonoption.space = ' '
24
- jsonoption.object_nl = ' '
25
- jsonstring = ::JSON.generate(damneddata, jsonoption)
26
- rescue
27
- warn '***warning: Failed to JSON.generate'
16
+ if RUBY_PLATFORM =~ /java/
17
+ # java-based ruby environment like JRuby.
18
+ begin
19
+ require 'jrjackson'
20
+ jsonstring = JrJackson::Json.dump(argvs.damn)
21
+ rescue
22
+ warn '***warning: Failed to JrJackson::Json.dump'
23
+ end
24
+ else
25
+ # MRI
26
+ begin
27
+ require 'oj'
28
+ jsonstring = Oj.dump(argvs.damn, :mode => :compat)
29
+ rescue
30
+ warn '***warning: Failed to Oj.dump'
31
+ end
28
32
  end
29
33
 
30
34
  return jsonstring
@@ -258,7 +258,6 @@ module Sisimai
258
258
  # o2d(2,'/') #=> 2015/11/02
259
259
  def o2d(argv1 = 0, argv2 = '-')
260
260
  piece = ::DateTime.now
261
- epoch = 0
262
261
 
263
262
  return piece.strftime('%Y/%m/%d') unless argv1 =~ /\A[-]?\d+\z/
264
263
  epoch = piece.to_time.to_i - argv1 * 86400
@@ -290,7 +289,6 @@ module Sisimai
290
289
  datestring = datestring.sub(/[,](\d+)/, ', \1') # Thu,13 -> Thu, 13
291
290
  datestring = datestring.sub(/(\d{1,2}),/, '\1') # Apr,29 -> Apr 29
292
291
  timetokens = datestring.split(' ')
293
- parseddate = '' # (String) Canonified Date/Time string
294
292
  afternoon1 = 0 # (Integer) After noon flag
295
293
  altervalue = {} # (Hash) To store alternative values
296
294
  v = {
@@ -442,10 +440,7 @@ module Sisimai
442
440
 
443
441
  # Build date string
444
442
  # Thu, 29 Apr 2004 10:01:11 +0900
445
- parseddate = sprintf(
446
- '%s, %s %s %s %s %s',
447
- v['a'], v['d'], v['M'], v['Y'], v['T'], v['z'])
448
- return parseddate
443
+ return sprintf('%s, %s %s %s %s %s', v['a'], v['d'], v['M'], v['Y'], v['T'], v['z'])
449
444
  end
450
445
 
451
446
  # Abbreviation -> Tiemzone
@@ -468,7 +463,6 @@ module Sisimai
468
463
  # tz2second('+0900') #=> 32400
469
464
  def tz2second(argv1)
470
465
  return nil unless argv1.is_a?(::String)
471
- digit = {}
472
466
  ztime = 0
473
467
 
474
468
  if cr = argv1.match(/\A([-+])(\d)(\d)(\d{2})\z/)
@@ -502,7 +496,6 @@ module Sisimai
502
496
  def second2tz(argv1)
503
497
  return '+0000' unless argv1.is_a?(Number)
504
498
  digit = { 'operator' => '+' }
505
- timez = ''
506
499
 
507
500
  return '' if argv1.abs > TZ_OFFSET # UTC+14 + 1(DST?)
508
501
  digit['operator'] = '-' if argv1 < 0
@@ -41,10 +41,7 @@ module Sisimai
41
41
  return nil unless self.offset < self.size
42
42
 
43
43
  seekhandle = self.handle
44
- filehandle = nil
45
44
  readbuffer = ''
46
- emailindir = ''
47
- emailinode = nil
48
45
 
49
46
  begin
50
47
  while r = seekhandle.read do
@@ -1,6 +1,6 @@
1
1
  module Sisimai
2
- # Sisimai::Mail::Mbox is a mailbox file (UNIX mbox) reader.
3
2
  class Mail
3
+ # Sisimai::Mail::Mbox is a mailbox file (UNIX mbox) reader.
4
4
  class Mbox
5
5
  # Imported from p5-Sisimail/lib/Sisimai/Mail/Mbox.pm
6
6
  @@roaccessors = [
@@ -1,6 +1,7 @@
1
- # Sisimai::Mail::STDIN is a reader for getting contents of each email from STDIN
2
1
  module Sisimai
3
2
  class Mail
3
+ # Sisimai::Mail::STDIN is a reader for getting contents of each email from
4
+ # STDIN
4
5
  class STDIN
5
6
  # Imported from p5-Sisimail/lib/Sisimai/Mail/STDIN.pm
6
7
  @@roaccessors = [
@@ -30,14 +30,12 @@ module Sisimai
30
30
  MultiHeads = { 'received' => true }
31
31
  IgnoreList = { 'dkim-signature' => true }
32
32
  Indicators = {
33
- :begin => ( 1 << 1 ),
34
- :endof => ( 1 << 2 ),
33
+ :begin => (1 << 1),
34
+ :endof => (1 << 2),
35
35
  }
36
- @@DefaultSet = Sisimai::Order.another
37
- @@PatternSet = Sisimai::Order.by('subject')
38
- @@ExtHeaders = Sisimai::Order.headers
39
- @@ToBeLoaded = []
40
- @@TryOnFirst = []
36
+ DefaultSet = Sisimai::Order.another
37
+ PatternSet = Sisimai::Order.by('subject')
38
+ ExtHeaders = Sisimai::Order.headers
41
39
 
42
40
  # Constructor of Sisimai::Message
43
41
  # @param [String] data Email text data
@@ -87,8 +85,11 @@ module Sisimai
87
85
 
88
86
  processing = { 'from' => '', 'header' => {}, 'rfc822' => '', 'ds' => [] }
89
87
  mtamodules = []
88
+ extheaders = ExtHeaders
89
+ tobeloaded = []
90
+ headerargv = {}
90
91
 
91
- ['load', 'order'].each do |e|
92
+ %w|load order|.each do |e|
92
93
  # The order of MTA modules specified by user
93
94
  next unless argvs.key?(e)
94
95
  next unless argvs[e].is_a? Array
@@ -109,37 +110,41 @@ module Sisimai
109
110
 
110
111
  Module.const_get(v).headerlist.each do |w|
111
112
  # Get header name which required user defined MTA module
112
- @@ExtHeaders[w] ||= {}
113
- @@ExtHeaders[w][v] = 1
113
+ extheaders[w] ||= {}
114
+ extheaders[w][v] = 1
114
115
  end
115
- @@ToBeLoaded << v
116
+ tobeloaded << v
116
117
  end
117
118
  end
118
119
 
119
120
  mtamodules.each do |e|
120
121
  # Append the custom order of MTA modules
121
- next if @@ToBeLoaded.index(e)
122
- @@ToBeLoaded << e
122
+ next if tobeloaded.index(e)
123
+ tobeloaded << e
123
124
  end
124
125
 
125
126
  # 0. Split email data to headers and a body part.
126
127
  aftersplit = Sisimai::Message.divideup(email)
127
128
  return nil if aftersplit.empty?
128
129
 
129
- # 1. Initialize variables for setting the value of each email header.
130
- @@TryOnFirst = []
131
-
132
- # 2. Convert email headers from text to hash reference
130
+ # 1. Convert email headers from text to hash reference
131
+ headerargv['extheaders'] = extheaders
132
+ headerargv['tryonfirst'] = []
133
133
  processing['from'] = aftersplit['from']
134
- processing['header'] = Sisimai::Message.headers(aftersplit['header'])
134
+ processing['header'] = Sisimai::Message.headers(aftersplit['header'], headerargv)
135
135
 
136
136
  # 3. Check headers for detecting MTA/MSP module
137
- if @@TryOnFirst.empty?
138
- @@TryOnFirst.concat(Sisimai::Message.makeorder(processing['header']))
137
+ if headerargv['tryonfirst'].empty?
138
+ headerargv['tryonfirst'].concat(Sisimai::Message.makeorder(processing['header']))
139
139
  end
140
140
 
141
141
  # 4. Rewrite message body for detecting the bounce reason
142
- methodargv = { 'mail' => processing, 'body' => aftersplit['body'] }
142
+ methodargv = {
143
+ 'mail' => processing,
144
+ 'body' => aftersplit['body'],
145
+ 'tryonfirst' => headerargv['tryonfirst'],
146
+ 'tobeloaded' => tobeloaded,
147
+ }
143
148
  bouncedata = Sisimai::Message.parse(methodargv)
144
149
 
145
150
  return nil unless bouncedata
@@ -180,6 +185,7 @@ module Sisimai
180
185
  hasdivided.each do |e|
181
186
  # Split email data to headers and a body part.
182
187
  e = e.delete("\r").delete("\n")
188
+ e = e.gsub(/[ \t]+\z/, '')
183
189
 
184
190
  if readcursor & Indicators[:endof] > 0
185
191
  # The body part of the email
@@ -208,19 +214,22 @@ module Sisimai
208
214
 
209
215
  # Convert email headers from text to hash reference
210
216
  # @param [String] heads Email header data
217
+ # @param [Hash] argvs
218
+ # @param options extheaders [Array] External header table
211
219
  # @return [Hash] Structured email header data
212
- def self.headers(heads)
220
+ def self.headers(heads, argvs = {})
213
221
  return nil unless heads
214
222
 
215
223
  currheader = ''
216
224
  allheaders = {}
217
225
  structured = {}
226
+ extheaders = argvs['extheaders'] || []
218
227
 
219
228
  HeaderList.each { |e| structured[e] = nil }
220
229
  HeaderList.each { |e| allheaders[e] = true }
221
230
  RFC3834Set.each { |e| allheaders[e] = true }
222
231
  MultiHeads.each_key { |e| structured[e.downcase] = [] }
223
- @@ExtHeaders.each_key { |e| allheaders[e] = true }
232
+ extheaders.each_key { |e| allheaders[e] = true }
224
233
 
225
234
  heads.split("\n").each do |e|
226
235
  # Convert email headers to hash
@@ -241,9 +250,12 @@ module Sisimai
241
250
 
242
251
  else
243
252
  # Other headers except "Received" and so on
244
- if @@ExtHeaders[currheader]
253
+ if extheaders[currheader]
245
254
  # MTA specific header
246
- @@TryOnFirst.concat(@@ExtHeaders[currheader].keys)
255
+ extheaders[currheader].keys.each do |r|
256
+ next if argvs['tryonfirst'].index(r)
257
+ argvs['tryonfirst'] << r
258
+ end
247
259
  end
248
260
  structured[currheader] = rhs
249
261
  end
@@ -277,12 +289,12 @@ module Sisimai
277
289
 
278
290
  # Try to match the value of "Subject" with patterns generated by
279
291
  # Sisimai::Order->by('subject') method
280
- @@PatternSet.each_key do |e|
292
+ PatternSet.each_key do |e|
281
293
  # Get MTA list from the subject header
282
294
  next unless heads['subject'] =~ e
283
295
 
284
296
  # Matched and push MTA list
285
- order.concat(@@PatternSet[e])
297
+ order.concat(PatternSet[e])
286
298
  break
287
299
  end
288
300
  return order
@@ -379,11 +391,14 @@ module Sisimai
379
391
  # @param options mail [String] rfc822 Original message part
380
392
  # @param options mail [Array] ds Delivery status list(parsed data)
381
393
  # @param options argvs [String] body Email message body
382
- # @param options argvs [Array] load MTA/MSP module list to load on first
394
+ # @param options argvs [Array] tryonfirst MTA/MSP module list to load on first
395
+ # @param options argvs [Array] tobeloaded User defined MTA module list
383
396
  # @return [Hash] Parsed and structured bounce mails
384
397
  def self.parse(argvs)
385
398
  mesgentity = argvs['mail']
386
399
  bodystring = argvs['body']
400
+ tryonfirst = argvs['tryonfirst'] || []
401
+ tobeloaded = argvs['tobeloaded'] || []
387
402
  mailheader = mesgentity['header']
388
403
 
389
404
  return nil unless argvs['mail']
@@ -443,7 +458,7 @@ module Sisimai
443
458
  throw :SCANNER if scannedset
444
459
  end
445
460
 
446
- @@ToBeLoaded.each do |r|
461
+ tobeloaded.each do |r|
447
462
  # Call user defined MTA modules
448
463
  next if haveloaded[r]
449
464
  begin
@@ -457,7 +472,7 @@ module Sisimai
457
472
  throw :SCANNER if scannedset
458
473
  end
459
474
 
460
- @@TryOnFirst.each do |r|
475
+ tryonfirst.each do |r|
461
476
  # Try MTA module candidates which are detected from MTA specific
462
477
  # mail headers on first
463
478
  next if haveloaded.key?(r)
@@ -472,7 +487,7 @@ module Sisimai
472
487
  throw :SCANNER if scannedset
473
488
  end
474
489
 
475
- @@DefaultSet.each do |r|
490
+ DefaultSet.each do |r|
476
491
  # MTA/MSP modules which does not have MTA specific header and did
477
492
  # not match with any regular expressions of Subject header.
478
493
  next if haveloaded.key?(r)
@@ -116,8 +116,8 @@ module Sisimai
116
116
  value = value.delete(%q|'"|)
117
117
  end
118
118
 
119
- value = sprintf( '--%s', value ) if start > -1
120
- value = sprintf( '%s--', value ) if start > 0
119
+ value = sprintf('--%s', value) if start > -1
120
+ value = sprintf('%s--', value) if start > 0
121
121
  return value
122
122
  end
123
123
  end
@@ -10,8 +10,8 @@ module Sisimai
10
10
  # @private
11
11
  def INDICATORS
12
12
  return {
13
- :'deliverystatus' => ( 1 << 1 ),
14
- :'message-rfc822' => ( 1 << 2 ),
13
+ :'deliverystatus' => (1 << 1),
14
+ :'message-rfc822' => (1 << 2),
15
15
  }
16
16
  end
17
17
 
@@ -45,7 +45,7 @@ module Sisimai
45
45
  'US::SendGrid', 'US::Verizon', 'RU::MailRu', 'RU::Yandex', 'DE::GMX',
46
46
  'US::Bigfoot', 'US::Facebook', 'US::Zoho', 'DE::EinsUndEins',
47
47
  'UK::MessageLabs', 'JP::EZweb', 'JP::KDDI', 'JP::Biglobe',
48
- 'US::ReceivingSES',
48
+ 'US::ReceivingSES', 'US::AmazonWorkMail', 'US::Office365',
49
49
  ]
50
50
  end
51
51
 
@@ -144,7 +144,7 @@ module Sisimai
144
144
  if mhead['received'].size > 0
145
145
  # Get localhost and remote host name from Received header.
146
146
  r0 = mhead['received']
147
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
147
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
148
148
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
149
149
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
150
150
  end
@@ -168,7 +168,7 @@ module Sisimai
168
168
  if mhead['received'].size > 0
169
169
  # Get localhost and remote host name from Received header.
170
170
  r0 = mhead['received']
171
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
171
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
172
172
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
173
173
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
174
174
  end
@@ -29,7 +29,7 @@ module Sisimai
29
29
 
30
30
  def description; return 'BIGLOBE: http://www.biglobe.ne.jp'; end
31
31
  def smtpagent; return 'JP::Biglobe'; end
32
- def headerlist; return ['']; end
32
+ def headerlist; return []; end
33
33
  def pattern; return Re0; end
34
34
 
35
35
  # Parse bounce messages from Biglobe
@@ -151,7 +151,7 @@ module Sisimai
151
151
  if mhead['received'].size > 0
152
152
  # Get localhost and remote host name from Received header.
153
153
  r0 = mhead['received']
154
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
154
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
155
155
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
156
156
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
157
157
  end
@@ -29,21 +29,21 @@ module Sisimai
29
29
  ReFailure = {
30
30
  #'notaccept' => [ %r/The following recipients did not receive this message:/ ],
31
31
  'mailboxfull' => [
32
- %r/The user[(]s[)] account is temporarily over quota/,
32
+ %r/The user[(]s[)] account is temporarily over quota/,
33
33
  ],
34
34
  'suspend' => [
35
- # http://www.naruhodo-au.kddi.com/qa3429203.html
36
- # The recipient may be unpaid user...?
37
- %r/The user[(]s[)] account is disabled[.]/,
38
- %r/The user[(]s[)] account is temporarily limited[.]/,
35
+ # http://www.naruhodo-au.kddi.com/qa3429203.html
36
+ # The recipient may be unpaid user...?
37
+ %r/The user[(]s[)] account is disabled[.]/,
38
+ %r/The user[(]s[)] account is temporarily limited[.]/,
39
39
  ],
40
40
  'expired' => [
41
- # Your message was not delivered within 0 days and 1 hours.
42
- # Remote host is not responding.
43
- %r/Your message was not delivered within /,
41
+ # Your message was not delivered within 0 days and 1 hours.
42
+ # Remote host is not responding.
43
+ %r/Your message was not delivered within /,
44
44
  ],
45
45
  'onhold' => [
46
- %r/Each of the following recipients was rejected by a remote mail server/,
46
+ %r/Each of the following recipients was rejected by a remote mail server/,
47
47
  ],
48
48
  }
49
49
  Indicators = Sisimai::MSP.INDICATORS
@@ -225,7 +225,7 @@ module Sisimai
225
225
  if mhead['received'].size > 0
226
226
  # Get localhost and remote host name from Received header.
227
227
  r0 = mhead['received']
228
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
228
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
229
229
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
230
230
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
231
231
  end
@@ -153,7 +153,7 @@ module Sisimai
153
153
  if mhead['received'].size > 0
154
154
  # Get localhost and remote host name from Received header.
155
155
  r0 = mhead['received']
156
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
156
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
157
157
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
158
158
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
159
159
  end
@@ -213,7 +213,7 @@ module Sisimai
213
213
  if mhead['received'].size > 0
214
214
  # Get localhost and remote host name from Received header.
215
215
  r0 = mhead['received']
216
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
216
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
217
217
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
218
218
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
219
219
  end
@@ -216,7 +216,7 @@ module Sisimai
216
216
  if mhead['received'].size > 0
217
217
  # Get localhost and remote host name from Received header.
218
218
  r0 = mhead['received']
219
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
219
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
220
220
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
221
221
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
222
222
  end
@@ -206,7 +206,7 @@ module Sisimai
206
206
  if mhead['received'].size > 0
207
207
  # Get localhost and remote host name from Received header.
208
208
  r0 = mhead['received']
209
- ['lhost', 'rhost'].each { |a| e[a] ||= '' }
209
+ %w|lhost rhost|.each { |a| e[a] ||= '' }
210
210
  e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
211
211
  e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
212
212
  end