Skip to content

Commit

Permalink
feat: sendgrid support for content_id (#691)
Browse files Browse the repository at this point in the history
* Add support for content_id in SendgridAdapter

Introduces support for content_id so that inline images in e-mails can
be send and referenced from HTML content of the e-mail

* refactor: remove negated is_nil to satisfy credo

---------

Co-authored-by: Hubert Łępicki <[email protected]>
  • Loading branch information
doomspork and hubertlepicki authored Jan 16, 2025
1 parent 66782dc commit 7a878f4
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
28 changes: 23 additions & 5 deletions lib/bamboo/adapters/send_grid_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,34 @@ defmodule Bamboo.SendGridAdapter do
attachments
|> Enum.reverse()
|> Enum.map(fn attachment ->
%{
filename: attachment.filename,
type: attachment.content_type,
content: Base.encode64(attachment.data)
}
maybe_append_content_id(
%{
filename: attachment.filename,
type: attachment.content_type,
content: Base.encode64(attachment.data),
disposition: attachment_disposition(attachment)
},
attachment
)
end)

Map.put(body, :attachments, transformed)
end

defp maybe_append_content_id(map, %{content_id: nil}) do
map
end

defp maybe_append_content_id(map, %{content_id: content_id}) do
Map.put(map, :content_id, content_id)
end

defp attachment_disposition(%Bamboo.Attachment{content_id: cid}) when is_binary(cid) do
"inline"
end

defp attachment_disposition(_), do: "attachment"

defp put_addresses(body, _, []), do: body

defp put_addresses(body, field, addresses),
Expand Down
38 changes: 37 additions & 1 deletion test/lib/bamboo/adapters/send_grid_adapter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,43 @@ defmodule Bamboo.SendGridAdapterTest do
%{
"type" => "text/plain",
"filename" => "attachment.txt",
"content" => "VGVzdCBBdHRhY2htZW50Cg=="
"content" => "VGVzdCBBdHRhY2htZW50Cg==",
"disposition" => "attachment"
}
]
end

test "deliver/2 sends from, html and text body, subject, headers and inline attachment" do
email =
[
from: {"From", "[email protected]"},
subject: "My Subject",
text_body: "TEXT BODY",
html_body: "HTML BODY <img src='cid:myimg' />"
]
|> new_email()
|> Email.put_header("Reply-To", "[email protected]")
|> Email.put_attachment(Path.join(__DIR__, "../../../support/attachment.txt"), content_id: "myimg")

SendGridAdapter.deliver(email, @config)

assert SendGridAdapter.supports_attachments?()
assert_receive {:fake_sendgrid, %{params: params, req_headers: headers}}

assert params["from"]["name"] == elem(email.from, 0)
assert params["from"]["email"] == elem(email.from, 1)
assert params["subject"] == email.subject
assert Enum.member?(params["content"], %{"type" => "text/plain", "value" => email.text_body})
assert Enum.member?(params["content"], %{"type" => "text/html", "value" => email.html_body})
assert Enum.member?(headers, {"authorization", "Bearer #{@config[:api_key]}"})

assert params["attachments"] == [
%{
"type" => "text/plain",
"filename" => "attachment.txt",
"content" => "VGVzdCBBdHRhY2htZW50Cg==",
"disposition" => "inline",
"content_id" => "myimg"
}
]
end
Expand Down

0 comments on commit 7a878f4

Please sign in to comment.