Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inline images in mandrill adapter #608

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
erlang 21.2
elixir 1.8.1
erlang 22.3.4
elixir 1.8
30 changes: 23 additions & 7 deletions lib/bamboo/adapters/mandrill_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,23 @@ defmodule Bamboo.MandrillAdapter do
subject: email.subject,
text: email.text_body,
html: email.html_body,
headers: email.headers,
attachments: attachments(email)
headers: email.headers
}
|> add_attachments(email)
|> add_message_params(email)
end

defp add_attachments(mandrill_message, %{attachments: attachments}) do
{images, files} =
attachments
|> Enum.reverse()
|> Enum.split_with(&is_inline_image?/1)

mandrill_message
|> Map.put(:attachments, format_attachments(files))
|> Map.put(:images, format_attachments(images))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know why we're calling this images? Will inline attachments always be images or is that how mandrill categorizes inline attachments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, of course! https://mailchimp.com/developer/transactional/api/messages/send-new-message/
Inside message attribute at the end.

Is similar to attachments with the difference of send the cid instead of the filename.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sending that link. That's very helpful! This is the section I'm looking at:

Screen Shot 2021-06-11 at 8 56 45 AM

Based on what I'm seeing, the changes in this PR seem good.

My only lingering question is: do you know if it's possible to add non-image files as inline attachments?

  • If that's the case, then someone could add a non-image attachment with content-id but we would incorrectly put it in the :images field.
  • If Mandrill only allows for images as inline attachments, then I think this PR is good to go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new commit to check the content_type too before add it as inline image.

end

defp add_message_params(mandrill_message, %{private: %{message_params: message_params}}) do
Enum.reduce(message_params, mandrill_message, fn {key, value}, mandrill_message ->
Map.put(mandrill_message, key, value)
Expand All @@ -117,18 +128,23 @@ defmodule Bamboo.MandrillAdapter do

defp add_message_params(mandrill_message, _), do: mandrill_message

defp attachments(%{attachments: attachments}) do
attachments
|> Enum.reverse()
|> Enum.map(fn attachment ->
defp format_attachments(attachments) do
Enum.map(attachments, fn attachment ->
name = if is_inline_image?(attachment), do: attachment.content_id, else: attachment.filename

%{
name: attachment.filename,
name: name,
type: attachment.content_type,
content: Base.encode64(attachment.data)
}
end)
end

defp is_inline_image?(%_{content_type: "image/" <> _, content_id: cid}) when not is_nil(cid),
do: true

defp is_inline_image?(_), do: false

defp recipients(email) do
[]
|> add_recipients(email.to, type: "to")
Expand Down
32 changes: 31 additions & 1 deletion test/lib/bamboo/adapters/mandrill_adapter_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Bamboo.MandrillAdapterTest do
use ExUnit.Case
alias Bamboo.Attachment
alias Bamboo.Email
alias Bamboo.MandrillHelper
alias Bamboo.MandrillAdapter
Expand Down Expand Up @@ -103,6 +104,8 @@ defmodule Bamboo.MandrillAdapterTest do
end

test "deliver/2 sends from, html and text body, subject, headers and attachment" do
file_path = Path.join(__DIR__, "../../../support/attachment.txt")

email =
new_email(
from: {"From", "from@foo.com"},
Expand All @@ -111,7 +114,20 @@ defmodule Bamboo.MandrillAdapterTest do
html_body: "HTML BODY"
)
|> Email.put_header("Reply-To", "reply@foo.com")
|> Email.put_attachment(Path.join(__DIR__, "../../../support/attachment.txt"))
|> Email.put_attachment(file_path)
|> Email.put_attachment(
Attachment.new(file_path, content_id: "my_fake_image", filename: "fake_image.jpg")
)
|> Email.put_attachment(%Attachment{
content_type: "image/png",
content_id: "my_image",
filename: "my_image.png",
data:
<<137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1,
8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 120, 218, 99, 252, 207,
192, 80, 15, 0, 4, 133, 1, 128, 132, 169, 140, 33, 0, 0, 0, 0, 73, 69, 78, 68, 174,
66, 96, 130>>
})

email |> MandrillAdapter.deliver(@config)

Expand All @@ -131,6 +147,20 @@ defmodule Bamboo.MandrillAdapterTest do
"type" => "text/plain",
"name" => "attachment.txt",
"content" => "VGVzdCBBdHRhY2htZW50Cg=="
},
%{
"type" => "text/plain",
"name" => "fake_image.jpg",
"content" => "VGVzdCBBdHRhY2htZW50Cg=="
}
]

assert message["images"] == [
%{
"type" => "image/png",
"name" => "my_image",
"content" =>
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
}
]
end
Expand Down