andrewtimberlake / mailroom

Mail handling for Elixir
MIT License
21 stars 18 forks source link

Docs #12

Open yok0 opened 2 years ago

yok0 commented 2 years ago

Any plans on updating docs or is this project being archived? I am having hard time figuring out how to use Mailroom. Also some of the functions in the existing examples arseems to be no longer there, like IMAP.retrive and IMAP.delete.

Thanks

andrewtimberlake commented 2 years ago

Hi @yok0 The project currently does all I need it to do and is running in production to manage incoming mail via IMAP. The primary focus of Mailroom is a router-like interface for incoming mail. The IMAP and POP3 modules provide functionality for those respective protocols but the power is in the Inbox module which works like this:

defmodule Namespace.Mailroom do
  use Mailroom.Inbox

  match do
    to("email@example.com")
    # recipient(~r/^.+@mydomain\.com$/i)
    subject(~r/a subject/)
    has_attachment?

    fetch_mail #Previous matching is done on headers and IMAP envelope, if the match succeeds and you need the body, then this will retrieve the message body
    process(SomeModule, :some_function)
  end

  match do
    to("wrong@example.com")

    ignore
  end

  def config([app, key]) do
    Keyword.merge(
      [debug: false, folder: :inbox, assigns: %{}],
      Application.get_env(app, key, [])
    )
  end
end

defmodule SomeModule do
  def some_function(%MessageContext{}) do
    #...
  end
end

To answer your issue about the missing examples, IMAP doesn’t have retrieve or delete but POP3 does I’m happy to answer questions or accept documentation pull requests.

gernotkogler commented 1 week ago

Hi @andrewtimberlake

Wow, this example helped a lot! Would be great if you could show some code that extracts attachments from an Email

andrewtimberlake commented 1 week ago

Hi @gernotkogler The module that is invoked through process(SomeModule, :some_function) will receive a %MessageContext{mail_info: mail_info, message: message} message is a message struct from the elixir email library You can use that to retrieve attachments:

message
|> Mail.get_attachments()
|> Enum.each(fn {filename, contents} ->
  # ... do something with the attachment
end)

PS. If you want to make your life much easier, I have launched a service, Mailcast that processes emails and sends them to you via webhook. Let me know if you’d like a demo

gernotkogler commented 1 week ago

Hi @andrewtimberlake

Thanks for the quick response. I figured out that I could use Mail to get to the attachments in the meantime, but your code snippet is a bit more concise.

I was reasoning about Mailroom.IMAP.BodyStructure since that module has a get_attachments(body_structure, acc \\ []) but didn't figure out how to use it (hint: zero docs).

I guess some work on the docs would attract way more people. If I hadn't found your snippet in the Docs issue today, I would have given up on mailroom. Now I have a perfect solution for my needs with just about 50 lines of code, great, thanks for your nice work!

Using a third party service is not an option for me since the emails I process are confidential. And, by the way, the site seems to have issues, it renders a big SORRY.

Let me know if you would accept a PR that documents the inbox usage in the README.

andrewtimberlake commented 1 week ago

Wrong link 🤦‍♂️ I’ve updated it. I understand about the emails. Feel free to submit a PR. Thanks

gernotkogler commented 1 week ago

Looks good, cool idea. I actually wondered if I could use a service that calls a webhook when emails arrive, but as I said, my emails are confidential.

May I ask you one more question? When I receive emails from an iPhone that just contain an image, the image is rendered inline. Mail.get_attachments() seems not to handle inline attachments. Did you run into that problem, too?

andrewtimberlake commented 1 week ago

I’ve sent you an email to take discussion of confidentiality offline.

I have seen that. Hey.com seems to do the same thing. I saw the comment on elixir-mail. I’ll have a look further there.