# encoding: UTF-8 module Vmail module ShowingMessage def current_message return unless @cur_message_id Message[@cur_message_id] end def current_mail (c = current_message) && Mail.new(c.rfc822) end def cached_full_message?(message_id) m = Message[message_id] if m log "- found message #{ message_id }" log "- message has plaintext? #{!m.plaintext.nil?}" else log "- could not find message #{ message_id.inspect }" end m && !m.plaintext.nil? && m end def show_message(message_id, raw=false) message_id = message_id.strip.gsub('\\', '') log "Show message: #{ message_id.inspect }" return current_message.rfc822 if raw res = retry_if_needed { fetch_and_cache(message_id) } log "Showing message message_id: #{ message_id }" @cur_message_id = message_id res end def fetch_and_cache(message_id) if message = cached_full_message?(message_id) log "- full message cache hit" return message.plaintext end log "- full message cache miss" params = { message_id: message_id, label_id: @label.label_id } labeling = Labeling[params] || Labeling.create(params) unless (labeling && labeling.uid) log "- Labeling not found for #{ params.inspect }" # break out early return "\nUnable to get message for #{ labeling.values }" end uid = labeling.uid log "- fetching message uid #{ uid }" fetch_data = reconnect_if_necessary do res = retry_if_needed do @imap.uid_fetch(uid, ["FLAGS", "RFC822", "RFC822.SIZE"]) end raise "Message uid #{ uid } could not be fetched from server" if res.nil? res[0] end seqno = fetch_data.seqno rfc822 = Mail.new(fetch_data.attr['RFC822']) formatter = Vmail::MessageFormatter.new rfc822 message = Message[message_id] parts_list = format_parts_info(formatter.list_parts) headers_hash = formatter.extract_headers headers_hash['date'] headers = format_headers headers_hash # replace the date value with the one derived from the envelope body = formatter.plaintext_part # [\w-]+ matches charsets like ISO-8851 if /charset=([\w-]+)/.match(parts_list) conv_from = /charset=([\w-]+)/.match(parts_list)[1].strip body = body.encode!('utf-8', conv_from, undef: :replace, invalid: :replace) else body = body.encode!('us-ascii', 'utf-8', undef: :replace, invalid: :replace) end message_text = <<-EOF #{ message_id } #{ number_to_human_size message.size } #{ message.flags } #{ parts_list } #{ divider '-' } #{ headers } #{ body } EOF # 2 calls so we can see more fine grained exceptions message.update(:rfc822 => rfc822) if !message_text.valid_encoding? message_text.encode!('utf-8', undef: :replace, invalid: :replace) end begin message.update(:plaintext => message_text) rescue log message_text.encoding #log message_text raise end message_text rescue msg = "Error encountered in fetch_and_cache(), message_id #{ message_id } [#@mailbox]:\n#{$!}\n#{$!.backtrace.join("\n")}" log msg msg end def format_parts_info(parts) lines = parts #.select {|part| part !~ %r{text/plain}} if lines.size > 0 "\n#{ lines.join("\n") }" end end end end