# frozen_string_literal: true # A very simple formatter for imported emails class EmailCook def self.url_regexp @url_regexp ||= /((?:https?:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.])(?:[^\s()<>]+|\([^\s()<>]+\))+(?:\([^\s()<>]+\)|[^`!()\[\]{};:'".,<>?«»“”‘’\s]))/ end def self.raw_regexp @raw_regexp ||= /^\[plaintext\]$\n(.*)\n^\[\/plaintext\]$(?:\s^\[attachments\]$\n(.*)\n^\[\/attachments\]$)?(?:\s^\[elided\]$\n(.*)\n^\[\/elided\]$)?/m end def initialize(raw) @raw = raw @body, @attachment_html, @elided = @raw.scan(EmailCook.raw_regexp).first end def add_quote(result, buffer) if buffer.present? return if buffer =~ /\A(<br>)+\z$/ result << "<blockquote>#{buffer}</blockquote>" end end def link_string!(line, unescaped_line) unescaped_line = unescaped_line.strip unescaped_line.scan(EmailCook.url_regexp).each do |m| url = m[0] if unescaped_line == url # this could be oneboxed val = %|<a href="#{url}" class="onebox" target="_blank">#{url}</a>| else val = %|<a href="#{url}">#{url}</a>| end line.gsub!(url, val) end end def htmlify(text) result = +"" quote_buffer = +"" in_text = false in_quote = false text.each_line do |line| # replace indentation with non-breaking spaces line.sub!(/^\s{2,}/) { |s| "\u00A0" * s.length } if line =~ /^\s*>/ in_quote = true line.sub!(/^[\s>]*/, '') unescaped_line = line line = CGI.escapeHTML(line) link_string!(line, unescaped_line) quote_buffer << line << "<br>" elsif in_quote add_quote(result, quote_buffer) quote_buffer = "" in_quote = false else sz = line.size unescaped_line = line line = CGI.escapeHTML(line) link_string!(line, unescaped_line) if sz < 60 if in_text && line == "\n" result << "<br>" end result << line result << "<br>" in_text = false else result << line in_text = true end end end if in_quote && quote_buffer.present? add_quote(result, quote_buffer) end result.gsub!(/(<br>\n*){3,10}/, '<br><br>') result end def cook(opts = {}) # fallback to PrettyText if we failed to detect a body return PrettyText.cook(@raw, opts) if @body.nil? result = htmlify(@body) result << "\n<br>" << @attachment_html if @attachment_html.present? result << "\n<br><br>" << Email::Receiver.elided_html(htmlify(@elided)) if @elided.present? result end end