Skip to content

Commit 14294c0

Browse files
Merge pull request rails#49828 from c960657/preview-interceptor-inline
Ignore inline attachments and show attached emails in attachment list
2 parents e956aaf + ff2e38c commit 14294c0

File tree

4 files changed

+53
-10
lines changed

4 files changed

+53
-10
lines changed

railties/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
* In Action Mailer previews, list inline attachments separately from normal
2+
attachments. For example, attachments that were previously listed like
3+
4+
> Attachments: logo.png file1.pdf file2.pdf
5+
6+
will now be listed like
7+
8+
> Attachments: file1.pdf file2.pdf (Inline: logo.png)
9+
10+
*Christian Schmidt* and *Jonathan Hefner*
11+
112
* In mailer preview, only show SMTP-To if it differs from the union of To, Cc and Bcc.
213

314
*Christian Schmidt*

railties/lib/rails/mailers_controller.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require "rails/application_controller"
4+
require "active_support/core_ext/enumerable"
45

56
class Rails::MailersController < Rails::ApplicationController # :nodoc:
67
prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATHS
@@ -9,7 +10,7 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
910
before_action :find_preview, only: [:preview, :download]
1011
before_action :require_local!, unless: :show_previews?
1112

12-
helper_method :part_query, :locale_query
13+
helper_method :attachment_url, :part_query, :locale_query
1314

1415
content_security_policy(false)
1516

@@ -38,6 +39,8 @@ def preview
3839
if @preview.email_exists?(@email_action)
3940
@page_title = "Mailer Preview for #{@preview.preview_name}##{@email_action}"
4041
@email = @preview.call(@email_action, params)
42+
@attachments = attachments_for(@email).reject { |filename, attachment| attachment.inline? }
43+
@inline_attachments = attachments_for(@email).select { |filename, attachment| attachment.inline? }
4144

4245
if params[:part]
4346
part_type = Mime::Type.lookup(params[:part])
@@ -95,6 +98,16 @@ def find_part(format) # :doc:
9598
end
9699
end
97100

101+
def attachments_for(email)
102+
email.all_parts.to_a.select(&:attachment?).index_by do |attachment|
103+
attachment.respond_to?(:original_filename) ? attachment.original_filename : attachment.filename
104+
end
105+
end
106+
107+
def attachment_url(attachment)
108+
"data:application/octet-stream;charset=utf-8;base64,#{Base64.encode64(attachment.body.to_s)}"
109+
end
110+
98111
def part_query(mime_type)
99112
request.query_parameters.merge(part: mime_type).to_query
100113
end

railties/lib/rails/templates/rails/mailers/email.html.erb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,16 @@
9898
<dt>Subject:</dt>
9999
<dd><strong id="subject"><%= @email.subject %></strong></dd>
100100

101-
<% unless @email.attachments.nil? || @email.attachments.empty? %>
101+
<% if @attachments.any? || @inline_attachments.any? %>
102102
<dt>Attachments:</dt>
103103
<dd>
104-
<% @email.attachments.each do |a| %>
105-
<% filename = a.respond_to?(:original_filename) ? a.original_filename : a.filename %>
106-
<%= link_to filename, "data:application/octet-stream;charset=utf-8;base64,#{Base64.encode64(a.body.to_s)}", download: filename %>
104+
<% @attachments.each do |filename, attachment| %>
105+
<%= link_to filename, attachment_url(attachment), download: filename %>
106+
<% end %>
107+
108+
<% if @inline_attachments.any? %>
109+
(Inline: <% @inline_attachments.each do |filename, attachment| %>
110+
<%= link_to filename, attachment_url(attachment), download: filename %><% end %>)
107111
<% end %>
108112
</dd>
109113
<% end %>

railties/test/application/mailer_previews_test.rb

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,10 @@ def foo
771771

772772
get "/rails/mailers/notifier/foo"
773773
assert_equal 200, last_response.status
774-
assert_match %r[<iframe name="messageBody"], last_response.body
774+
assert_match %[<iframe name="messageBody"], last_response.body
775+
assert_match %[<dt>Attachments:</dt>], last_response.body
776+
assert_no_match %[Inline:], last_response.body
777+
assert_match %[<a download="pixel.png" href="data:application/octet-stream;charset=utf-8;base64,iVBORw0K], last_response.body
775778

776779
get "/rails/mailers/notifier/foo?part=text/plain"
777780
assert_equal 200, last_response.status
@@ -819,7 +822,10 @@ def foo
819822

820823
get "/rails/mailers/notifier/foo"
821824
assert_equal 200, last_response.status
822-
assert_match %r[<iframe name="messageBody"], last_response.body
825+
assert_match %[<iframe name="messageBody"], last_response.body
826+
assert_match %[<dt>Attachments:</dt>], last_response.body
827+
assert_no_match %[Inline:], last_response.body
828+
assert_match %[<a download="pixel.png" href="data:application/octet-stream;charset=utf-8;base64,iVBORw0K], last_response.body
823829

824830
get "/rails/mailers/notifier/foo?part=text/plain"
825831
assert_equal 200, last_response.status
@@ -838,7 +844,7 @@ class Notifier < ActionMailer::Base
838844
default from: "[email protected]"
839845
840846
def foo
841-
attachments['pixel.png'] = File.binread("#{app_path}/public/images/pixel.png")
847+
attachments.inline['pixel.png'] = File.binread("#{app_path}/public/images/pixel.png")
842848
mail to: "[email protected]"
843849
end
844850
end
@@ -865,7 +871,9 @@ def foo
865871

866872
get "/rails/mailers/notifier/foo"
867873
assert_equal 200, last_response.status
868-
assert_match %r[<iframe name="messageBody"], last_response.body
874+
assert_match %[<iframe name="messageBody"], last_response.body
875+
assert_match %[<dt>Attachments:</dt>], last_response.body
876+
assert_match %r[\(Inline:\s+<a download="pixel.png" href="data:application/octet-stream;charset=utf-8;base64,iVBORw0K], last_response.body
869877

870878
get "/rails/mailers/notifier/foo?part=text/plain"
871879
assert_equal 200, last_response.status
@@ -875,6 +883,10 @@ def foo
875883
assert_equal 200, last_response.status
876884
assert_match %r[<p>Hello, World!</p>], last_response.body
877885
assert_match %r[src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEWzIioca/JlAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJgggo="], last_response.body
886+
887+
get "/rails/mailers/download/notifier/foo"
888+
email = Mail.read_from_string(last_response.body)
889+
assert_equal "inline; filename=pixel.png", email.attachments.inline["pixel.png"].content_disposition
878890
end
879891

880892
test "multipart mailer preview with attached email" do
@@ -923,7 +935,10 @@ def foo
923935

924936
get "/rails/mailers/notifier/foo"
925937
assert_equal 200, last_response.status
926-
assert_match %r[<iframe name="messageBody"], last_response.body
938+
assert_match %[<iframe name="messageBody"], last_response.body
939+
assert_match %[<dt>Attachments:</dt>], last_response.body
940+
assert_no_match %[Inline:], last_response.body
941+
assert_match %[<a download="message.eml" href="data:application/octet-stream;charset=utf-8;base64,RGF0ZTog], last_response.body
927942

928943
get "/rails/mailers/notifier/foo?part=text/plain"
929944
assert_equal 200, last_response.status

0 commit comments

Comments
 (0)