Permalink
Browse files

Refactor in Mail::Encodings, also body now auto decodes itself on #de…

…coded
  • Loading branch information...
1 parent 090e0e2 commit cdf44012ba8bc241be41867aacac5d9a0d20e72c @mikel committed Nov 21, 2009
View
@@ -1,3 +1,7 @@
+== Sat Nov 21 12:52:46 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
+
+* Changed Mail::Encodings to clean it up, added in unquote_and_convert_to as well as refactor in this area
+
== Thu Nov 19 04:16:10 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
* Added sendmail support from (Simon Rozet)
View
@@ -56,7 +56,13 @@ def encoded
# Returns the raw source right now. Need to implement
def decoded
- raw_source.to_lf
+ if encoding.nil?
+ raw_source.to_lf
+ else
+ if Encodings.defined?(encoding)
+ Encodings.get_encoding(encoding).decode(raw_source)
+ end
+ end
end
def charset
@@ -88,18 +88,49 @@ def Encodings.decode_encode(str, output_type)
# Decodes a given string as Base64 or Quoted Printable, depending on what
# type it is.
#
- #
+ # String has to be of the format =?<encoding>?[QB]?<string>?=
def Encodings.value_decode(str)
- case
- when str =~ /\=\?.+?\?B\?.+?\?\=/
- Encodings.b_value_decode(str)
- when str =~ /\=\?.+?\?Q\?.+?\?\=/
- Encodings.q_value_decode(str)
- else
- str
+ str.gsub!(/\?=(\s*)=\?/, '?==?') # Remove whitespaces between 'encoded-word's
+ str.gsub(/(.*?)(=\?.*?\?.\?.*?\?=)|$/) do
+ before = $1.to_s
+ text = $2.to_s
+
+ case
+ when text =~ /=\?.+\?[Bb]\?/
+ before + b_value_decode(text)
+ when text =~ /=\?.+\?[Qq]\?/
+ before + q_value_decode(text)
+ else
+ before + text
+ end
end
end
+
+ # Takes an encoded string of the format =?<encoding>?[QB]?<string>?=
+ def Encodings.unquote_and_convert_to(str, to_encoding)
+ original_encoding, string = split_encoding_from_string( str )
+
+ output = value_decode( str ).to_s
+ if original_encoding.to_s.downcase.gsub("-", "") == to_encoding.to_s.downcase.gsub("-", "")
+ output
+ elsif original_encoding && to_encoding
+ begin
+ Iconv.iconv(to_encoding, original_encoding, output).first
+ rescue Iconv::IllegalSequence, Iconv::InvalidEncoding, Errno::EINVAL
+ # the 'from' parameter specifies a charset other than what the text
+ # actually is...not much we can do in this case but just return the
+ # unconverted text.
+ #
+ # Ditto if either parameter represents an unknown charset, like
+ # X-UNKNOWN.
+ output
+ end
+ else
+ output
+ end
+ end
+
# Encode a string with Base64 Encoding and returns it ready to be inserted
# as a value for a field, that is, in the =?<charset>?B?<string>?= format
#
@@ -114,19 +145,6 @@ def Encodings.b_value_encode(str, encoding = nil)
end.join(" ")
end
- # Decodes a Base64 string from the "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=" format
- #
- # Example:
- #
- # Encodings.b_value_encode("=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=")
- # #=> 'This is あ string'
- def Encodings.b_value_decode(str)
- string = str.split(Mail::Patterns::WSP)
- string.flatten.map do |s|
- RubyVer.b_value_decode(s)
- end.join('')
- end
-
# Encode a string with Quoted-Printable Encoding and returns it ready to be inserted
# as a value for a field, that is, in the =?<charset>?Q?<string>?= format
#
@@ -139,20 +157,36 @@ def Encodings.q_value_encode(str, encoding = nil)
"=?#{encoding}?Q?#{string.chomp}?="
end
+ private
+
+ # Decodes a Base64 string from the "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=" format
+ #
+ # Example:
+ #
+ # Encodings.b_value_encode("=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=")
+ # #=> 'This is あ string'
+ def Encodings.b_value_decode(str)
+ RubyVer.b_value_decode(str)
+ end
+
# Decodes a Quoted-Printable string from the "=?UTF-8?Q?This_is_=E3=81=82_string?=" format
#
# Example:
#
# Encodings.b_value_encode("=?UTF-8?Q?This_is_=E3=81=82_string?=")
# #=> 'This is あ string'
def Encodings.q_value_decode(str)
- string = str.split(Mail::Patterns::WSP)
- string.flatten.map do |s|
- RubyVer.q_value_decode(s)
- end.join('')
+ RubyVer.q_value_decode(str)
end
- private
+ def Encodings.split_encoding_from_string( str )
+ match = str.match(/\=\?(.+)?\?[QB]\?(.+)?\?\=/i)
+ if match
+ [match[1], match[2]]
+ else
+ nil
+ end
+ end
def Encodings.find_encoding(str)
RUBY_VERSION >= '1.9' ? str.encoding : $KCODE
View
@@ -183,6 +183,7 @@ def body=(value)
else
@body = Mail::Body.new(value)
end
+ add_encoding_to_body
end
# Returns the body of the message object. Or, if passed
@@ -196,7 +197,12 @@ def body=(value)
# mail.body 'This is another body'
# mail.body #=> #<Mail::Body:0x13919c @raw_source="This is anothe...
def body(value = nil)
- value ? self.body = value : @body
+ if value
+ self.body = value
+ add_encoding_to_body
+ else
+ @body
+ end
end
# Sets the to filed of the message header.
@@ -769,6 +775,12 @@ def separate_parts
body.split!(boundary)
end
+ def add_encoding_to_body
+ unless content_transfer_encoding.blank?
+ body.encoding = content_transfer_encoding.decoded
+ end
+ end
+
def add_required_fields
@body = Mail::Body.new('') if body.nil?
add_message_id unless (has_message_id? || self.class == Mail::Part)
@@ -45,7 +45,7 @@ def Ruby18.b_value_encode(str, encoding)
end
def Ruby18.b_value_decode(str)
- match = str.match(/\=\?(.+)?\?B\?(.+)?\?\=/)
+ match = str.match(/\=\?(.+)?\?[Bb]\?(.+)?\?\=/)
if match
encoding = match[1]
str = Ruby18.decode_base64(match[2])
@@ -61,7 +61,7 @@ def Ruby18.q_value_encode(str, encoding)
end
def Ruby18.q_value_decode(str)
- match = str.match(/\=\?(.+)?\?Q\?(.+)?\?\=/)
+ match = str.match(/\=\?(.+)?\?[Qq]\?(.+)?\?\=/)
if match
encoding = match[1]
str = Encodings::QuotedPrintable.decode(match[2])
@@ -37,7 +37,7 @@ def Ruby19.b_value_encode(str, encoding = nil)
end
def Ruby19.b_value_decode(str)
- match = str.match(/\=\?(.+)?\?B\?(.+)?\?\=/)
+ match = str.match(/\=\?(.+)?\?[Bb]\?(.+)?\?\=/)
if match
encoding = match[1]
str = Ruby19.decode_base64(match[2])
@@ -52,7 +52,7 @@ def Ruby19.q_value_encode(str, encoding = nil)
end
def Ruby19.q_value_decode(str)
- match = str.match(/\=\?(.+)?\?Q\?(.+)?\?\=/)
+ match = str.match(/\=\?(.+)?\?[Qq]\?(.+)?\?\=/)
if match
encoding = match[1]
str = Encodings::QuotedPrintable.decode(match[2])
View
@@ -75,10 +75,29 @@
end
describe "decoding" do
+
it "should convert all new lines to crlf" do
body = Mail::Body.new("This has \n various \r new \r\n lines")
body.decoded.should == "This has \n various \n new \n lines"
end
+
+ it "should not change a body on decode if not given an encoding type to decode" do
+ body = Mail::Body.new("The=3Dbody")
+ body.decoded.should == "The=3Dbody"
+ end
+
+ it "should change a body on decode if given an encoding type to decode" do
+ body = Mail::Body.new("The=3Dbody")
+ body.encoding = 'quoted-printable'
+ body.decoded.should == "The=body"
+ end
+
+ it "should change a body on decode if given an encoding type to decode" do
+ body = Mail::Body.new("VGhlIGJvZHk=\n")
+ body.encoding = 'base64'
+ body.decoded.should == "The body"
+ end
+
end
describe "splitting up a multipart document" do
Oops, something went wrong.

0 comments on commit cdf4401

Please sign in to comment.