(FunctionClauseError) no function clause matching in Base.encode64/2

I am trying to send attachment inside email from my phoenix application using Bamboo.

Library used:
nimble_csv
bamboo
bamboo_smtp

The attachment is in-memory data that I am getting after parsing the CSV and making some changes into it. I don’t want to save the CSV file so using the in-memory approach.

def dump_to_csv(list) do
    [~w(ORIGINAL_URL NEW_URL)] ++ list
      |> ShortnerParser.dump_to_iodata()
      |> prepare_mail
      |> Mailer.deliver_later
  end

def prepare_mail(data) do
    attachment = %Bamboo.Attachment{content_type: "application/octet-stream", filename: "shortner.csv", data: data}
    Email.send_csv("myemail@gmail.com", attachment)
  end

Error I am getting:

[error] Task #PID<0.1556.0> started from #PID<0.1492.0> terminating
** (FunctionClauseError) no function clause matching in Base.encode64/2
    (elixir) lib/base.ex:371: Base.encode64([["ORIGINAL_URL", 44, "NEW_URL", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/ldhkRf", 10], ["https://google.com", 44, "https://localhost:4000/n594Hy", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/Kl67G5", 10], ["https://google.com", 44, "https://localhost:4000/Ct17TM", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/w1gX_x", 10], ["https://google.com", 44, "https://localhost:4000/1lqoLr", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/R_u3Yq", 10], ["https://google.com", 44, "https://localhost:4000/elXe4V", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/13hn32", 10], ["https://google.com", 44, "https://localhost:4000/j9uiKL", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/c3pzUB", 10], ["https://google.com", 44, "https://localhost:4000/Yhb7Kv", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/19PS7z", 10], ["https://google.com", 44, "https://localhost:4000/LvHqO1", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/teJagz", 10], ["https://google.com", 44, "https://localhost:4000/MBYX_e", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/DfpQ25", 10], ["https://google.com", 44, "https://localhost:4000/jLFq6P", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/xM7Jg3", 10], ["https://google.com", 44, "https://localhost:4000/IM2RG6", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/1X2IZ8", 10], ["https://google.com", 44, "https://localhost:4000/KKo0kt", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/YvTW_p", 10], ["https://google.com", 44, "https://localhost:4000/iwLt7L", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/DoIvwE", 10], ["https://google.com", 44, "https://localhost:4000/ZMe3dE", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/CGEIa1", 10], ["https://google.com", 44, "https://localhost:4000/Z6fPMT", 10], ["https:pharmeasy.in", 44, "invalid_url", 10], ["https://facebook.com", 44, "https://localhost:4000/zYpNgG", 10], ["https://google.com", 44, "https://localhost:4000/MYQdRu", 10], ["https:pharmeasy.in", 44, "invalid_url", ...], ["https://facebook.com", 44, ...], ["https://google.com", ...], [...], ...], [])
    (bamboo_smtp) lib/bamboo/adapters/smtp_adapter.ex:214: Bamboo.SMTPAdapter.add_attachment_body/2
    (elixir) lib/enum.ex:1314: Enum."-map/2-lists^map/1-0-"/2
    (bamboo_smtp) lib/bamboo/adapters/smtp_adapter.ex:233: Bamboo.SMTPAdapter.add_attachments/3
    (bamboo_smtp) lib/bamboo/adapters/smtp_adapter.ex:278: Bamboo.SMTPAdapter.body/1
    (bamboo_smtp) lib/bamboo/adapters/smtp_adapter.ex:360: Bamboo.SMTPAdapter.to_gen_smtp_message/1
    (bamboo_smtp) lib/bamboo/adapters/smtp_adapter.ex:76: Bamboo.SMTPAdapter.deliver/2
    (elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Function: #Function<0.73693256/0 in Bamboo.TaskSupervisorStrategy.deliver_later/3>
    Args: []
1 Like

You need to pass in a binary, rather than iodata.

2 Likes

How can I do that can you please help me with that?

Sorry that was lame question below method did the trick.

def convert_to_binary(data) do
    data
      |> IO.iodata_to_binary
  end

Thanks.

2 Likes

You can simply use the to_string function.

I could be wrong, but I think to_string is not equivalent to IO.iodata_to_binary. to_string expects a list of codepoints, but IO.iodata_to_binary expects any integers in the list to be bytes:

iex(2)> "hełło" |> String.to_charlist |> IO.iodata_to_binary
** (ArgumentError) argument error
    :erlang.iolist_to_binary([104, 101, 322, 322, 111])
iex(2)> "hełło" |> String.to_charlist |> to_string          
"hełło"

I don’t know if this makes any difference if what you start with is an iolist though.

1 Like

Interesting nuance. It’s just that I very early learned to use to_string on iolists and kind of never questioned it because it always worked well (and without botching encoding).

Gotcha. If I had to guess, IO.iodata_to_binary is gonna perform better because it only needs to concern itself with bytes.