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
@@ -27,28 +27,26 @@ module Sisimai
27
27
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
28
28
  }
29
29
  ReFailure = {
30
- #'notaccept' => [ %r/The following recipients did not receive this message:/ ],
31
- 'mailboxfull' => [
30
+ # notaccept: [ %r/The following recipients did not receive this message:/ ],
31
+ mailboxfull: [
32
32
  %r/The user[(]s[)] account is temporarily over quota/,
33
33
  ],
34
- 'suspend' => [
34
+ suspend: [
35
35
  # http://www.naruhodo-au.kddi.com/qa3429203.html
36
36
  # The recipient may be unpaid user...?
37
37
  %r/The user[(]s[)] account is disabled[.]/,
38
38
  %r/The user[(]s[)] account is temporarily limited[.]/,
39
39
  ],
40
- 'expired' => [
40
+ expired: [
41
41
  # Your message was not delivered within 0 days and 1 hours.
42
42
  # Remote host is not responding.
43
43
  %r/Your message was not delivered within /,
44
44
  ],
45
- 'onhold' => [
45
+ onhold: [
46
46
  %r/Each of the following recipients was rejected by a remote mail server/,
47
47
  ],
48
48
  }
49
49
  Indicators = Sisimai::MSP.INDICATORS
50
- LongFields = Sisimai::RFC5322.LONGFIELDS
51
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
52
50
 
53
51
  def description; return 'au EZweb: http://www.au.kddi.com/mobile/'; end
54
52
  def smtpagent; return 'JP::EZweb'; end
@@ -81,11 +79,10 @@ module Sisimai
81
79
 
82
80
  require 'sisimai/string'
83
81
  require 'sisimai/address'
84
- dscontents = []; dscontents << Sisimai::MSP.DELIVERYSTATUS
82
+ dscontents = [Sisimai::MSP.DELIVERYSTATUS]
85
83
  hasdivided = mbody.split("\n")
86
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
87
- rfc822part = '' # (String) message/rfc822-headers part
88
- previousfn = '' # (String) Previous field name
84
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
85
+ blanklines = 0 # (Integer) The number of blank lines
89
86
  readcursor = 0 # (Integer) Points the current cursor position
90
87
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
91
88
  rxboundary = %r/\A__SISIMAI_PSEUDO_BOUNDARY__\z/
@@ -108,7 +105,7 @@ module Sisimai
108
105
  if readcursor == 0
109
106
  # Beginning of the bounce message or delivery status part
110
107
  if e =~ Re1[:begin]
111
- readcursor |= Indicators[:'deliverystatus']
108
+ readcursor |= Indicators[:deliverystatus]
112
109
  end
113
110
  end
114
111
 
@@ -122,30 +119,16 @@ module Sisimai
122
119
 
123
120
  if readcursor & Indicators[:'message-rfc822'] > 0
124
121
  # After "message/rfc822"
125
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
126
- # Get required headers only
127
- lhs = cv[1].downcase
128
- previousfn = ''
129
- next unless RFC822Head.key?(lhs)
130
-
131
- previousfn = lhs
132
- rfc822part += e + "\n"
133
-
134
- elsif e =~ /\A[ \t]+/
135
- # Continued line from the previous line
136
- next if rfc822next[previousfn]
137
- rfc822part += e + "\n" if LongFields.key?(previousfn)
138
-
139
- else
140
- # Check the end of headers in rfc822 part
141
- next unless LongFields.key?(previousfn)
142
- next unless e.empty?
143
- rfc822next[previousfn] = true
122
+ if e.empty?
123
+ blanklines += 1
124
+ break if blanklines > 1
125
+ next
144
126
  end
127
+ rfc822list << e
145
128
 
146
129
  else
147
130
  # Before "message/rfc822"
148
- next if readcursor & Indicators[:'deliverystatus'] == 0
131
+ next if readcursor & Indicators[:deliverystatus] == 0
149
132
  next if e.empty?
150
133
 
151
134
  # The user(s) account is disabled.
@@ -162,8 +145,8 @@ module Sisimai
162
145
  v = dscontents[-1]
163
146
 
164
147
  if cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>]\z/) ||
165
- cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>]:?(.*)\z/) ||
166
- cv = e.match(/\A[ \t]+Recipient: [<]([^ ]+[@][^ ]+)[>]/)
148
+ e.match(/\A[<]([^ ]+[@][^ ]+)[>]:?(.*)\z/) ||
149
+ e.match(/\A[ \t]+Recipient: [<]([^ ]+[@][^ ]+)[>]/)
167
150
 
168
151
  if v['recipient']
169
152
  # There are multiple recipient addresses in the message body.
@@ -217,19 +200,9 @@ module Sisimai
217
200
  end
218
201
  end
219
202
  end
220
-
221
203
  return nil if recipients == 0
222
- require 'sisimai/smtp/status'
223
204
 
224
205
  dscontents.map do |e|
225
- if mhead['received'].size > 0
226
- # Get localhost and remote host name from Received header.
227
- r0 = mhead['received']
228
- %w|lhost rhost|.each { |a| e[a] ||= '' }
229
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
230
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
231
- end
232
-
233
206
  if e['alterrors'] && e['alterrors'].size > 0
234
207
  # Copy alternative error message
235
208
  e['diagnosis'] ||= e['alterrors']
@@ -259,7 +232,7 @@ module Sisimai
259
232
  ReFailure[r].each do |rr|
260
233
  # Check each regular expression
261
234
  next unless e['diagnosis'] =~ rr
262
- e['reason'] = r
235
+ e['reason'] = r.to_s
263
236
  throw :SESSION
264
237
  end
265
238
  end
@@ -276,13 +249,10 @@ module Sisimai
276
249
  e['reason'] = 'userunknown'
277
250
  end
278
251
  end
279
-
280
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
281
- e['spec'] = 'SMTP'
282
- e['action'] = 'failed' if e['status'] =~ /\A[45]/
283
- e['agent'] = Sisimai::MSP::JP::EZweb.smtpagent
252
+ e['agent'] = Sisimai::MSP::JP::EZweb.smtpagent
284
253
  end
285
254
 
255
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
286
256
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
287
257
  end
288
258
 
@@ -24,15 +24,12 @@ module Sisimai
24
24
  :error => %r/Could not be delivered to:? /,
25
25
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
26
26
  }
27
-
28
27
  ReFailure = {
29
- 'mailboxfull' => %r/As[ ]their[ ]mailbox[ ]is[ ]full/x,
30
- 'norelaying' => %r/Due[ ]to[ ]the[ ]following[ ]SMTP[ ]relay[ ]error/x,
31
- 'hostunknown' => %r/As[ ]the[ ]remote[ ]domain[ ]doesnt[ ]exist/x,
28
+ mailboxfull: %r/As[ ]their[ ]mailbox[ ]is[ ]full/x,
29
+ norelaying: %r/Due[ ]to[ ]the[ ]following[ ]SMTP[ ]relay[ ]error/x,
30
+ hostunknown: %r/As[ ]the[ ]remote[ ]domain[ ]doesnt[ ]exist/x,
32
31
  }
33
32
  Indicators = Sisimai::MSP.INDICATORS
34
- LongFields = Sisimai::RFC5322.LONGFIELDS
35
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
36
33
 
37
34
  def description; return 'au by KDDI: http://www.au.kddi.com'; end
38
35
  def smtpagent; return 'JP::KDDI'; end
@@ -63,11 +60,10 @@ module Sisimai
63
60
  require 'sisimai/string'
64
61
  require 'sisimai/address'
65
62
 
66
- dscontents = []; dscontents << Sisimai::MSP.DELIVERYSTATUS
63
+ dscontents = [Sisimai::MSP.DELIVERYSTATUS]
67
64
  hasdivided = mbody.split("\n")
68
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
69
- rfc822part = '' # (String) message/rfc822-headers part
70
- previousfn = '' # (String) Previous field name
65
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
66
+ blanklines = 0 # (Integer) The number of blank lines
71
67
  readcursor = 0 # (Integer) Points the current cursor position
72
68
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
73
69
  v = nil
@@ -76,7 +72,7 @@ module Sisimai
76
72
  if readcursor == 0
77
73
  # Beginning of the bounce message or delivery status part
78
74
  if e =~ Re1[:begin]
79
- readcursor |= Indicators[:'deliverystatus']
75
+ readcursor |= Indicators[:deliverystatus]
80
76
  next
81
77
  end
82
78
  end
@@ -91,30 +87,16 @@ module Sisimai
91
87
 
92
88
  if readcursor & Indicators[:'message-rfc822'] > 0
93
89
  # After "message/rfc822"
94
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
95
- # Get required headers only
96
- lhs = cv[1].downcase
97
- previousfn = ''
98
- next unless RFC822Head.key?(lhs)
99
-
100
- previousfn = lhs
101
- rfc822part += e + "\n"
102
-
103
- elsif e =~ /\A[ \t]+/
104
- # Continued line from the previous line
105
- next if rfc822next[previousfn]
106
- rfc822part += e + "\n" if LongFields.key?(previousfn)
107
-
108
- else
109
- # Check the end of headers in rfc822 part
110
- next unless LongFields.key?(previousfn)
111
- next unless e.empty?
112
- rfc822next[previousfn] = true
90
+ if e.empty?
91
+ blanklines += 1
92
+ break if blanklines > 1
93
+ next
113
94
  end
95
+ rfc822list << e
114
96
 
115
97
  else
116
98
  # Before "message/rfc822"
117
- next if readcursor & Indicators[:'deliverystatus'] == 0
99
+ next if readcursor & Indicators[:deliverystatus] == 0
118
100
  next if e.empty?
119
101
 
120
102
  v = dscontents[-1]
@@ -150,13 +132,7 @@ module Sisimai
150
132
  require 'sisimai/smtp/status'
151
133
 
152
134
  dscontents.map do |e|
153
- if mhead['received'].size > 0
154
- # Get localhost and remote host name from Received header.
155
- r0 = mhead['received']
156
- %w|lhost rhost|.each { |a| e[a] ||= '' }
157
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
158
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
159
- end
135
+ e['agent'] = Sisimai::MSP::JP::KDDI.smtpagent
160
136
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
161
137
 
162
138
  if mhead['x-spasign'] && mhead['x-spasign'] == 'NG'
@@ -174,18 +150,15 @@ module Sisimai
174
150
  ReFailure.each_key do |r|
175
151
  # Verify each regular expression of session errors
176
152
  next unless e['diagnosis'] =~ ReFailure[r]
177
- e['reason'] = r
153
+ e['reason'] = r.to_s
178
154
  break
179
155
  end
180
156
  end
181
157
  end
182
158
 
183
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
184
- e['spec'] = 'SMTP'
185
- e['action'] = 'failed' if e['status'] =~ /\A[45]/
186
- e['agent'] = Sisimai::MSP::JP::KDDI.smtpagent
187
159
  end
188
160
 
161
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
189
162
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
190
163
  end
191
164
 
@@ -33,15 +33,13 @@ module Sisimai
33
33
  %r/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,
34
34
  ]
35
35
  ReFailure = {
36
- 'expired' => %r{(?:
36
+ expired: %r{(?:
37
37
  retry[ ]timeout[ ]exceeded
38
38
  |No[ ]action[ ]is[ ]required[ ]on[ ]your[ ]part
39
39
  )
40
40
  }x,
41
- 'userunknown' => %r{
42
- user[ ]not[ ]found
43
- }x,
44
- 'hostunknown' => %r{(?>
41
+ userunknown: %r/user[ ]not[ ]found/x,
42
+ hostunknown: %r{(?>
45
43
  all[ ](?:
46
44
  host[ ]address[ ]lookups[ ]failed[ ]permanently
47
45
  |relevant[ ]MX[ ]records[ ]point[ ]to[ ]non[-]existent[ ]hosts
@@ -49,28 +47,20 @@ module Sisimai
49
47
  |Unrouteable[ ]address
50
48
  )
51
49
  }x,
52
- 'mailboxfull' => %r{(?:
53
- mailbox[ ]is[ ]full:?
54
- |error:[ ]quota[ ]exceed
55
- )
56
- }x,
57
- 'notaccept' => %r{(?:
50
+ mailboxfull: %r/(?:mailbox[ ]is[ ]full:?|error:[ ]quota[ ]exceed)/x,
51
+ notaccept: %r{(?:
58
52
  an[ ]MX[ ]or[ ]SRV[ ]record[ ]indicated[ ]no[ ]SMTP[ ]service
59
53
  |no[ ]host[ ]found[ ]for[ ]existing[ ]SMTP[ ]connection
60
54
  )
61
55
  }x,
62
- 'systemerror' => %r{(?:
56
+ systemerror: %r{(?:
63
57
  delivery[ ]to[ ](?:file|pipe)[ ]forbidden
64
58
  |local[ ]delivery[ ]failed
65
59
  )
66
60
  }x,
67
- 'contenterror' => %r{
68
- Too[ ]many[ ]["]Received["][ ]headers[ ]
69
- }x,
61
+ contenterror: %r/Too[ ]many[ ]["]Received["][ ]headers[ ]/x,
70
62
  }
71
63
  Indicators = Sisimai::MSP.INDICATORS
72
- LongFields = Sisimai::RFC5322.LONGFIELDS
73
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
74
64
 
75
65
  def description; return '@mail.ru: https://mail.ru'; end
76
66
  def smtpagent; return 'RU::MailRu'; end
@@ -95,11 +85,10 @@ module Sisimai
95
85
  return nil unless mhead['subject'] =~ Re0[:subject]
96
86
  return nil unless mhead['message-id'] =~ Re0[:'message-id']
97
87
 
98
- dscontents = []; dscontents << Sisimai::MSP.DELIVERYSTATUS
88
+ dscontents = [Sisimai::MSP.DELIVERYSTATUS]
99
89
  hasdivided = mbody.split("\n")
100
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
101
- rfc822part = '' # (String) message/rfc822-headers part
102
- previousfn = '' # (String) Previous field name
90
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
91
+ blanklines = 0 # (Integer) The number of blank lines
103
92
  readcursor = 0 # (Integer) Points the current cursor position
104
93
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
105
94
  localhost0 = '' # (String) Local MTA
@@ -109,7 +98,7 @@ module Sisimai
109
98
  if readcursor == 0
110
99
  # Beginning of the bounce message or delivery status part
111
100
  if e =~ Re1[:begin]
112
- readcursor |= Indicators[:'deliverystatus']
101
+ readcursor |= Indicators[:deliverystatus]
113
102
  next
114
103
  end
115
104
  end
@@ -124,30 +113,17 @@ module Sisimai
124
113
 
125
114
  if readcursor & Indicators[:'message-rfc822'] > 0
126
115
  # After "message/rfc822"
127
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
128
- # Get required headers only
129
- lhs = cv[1].downcase
130
- previousfn = ''
131
- next unless RFC822Head.key?(lhs)
132
-
133
- previousfn = lhs
134
- rfc822part += e + "\n"
135
-
136
- elsif e =~ /\A[ \t]+/
137
- # Continued line from the previous line
138
- next if rfc822next[previousfn]
139
- rfc822part += e + "\n" if LongFields.key?(previousfn)
140
-
141
- else
142
- # Check the end of headers in rfc822 part
143
- next unless LongFields.key?(previousfn)
144
- next unless e.empty?
145
- rfc822next[previousfn] = true
116
+ # After "message/rfc822"
117
+ if e.empty?
118
+ blanklines += 1
119
+ break if blanklines > 1
120
+ next
146
121
  end
122
+ rfc822list << e
147
123
 
148
124
  else
149
125
  # Before "message/rfc822"
150
- next if readcursor & Indicators[:'deliverystatus'] == 0
126
+ next if readcursor & Indicators[:deliverystatus] == 0
151
127
  next if e.empty?
152
128
 
153
129
  # Это письмо создано автоматически
@@ -226,7 +202,6 @@ module Sisimai
226
202
  end
227
203
  end
228
204
  require 'sisimai/string'
229
- require 'sisimai/smtp/status'
230
205
 
231
206
  dscontents.map do |e|
232
207
  # Set default values if each value is empty.
@@ -283,19 +258,16 @@ module Sisimai
283
258
  ReFailure.each_key do |r|
284
259
  # Check each regular expression
285
260
  next unless e['diagnosis'] =~ ReFailure[r]
286
- e['reason'] = r
261
+ e['reason'] = r.to_s
287
262
  break
288
263
  end
289
264
  end
290
265
  end
291
-
292
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
293
- e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
294
- e['action'] = 'failed' if e['status'] =~ /\A[45]/
295
266
  e['command'] ||= ''
296
267
  e['agent'] = Sisimai::MSP::RU::MailRu.smtpagent
297
268
  end
298
269
 
270
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
299
271
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
300
272
  end
301
273
 
@@ -17,8 +17,6 @@ module Sisimai
17
17
  :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
18
18
  }
19
19
  Indicators = Sisimai::MSP.INDICATORS
20
- LongFields = Sisimai::RFC5322.LONGFIELDS
21
- RFC822Head = Sisimai::RFC5322.HEADERFIELDS
22
20
 
23
21
  def description; return 'Yandex.Mail: http://www.yandex.ru'; end
24
22
  def smtpagent; return 'RU::Yandex'; end
@@ -50,12 +48,11 @@ module Sisimai
50
48
  return nil unless mhead['x-yandex-uniq']
51
49
  return nil unless mhead['from'] =~ Re0[:from]
52
50
 
53
- dscontents = []; dscontents << Sisimai::MSP.DELIVERYSTATUS
51
+ dscontents = [Sisimai::MSP.DELIVERYSTATUS]
54
52
  hasdivided = mbody.split("\n")
55
- havepassed = [''];
56
- rfc822next = { 'from' => false, 'to' => false, 'subject' => false }
57
- rfc822part = '' # (String) message/rfc822-headers part
58
- previousfn = '' # (String) Previous field name
53
+ havepassed = ['']
54
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
55
+ blanklines = 0 # (Integer) The number of blank lines
59
56
  readcursor = 0 # (Integer) Points the current cursor position
60
57
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
61
58
  commandset = [] # (Array) ``in reply to * command'' list
@@ -68,12 +65,13 @@ module Sisimai
68
65
 
69
66
  hasdivided.each do |e|
70
67
  # Save the current line for the next loop
71
- havepassed << e; p = havepassed[-2]
68
+ havepassed << e
69
+ p = havepassed[-2]
72
70
 
73
71
  if readcursor == 0
74
72
  # Beginning of the bounce message or delivery status part
75
73
  if e =~ Re1[:begin]
76
- readcursor |= Indicators[:'deliverystatus']
74
+ readcursor |= Indicators[:deliverystatus]
77
75
  next
78
76
  end
79
77
  end
@@ -88,30 +86,16 @@ module Sisimai
88
86
 
89
87
  if readcursor & Indicators[:'message-rfc822'] > 0
90
88
  # After "message/rfc822"
91
- if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*.+\z/)
92
- # Get required headers only
93
- lhs = cv[1].downcase
94
- previousfn = ''
95
- next unless RFC822Head.key?(lhs)
96
-
97
- previousfn = lhs
98
- rfc822part += e + "\n"
99
-
100
- elsif e =~ /\A[ \t]+/
101
- # Continued line from the previous line
102
- next if rfc822next[previousfn]
103
- rfc822part += e + "\n" if LongFields.key?(previousfn)
104
-
105
- else
106
- # Check the end of headers in rfc822 part
107
- next unless LongFields.key?(previousfn)
108
- next unless e.empty?
109
- rfc822next[previousfn] = true
89
+ if e.empty?
90
+ blanklines += 1
91
+ break if blanklines > 1
92
+ next
110
93
  end
94
+ rfc822list << e
111
95
 
112
96
  else
113
97
  # Before "message/rfc822"
114
- next if readcursor & Indicators[:'deliverystatus'] == 0
98
+ next if readcursor & Indicators[:deliverystatus] == 0
115
99
  next if e.empty?
116
100
 
117
101
  if connvalues == connheader.keys.size
@@ -200,37 +184,19 @@ module Sisimai
200
184
 
201
185
  end
202
186
  end
203
-
204
187
  return nil if recipients == 0
205
188
  require 'sisimai/string'
206
- require 'sisimai/smtp/status'
207
189
 
208
190
  dscontents.map do |e|
209
191
  # Set default values if each value is empty.
210
192
  connheader.each_key { |a| e[a] ||= connheader[a] || '' }
211
- e['command'] = commandset.shift || ''
212
-
213
- if mhead['received'].size > 0
214
- # Get localhost and remote host name from Received header.
215
- r0 = mhead['received']
216
- %w|lhost rhost|.each { |a| e[a] ||= '' }
217
- e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
218
- e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
219
- end
193
+ e['command'] = commandset.shift || ''
220
194
  e['diagnosis'] = e['diagnosis'].gsub(/\\n/, '')
221
195
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
222
-
223
- e['status'] ||= ''
224
- if e['status'].empty? || e['status'] =~ /\A\d[.]0[.]0\z/
225
- # There is no value of Status header or the value is 5.0.0, 4.0.0
226
- r = Sisimai::SMTP::Status.find(e['diagnosis'])
227
- e['status'] = r if r.size > 0
228
- end
229
-
230
- e['spec'] = 'SMTP'
231
- e['agent'] = Sisimai::MSP::RU::Yandex.smtpagent
196
+ e['agent'] = Sisimai::MSP::RU::Yandex.smtpagent
232
197
  end
233
198
 
199
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
234
200
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
235
201
  end
236
202