remove premailer
This commit is contained in:
@@ -4,6 +4,7 @@ source 'https://rubygems.org'
|
|||||||
|
|
||||||
ruby '4.0.1'
|
ruby '4.0.1'
|
||||||
|
|
||||||
|
gem 'addressable'
|
||||||
gem 'arabic-letter-connector', require: false
|
gem 'arabic-letter-connector', require: false
|
||||||
gem 'aws-sdk-s3', require: false
|
gem 'aws-sdk-s3', require: false
|
||||||
gem 'aws-sdk-secretsmanager', require: false
|
gem 'aws-sdk-secretsmanager', require: false
|
||||||
@@ -28,7 +29,6 @@ gem 'oj'
|
|||||||
gem 'onnxruntime', require: false
|
gem 'onnxruntime', require: false
|
||||||
gem 'pagy'
|
gem 'pagy'
|
||||||
gem 'pg', require: false
|
gem 'pg', require: false
|
||||||
gem 'premailer-rails'
|
|
||||||
gem 'pretender'
|
gem 'pretender'
|
||||||
gem 'puma', require: false
|
gem 'puma', require: false
|
||||||
gem 'rack'
|
gem 'rack'
|
||||||
|
|||||||
+1
-12
@@ -150,8 +150,6 @@ GEM
|
|||||||
bigdecimal
|
bigdecimal
|
||||||
rexml
|
rexml
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
css_parser (1.21.1)
|
|
||||||
addressable
|
|
||||||
csv (3.3.5)
|
csv (3.3.5)
|
||||||
csv-safe (3.3.1)
|
csv-safe (3.3.1)
|
||||||
csv (~> 3.0)
|
csv (~> 3.0)
|
||||||
@@ -264,7 +262,6 @@ GEM
|
|||||||
geom2d (~> 0.4, >= 0.4.1)
|
geom2d (~> 0.4, >= 0.4.1)
|
||||||
openssl (>= 2.2.1)
|
openssl (>= 2.2.1)
|
||||||
strscan (>= 3.1.2)
|
strscan (>= 3.1.2)
|
||||||
htmlentities (4.4.2)
|
|
||||||
i18n (1.14.8)
|
i18n (1.14.8)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
image_processing (1.14.0)
|
image_processing (1.14.0)
|
||||||
@@ -370,14 +367,6 @@ GEM
|
|||||||
pg (1.6.3-x86_64-linux-musl)
|
pg (1.6.3-x86_64-linux-musl)
|
||||||
pp (0.6.3)
|
pp (0.6.3)
|
||||||
prettyprint
|
prettyprint
|
||||||
premailer (1.27.0)
|
|
||||||
addressable
|
|
||||||
css_parser (>= 1.19.0)
|
|
||||||
htmlentities (>= 4.0.0)
|
|
||||||
premailer-rails (1.12.0)
|
|
||||||
actionmailer (>= 3)
|
|
||||||
net-smtp
|
|
||||||
premailer (~> 1.7, >= 1.7.9)
|
|
||||||
pretender (0.6.0)
|
pretender (0.6.0)
|
||||||
actionpack (>= 7.1)
|
actionpack (>= 7.1)
|
||||||
prettyprint (0.2.0)
|
prettyprint (0.2.0)
|
||||||
@@ -607,6 +596,7 @@ PLATFORMS
|
|||||||
x86_64-linux-musl
|
x86_64-linux-musl
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
addressable
|
||||||
annotaterb
|
annotaterb
|
||||||
arabic-letter-connector
|
arabic-letter-connector
|
||||||
aws-sdk-s3
|
aws-sdk-s3
|
||||||
@@ -643,7 +633,6 @@ DEPENDENCIES
|
|||||||
onnxruntime
|
onnxruntime
|
||||||
pagy
|
pagy
|
||||||
pg
|
pg
|
||||||
premailer-rails
|
|
||||||
pretender
|
pretender
|
||||||
pry-rails
|
pry-rails
|
||||||
puma
|
puma
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ class ApplicationMailer < ActionMailer::Base
|
|||||||
layout 'mailer'
|
layout 'mailer'
|
||||||
|
|
||||||
register_interceptor ActionMailerConfigsInterceptor
|
register_interceptor ActionMailerConfigsInterceptor
|
||||||
|
register_interceptor HtmlToPlainTextInterceptor
|
||||||
|
register_preview_interceptor HtmlToPlainTextInterceptor
|
||||||
|
|
||||||
register_observer ActionMailerEventsObserver
|
register_observer ActionMailerEventsObserver
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module HtmlToPlainText
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def call(html, line_length = 65)
|
||||||
|
return '' if html.nil? || html.strip.empty?
|
||||||
|
|
||||||
|
cleaned = html.gsub(%r{<!-- start text/html -->.*?<!-- end text/html -->}m, '')
|
||||||
|
|
||||||
|
doc = Nokogiri::HTML.fragment(cleaned)
|
||||||
|
|
||||||
|
doc.css('script').each(&:remove)
|
||||||
|
|
||||||
|
result = process_nodes(doc, line_length)
|
||||||
|
|
||||||
|
result.gsub!(/\r\n?/, "\n")
|
||||||
|
result.gsub!(/[ \t]*\u00A0+[ \t]*/, ' ')
|
||||||
|
result.gsub!(/\n[ \t]+/, "\n")
|
||||||
|
result.gsub!(/[ \t]+\n/, "\n")
|
||||||
|
result.gsub!(/\n{3,}/, "\n\n")
|
||||||
|
|
||||||
|
result = word_wrap(result, line_length)
|
||||||
|
|
||||||
|
result.gsub!(/\(([ \n])(http[^)]+)([\n ])\)/) do
|
||||||
|
"#{"\n" if ::Regexp.last_match(1) == "\n"}( #{::Regexp.last_match(2)} )#{"\n" if ::Regexp.last_match(3) == "\n"}"
|
||||||
|
end
|
||||||
|
|
||||||
|
result.strip
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_nodes(node, line_length)
|
||||||
|
result = +''
|
||||||
|
|
||||||
|
node.children.each do |child|
|
||||||
|
case child
|
||||||
|
when Nokogiri::XML::Text
|
||||||
|
result << child.text
|
||||||
|
when Nokogiri::XML::Comment
|
||||||
|
next
|
||||||
|
when Nokogiri::XML::Element
|
||||||
|
result << process_element(child, line_length)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_element(node, line_length)
|
||||||
|
case node.name
|
||||||
|
when 'br'
|
||||||
|
"\n"
|
||||||
|
when 'p', 'div'
|
||||||
|
inner = process_nodes(node, line_length)
|
||||||
|
inner.strip.empty? ? '' : "#{inner}\n\n"
|
||||||
|
when 'img'
|
||||||
|
node['alt'] || ''
|
||||||
|
when 'a'
|
||||||
|
process_link(node, line_length)
|
||||||
|
when /\Ah([1-6])\z/
|
||||||
|
process_heading(node, ::Regexp.last_match(1).to_i, line_length)
|
||||||
|
when 'li'
|
||||||
|
inner = process_nodes(node, line_length)
|
||||||
|
"* #{inner.strip}\n"
|
||||||
|
else
|
||||||
|
process_nodes(node, line_length)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_link(node, line_length)
|
||||||
|
text = process_nodes(node, line_length).strip
|
||||||
|
return '' if text.empty?
|
||||||
|
|
||||||
|
href = node['href']
|
||||||
|
href = href.sub(/\Amailto:/i, '') if href
|
||||||
|
|
||||||
|
if href.nil? || text.casecmp(href.strip) == 0
|
||||||
|
text
|
||||||
|
else
|
||||||
|
"#{text} ( #{href.strip} )"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_heading(node, level, line_length)
|
||||||
|
text = +''
|
||||||
|
node.children.each do |child|
|
||||||
|
text << if child.name == 'br'
|
||||||
|
"\n"
|
||||||
|
else
|
||||||
|
child.text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text.strip!
|
||||||
|
|
||||||
|
hlength = text.each_line.map { |l| l.strip.length }.max || 0
|
||||||
|
hlength = line_length if hlength > line_length
|
||||||
|
|
||||||
|
decorated = case level
|
||||||
|
when 1
|
||||||
|
"#{'*' * hlength}\n#{text}\n#{'*' * hlength}"
|
||||||
|
when 2
|
||||||
|
"#{'-' * hlength}\n#{text}\n#{'-' * hlength}"
|
||||||
|
else
|
||||||
|
"#{text}\n#{'-' * hlength}"
|
||||||
|
end
|
||||||
|
|
||||||
|
"\n\n#{decorated}\n\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def word_wrap(txt, line_length)
|
||||||
|
txt.split("\n").map do |line|
|
||||||
|
if line.length > line_length
|
||||||
|
line.gsub(/(.{1,#{line_length}})(\s+|$)/, "\\1\n").strip
|
||||||
|
else
|
||||||
|
line
|
||||||
|
end
|
||||||
|
end.join("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module HtmlToPlainTextInterceptor
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def delivering_email(message)
|
||||||
|
process(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def previewing_email(message)
|
||||||
|
process(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process(message)
|
||||||
|
return message unless html_part(message)
|
||||||
|
return message if message.text_part
|
||||||
|
|
||||||
|
add_text_part(message)
|
||||||
|
|
||||||
|
message
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_text_part(message)
|
||||||
|
html = html_part(message).decoded
|
||||||
|
text = HtmlToPlainText.call(html)
|
||||||
|
|
||||||
|
text_part = Mail::Part.new do
|
||||||
|
content_type 'text/plain; charset=UTF-8'
|
||||||
|
body text
|
||||||
|
end
|
||||||
|
|
||||||
|
if pure_html_message?(message)
|
||||||
|
message.body = nil
|
||||||
|
message.content_type = 'multipart/alternative'
|
||||||
|
message.add_part(text_part)
|
||||||
|
message.add_part(Mail::Part.new do
|
||||||
|
content_type 'text/html; charset=UTF-8'
|
||||||
|
body html
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
alternative = Mail::Part.new(content_type: 'multipart/alternative')
|
||||||
|
alternative.add_part(text_part)
|
||||||
|
alternative.add_part(message.html_part)
|
||||||
|
replace_part(message.parts, message.html_part, alternative)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pure_html_message?(message)
|
||||||
|
message.content_type.to_s.include?('text/html')
|
||||||
|
end
|
||||||
|
|
||||||
|
def html_part(message)
|
||||||
|
pure_html_message?(message) ? message : message.html_part
|
||||||
|
end
|
||||||
|
|
||||||
|
def replace_part(parts, old_part, new_part)
|
||||||
|
if (index = parts.index(old_part))
|
||||||
|
parts[index] = new_part
|
||||||
|
else
|
||||||
|
parts.each do |part|
|
||||||
|
replace_part(part.parts, old_part, new_part) if part.respond_to?(:parts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user