From c9046a2448bb6f4e08a8024d2b6637e2c12c23e5 Mon Sep 17 00:00:00 2001 From: Farid Bagishev Date: Wed, 7 Oct 2020 16:08:16 +0500 Subject: [PATCH 1/3] Convert RTF to HTML respecting original code page --- lib/mapi/mime.rb | 10 +++++++--- lib/mapi/rtf.rb | 16 +++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/mapi/mime.rb b/lib/mapi/mime.rb index 3271de8..3cf5e6f 100644 --- a/lib/mapi/mime.rb +++ b/lib/mapi/mime.rb @@ -69,6 +69,10 @@ def initialize str, ignore_body=false end end + def encode(x) + x.encoding == Encoding::UTF_8 ? x : x.encode('utf-8', 'cp1252') + end + def multipart? @content_type && @content_type =~ /^multipart/ ? true : false end @@ -97,7 +101,7 @@ def to_s opts={} opts = {:boundary_counter => 0}.merge opts if multipart? boundary = Mime.make_boundary opts[:boundary_counter] += 1, self - @body = [preamble, parts.map { |part| "\r\n" + part.to_s(opts) + "\r\n" }, "--\r\n" + epilogue]. + @body = [encode(preamble), parts.map { |part| "\r\n" + part.to_s(opts) + "\r\n" }, "--\r\n" + encode(epilogue)]. flatten.join("\r\n--" + boundary) content_type, attrs = Mime.split_header @headers['Content-Type'][0] attrs['boundary'] = boundary @@ -106,9 +110,9 @@ def to_s opts={} str = '' @headers.each do |key, vals| - vals.each { |val| str << "#{key}: #{val}\r\n" } + vals.each { |val| str << "#{encode(key)}: #{encode(val)}\r\n" } end - str << "\r\n" + @body + str << "\r\n" + encode(@body) end def self.split_header header diff --git a/lib/mapi/rtf.rb b/lib/mapi/rtf.rb index 4130066..e406049 100644 --- a/lib/mapi/rtf.rb +++ b/lib/mapi/rtf.rb @@ -122,7 +122,7 @@ def self.rtf2text str, format=:text end end - RTF_PREBUF = + RTF_PREBUF = "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \ "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript " \ "\\fdecor MS Sans SerifSymbolArialTimes New RomanCourier" \ @@ -175,7 +175,7 @@ def rtfdecompr data else # unknown magic number raise "Unknown compression type (magic number 0x%08x)" % magic end - + # not sure if its due to a bug in the above code. doesn't seem to be # in my tests, but sometimes there's a trailing null. we chomp it here, # which actually makes the resultant rtf smaller than its advertised @@ -189,7 +189,7 @@ def rtfdecompr data # # Returns +nil+ if it doesn't look like an rtf encapsulated rtf. # - # Some cases that the original didn't deal with have been patched up, eg from + # Some cases that the original didn't deal with have been patched up, eg from # this chunk, where there are tags outside of the htmlrtf ignore block. # # "{\\*\\htmltag116
}\\htmlrtf \\line \\htmlrtf0 \\line {\\*\\htmltag84 Date: Tue, 9 Nov 2021 15:50:39 +0300 Subject: [PATCH 2/3] Fix crash when date without timezone --- lib/mapi/convert/note-mime.rb | 7 +++---- lib/mapi/convert/note-tmail.rb | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/mapi/convert/note-mime.rb b/lib/mapi/convert/note-mime.rb index 7a4d010..8bb08a8 100644 --- a/lib/mapi/convert/note-mime.rb +++ b/lib/mapi/convert/note-mime.rb @@ -35,7 +35,7 @@ def populate_headers # headers, i think because one recipient was external. the only place the senders email address # exists is in the transport headers. so its maybe not good to overwrite from. # recipients however usually have smtp address available. - # maybe we'll do it for all addresses that are smtp? (is that equivalent to + # maybe we'll do it for all addresses that are smtp? (is that equivalent to # sender_email_address !~ /^\// name, email = props.sender_name, props.sender_email_address if props.sender_addrtype == 'SMTP' @@ -105,7 +105,7 @@ def populate_headers # i have no timezone info anyway. # in gmail, i see stuff like 15 Jan 2007 00:48:19 -0000, and it displays as 11:48. # can also add .localtime here if desired. but that feels wrong. - headers['Date'] = [Time.iso8601(time.to_s).rfc2822] if time + headers['Date'] = [time.rfc2822] if time end # some very simplistic mapping between internet message headers and the @@ -266,9 +266,8 @@ def populate_headers # can employ other methods for getting a time. heres one in a similar vein to msgconvert.pl, # ie taking the time from an ole object time = @root.ole.dirents.map { |dirent| dirent.modify_time || dirent.create_time }.compact.sort.last - headers['Date'] = [Time.iso8601(time.to_s).rfc2822] if time + headers['Date'] = [time.rfc2822] if time end end end end - diff --git a/lib/mapi/convert/note-tmail.rb b/lib/mapi/convert/note-tmail.rb index dfb6b28..e45e6aa 100644 --- a/lib/mapi/convert/note-tmail.rb +++ b/lib/mapi/convert/note-tmail.rb @@ -45,7 +45,7 @@ def populate_headers # headers, i think because one recipient was external. the only place the senders email address # exists is in the transport headers. so its maybe not good to overwrite from. # recipients however usually have smtp address available. - # maybe we'll do it for all addresses that are smtp? (is that equivalent to + # maybe we'll do it for all addresses that are smtp? (is that equivalent to # sender_email_address !~ /^\// name, email = props.sender_name, props.sender_email_address if props.sender_addrtype == 'SMTP' @@ -115,7 +115,7 @@ def populate_headers # i have no timezone info anyway. # in gmail, i see stuff like 15 Jan 2007 00:48:19 -0000, and it displays as 11:48. # can also add .localtime here if desired. but that feels wrong. - headers['Date'] = [Time.iso8601(time.to_s).rfc2822] if time + headers['Date'] = [time.rfc2822] if time end # some very simplistic mapping between internet message headers and the @@ -279,9 +279,8 @@ def populate_headers # can employ other methods for getting a time. heres one in a similar vein to msgconvert.pl, # ie taking the time from an ole object time = @root.ole.dirents.map { |dirent| dirent.modify_time || dirent.create_time }.compact.sort.last - headers['Date'] = [Time.iso8601(time.to_s).rfc2822] if time + headers['Date'] = [time.rfc2822] if time end end end end - From ea450e06878658abc3eab175c9b2abc71dd71a52 Mon Sep 17 00:00:00 2001 From: Pavel Ivchenko <44842298+pavelazazel@users.noreply.github.com> Date: Thu, 20 Jan 2022 14:46:09 +0300 Subject: [PATCH 3/3] Fix attachment converting --- lib/mapi/convert/note-mime.rb | 2 +- lib/mapi/convert/note-tmail.rb | 2 +- lib/mapi/version.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mapi/convert/note-mime.rb b/lib/mapi/convert/note-mime.rb index 8bb08a8..cd825a3 100644 --- a/lib/mapi/convert/note-mime.rb +++ b/lib/mapi/convert/note-mime.rb @@ -235,7 +235,7 @@ def to_mime # hmmm, have to use read here. that assumes that the data isa stream. # but if the attachment data is a string, then it won't work. possible? data_str = if @embedded_msg - mime.headers['Content-Type'] = 'message/rfc822' + mime.headers['Content-Type'] = ['message/rfc822'] # lets try making it not base64 for now mime.headers.delete 'Content-Transfer-Encoding' # not filename. rather name, or something else right? diff --git a/lib/mapi/convert/note-tmail.rb b/lib/mapi/convert/note-tmail.rb index e45e6aa..a7af527 100644 --- a/lib/mapi/convert/note-tmail.rb +++ b/lib/mapi/convert/note-tmail.rb @@ -248,7 +248,7 @@ def to_tmail # but if the attachment data is a string, then it won't work. possible? data_str = if @embedded_msg raise NotImplementedError - mime.headers['Content-Type'] = 'message/rfc822' + mime.headers['Content-Type'] = ['message/rfc822'] # lets try making it not base64 for now mime.headers.delete 'Content-Transfer-Encoding' # not filename. rather name, or something else right? diff --git a/lib/mapi/version.rb b/lib/mapi/version.rb index e94f97c..0653d07 100644 --- a/lib/mapi/version.rb +++ b/lib/mapi/version.rb @@ -1,3 +1,3 @@ module Mapi - VERSION = '1.5.2' + VERSION = '1.5.3' end