mail 2.2.4 → 2.2.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mail might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +6 -0
- data/lib/VERSION +1 -1
- data/lib/mail/encodings.rb +25 -15
- data/lib/mail/fields/unstructured_field.rb +58 -45
- data/lib/mail/mail.rb +7 -0
- data/lib/mail/message.rb +2 -0
- data/lib/mail/network/retriever_methods/pop3.rb +10 -0
- data/lib/mail/parts_list.rb +10 -1
- metadata +3 -3
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== Thu 17 Jun 2010 22:13:18 UTC Mikel Lindsaar <mikel@rubyx.com>
|
2
|
+
|
3
|
+
* Added Mail::POP3.delete_all, including specs (Martijn Storck)
|
4
|
+
* Lars Pind updates on header folding
|
5
|
+
* Version bump to 2.2.5
|
6
|
+
|
1
7
|
== Tue Jun 8 01:55:21 UTC 2010 Mikel Lindsaar <mikel@rubyx.com>
|
2
8
|
|
3
9
|
* Added inline attachment support to mail (mikel)
|
data/lib/VERSION
CHANGED
data/lib/mail/encodings.rb
CHANGED
@@ -113,24 +113,34 @@ module Mail
|
|
113
113
|
#
|
114
114
|
# String has to be of the format =?<encoding>?[QB]?<string>?=
|
115
115
|
def Encodings.value_decode(str)
|
116
|
-
|
117
|
-
|
118
|
-
# Join QP encoded-words that are adjacent to avoid decoding partial chars
|
119
|
-
str.gsub!( /=\?==\?.+?\?[Qq]\?/m, '' ) if str =~ /\?==\?/
|
116
|
+
# Optimization: If there's no encoded-words in the string, just return it
|
117
|
+
return str unless str.index("=?")
|
120
118
|
|
121
|
-
str.gsub(
|
122
|
-
before = $1.to_s
|
123
|
-
text = $2.to_s
|
119
|
+
str = str.gsub(/\?=(\s*)=\?/, '?==?') # Remove whitespaces between 'encoded-word's
|
124
120
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
before + q_value_decode(text)
|
121
|
+
# Split on white-space boundaries with capture, so we capture the white-space as well
|
122
|
+
str.split(/([ \t])/).map do |text|
|
123
|
+
if text.index('=?') != 0
|
124
|
+
text
|
130
125
|
else
|
131
|
-
|
126
|
+
# Join QP encoded-words that are adjacent to avoid decoding partial chars
|
127
|
+
text.gsub!(/\?\=\=\?.+?\?[Qq]\?/m, '') if text =~ /\?==\?/
|
128
|
+
|
129
|
+
# Separate encoded-words with a space, so we can treat them one by one
|
130
|
+
text.gsub!(/\?\=\=\?/, '?= =?')
|
131
|
+
|
132
|
+
text.split(/ /).map do |word|
|
133
|
+
case
|
134
|
+
when word.to_str =~ /=\?.+\?[Bb]\?/m
|
135
|
+
b_value_decode(word)
|
136
|
+
when text.to_str =~ /=\?.+\?[Qq]\?/m
|
137
|
+
q_value_decode(word)
|
138
|
+
else
|
139
|
+
word.to_str
|
140
|
+
end
|
141
|
+
end
|
132
142
|
end
|
133
|
-
end
|
143
|
+
end.join("")
|
134
144
|
end
|
135
145
|
|
136
146
|
# Takes an encoded string of the format =?<encoding>?[QB]?<string>?=
|
@@ -214,7 +224,7 @@ module Mail
|
|
214
224
|
def Encodings.q_value_encode(str, encoding = nil)
|
215
225
|
return str if str.to_s.ascii_only?
|
216
226
|
string, encoding = RubyVer.q_value_encode(str, encoding)
|
217
|
-
string.gsub!("=\r\n
|
227
|
+
string.gsub!("=\r\n", '') # We already have limited the string to the length we want
|
218
228
|
string.each_line.map do |str|
|
219
229
|
"=?#{encoding}?Q?#{str.chomp.gsub(/ /, '_')}?="
|
220
230
|
end.join(" ")
|
@@ -102,64 +102,77 @@ module Mail
|
|
102
102
|
# it is allowed elsewhere.
|
103
103
|
def wrapped_value # :nodoc:
|
104
104
|
@folded_line = []
|
105
|
-
@unfolded_line = decoded.to_s.
|
105
|
+
@unfolded_line = decoded.to_s.split(/[ \t]/)
|
106
106
|
fold("#{name}: ".length)
|
107
107
|
wrap_lines(name, @folded_line)
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
|
+
# 6.2. Display of 'encoded-word's
|
111
|
+
#
|
112
|
+
# When displaying a particular header field that contains multiple
|
113
|
+
# 'encoded-word's, any 'linear-white-space' that separates a pair of
|
114
|
+
# adjacent 'encoded-word's is ignored. (This is to allow the use of
|
115
|
+
# multiple 'encoded-word's to represent long strings of unencoded text,
|
116
|
+
# without having to separate 'encoded-word's where spaces occur in the
|
117
|
+
# unencoded text.)
|
110
118
|
def wrap_lines(name, folded_lines)
|
111
119
|
result = []
|
112
120
|
index = 0
|
113
121
|
result[index] = "#{name}: #{folded_lines.shift}"
|
114
|
-
folded_lines
|
115
|
-
|
116
|
-
result[index] << " " + line
|
117
|
-
else
|
118
|
-
result[index] << "\r\n\s"
|
119
|
-
index += 1
|
120
|
-
result[index] = line
|
121
|
-
end
|
122
|
-
end
|
123
|
-
result.join
|
122
|
+
result.concat(folded_lines)
|
123
|
+
result.join("\r\n\s")
|
124
124
|
end
|
125
125
|
|
126
126
|
def fold(prepend = 0) # :nodoc:
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
127
|
+
encoding = @charset.to_s.upcase.gsub('_', '-')
|
128
|
+
while !@unfolded_line.empty?
|
129
|
+
encoded = false
|
130
|
+
limit = 78 - prepend
|
131
|
+
line = ""
|
132
|
+
while !@unfolded_line.empty?
|
133
|
+
break unless word = @unfolded_line.first.dup
|
134
|
+
# Remember whether it was non-ascii before we encode it ('cause then we can't tell anymore)
|
135
|
+
non_ascii = word.not_ascii_only?
|
136
|
+
encoded_word = encode(word)
|
137
|
+
# Skip to next line if we're going to go past the limit
|
138
|
+
# Unless this is the first word, in which case we're going to add it anyway
|
139
|
+
# Note: This means that a word that's longer than 998 characters is going to break the spec. Please fix if this is a problem for you.
|
140
|
+
# (The fix, it seems, would be to use encoded-word encoding on it, because that way you can break it across multiple lines and
|
141
|
+
# the linebreak will be ignored)
|
142
|
+
break if !line.empty? && (line.length + encoded_word.length + 1 > limit)
|
143
|
+
# If word was the first non-ascii word, we're going to make the entire line encoded and we're going to reduce the limit accordingly
|
144
|
+
if non_ascii && !encoded
|
145
|
+
encoded = true
|
146
|
+
encoded_word_safify!(line)
|
147
|
+
limit = limit - 8 - encoding.length # minus the =?...?Q?...?= part, the possible leading white-space, and the name of the encoding
|
148
|
+
end
|
149
|
+
# Remove the word from the queue ...
|
150
|
+
@unfolded_line.shift
|
151
|
+
# ... add it in encoded form to the current line
|
152
|
+
line << " " unless line.empty?
|
153
|
+
encoded_word_safify!(encoded_word) if encoded
|
154
|
+
line << encoded_word
|
155
|
+
end
|
156
|
+
# Add leading whitespace if both this and the last line were encoded, because whitespace between two encoded-words is ignored when decoding
|
157
|
+
line = " " + line if encoded && @folded_line.last && @folded_line.last.index('=?') == 0
|
158
|
+
# Encode the line if necessary
|
159
|
+
line = "=?#{encoding}?Q?#{line.gsub(/ /, '_')}?=" if encoded
|
160
|
+
# Add the line to the output and reset the prepend
|
161
|
+
@folded_line << line
|
162
|
+
prepend = 0
|
156
163
|
end
|
157
164
|
end
|
158
|
-
|
165
|
+
|
159
166
|
def encode(value)
|
160
|
-
value.gsub
|
161
|
-
|
162
|
-
|
167
|
+
(value.not_ascii_only? ? [value].pack("M").gsub("=\n", '') : value).gsub("\r", "=0D").gsub("\n", "=0A")
|
168
|
+
end
|
169
|
+
|
170
|
+
def encoded_word_safify!(value)
|
171
|
+
value.gsub!(/"/, '=22')
|
172
|
+
value.gsub!(/\(/, '=28')
|
173
|
+
value.gsub!(/\)/, '=29')
|
174
|
+
value.gsub!(/\?/, '=3F')
|
175
|
+
value.gsub!(/_/, '=5F')
|
163
176
|
end
|
164
177
|
|
165
178
|
end
|
data/lib/mail/mail.rb
CHANGED
@@ -170,6 +170,13 @@ module Mail
|
|
170
170
|
Mail.new(File.read(filename))
|
171
171
|
end
|
172
172
|
|
173
|
+
# Delete all emails from a POP3 server.
|
174
|
+
# See Mail::POP3 for a complete documentation.
|
175
|
+
def Mail.delete_all(*args, &block)
|
176
|
+
retriever_method.delete_all(*args, &block)
|
177
|
+
end
|
178
|
+
|
179
|
+
|
173
180
|
# Initialize the observers and interceptors arrays
|
174
181
|
@@delivery_notification_observers = []
|
175
182
|
@@delivery_interceptors = []
|
data/lib/mail/message.rb
CHANGED
@@ -118,6 +118,16 @@ module Mail
|
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
|
+
# Delete all emails from a POP3 server
|
122
|
+
def delete_all
|
123
|
+
start do |pop3|
|
124
|
+
unless pop3.mails.empty?
|
125
|
+
pop3.delete_all
|
126
|
+
pop3.finish
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
121
131
|
private
|
122
132
|
|
123
133
|
# Set default options
|
data/lib/mail/parts_list.rb
CHANGED
@@ -14,8 +14,17 @@ module Mail
|
|
14
14
|
to_a
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
undef :map
|
19
|
+
alias_method :map, :collect
|
17
20
|
|
18
|
-
|
21
|
+
def map!
|
22
|
+
raise NoMethodError, "#map! is not defined, please call #collect and create a new PartsList"
|
23
|
+
end
|
24
|
+
|
25
|
+
def collect!
|
26
|
+
raise NoMethodError, "#collect! is not defined, please call #collect and create a new PartsList"
|
27
|
+
end
|
19
28
|
|
20
29
|
def sort!(order)
|
21
30
|
sorted = self.sort do |a, b|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 2
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 2.2.
|
8
|
+
- 5
|
9
|
+
version: 2.2.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mikel Lindsaar
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-06-
|
17
|
+
date: 2010-06-17 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|