README.md

# Bamboo

Bamboo was built with a few goals in mind

* Easy to format recipients, so you can do `new_email(to: Repo.one(User))` and Bamboo can format the user automatically.
* Works with Phoenix views and layouts to make rendering easy.
* Adapter based so it can be used with Mandrill, SMTP, or whatever else you want.
* Very composable. Emails are just a Bamboo.Email struct and be manipulated with plain functions.
* Make it super easy to unit test. No special functions needed.
* Easy to test delivery in integration tests. As little repeated code as possible.

See the module docs for the most up to date information.

## Usage

Bamboo breaks email creation and email sending in to two separate modules.

```elixir
# In your config/config.exs file
config :my_app, MyApp.Mailer,
  adapter: Bamboo.MandrillAdapter,
  api_key: "my_api_key"

# In your application code
defmodule MyApp.Mailer do
  use Bamboo.Mailer, otp_app: :my_app
end

defmodule MyApp.Emails do
  import Bamboo.Email

  def welcome_email do
    new_mail(
      to: "foo@example.com",
      from: "me@example.com",
      subject: "Welcome!!!",
      html_body: "<strong>WELCOME</strong>",
      text_body: "WELCOME"
    )
  end
end

# In a controller or some other module
defmodule MyApp.Foo do
  alias MyApp.Emails
  alias MyApp.Mailer

  def register_user do
    # Create a user and whatever else is needed

    # Emails are not delivered until you explicitly deliver them. This makes
    # them very composable and easy to unit test
    Emails.welcome_email |> Mailer.deliver
  end
end
```

## More options

```elixir
defmodule MyApp.Emails do
  # Adds a `render` function for rending emails with a Phoenix view
  use Bamboo.Phoenix, view: MyApp.EmailView
  import Bamboo.MandrillEmails

  def welcome_email do
    base_email
    |> to("foo@bar.com", %Bamboo.EmailAddress{name: "John Smith", address:"john@foo.com"})
    |> cc(author) # You can set up a custom protocol that handles different types of structs.
    |> subject("Welcome!!!")
    |> tag("welcome-email") # Imported by Bamboo.MandrillEmails
    |> put_header("Reply-To", "somewhere@example.com")
    # Uses the view from `view` to render the `welcome_email.html.eex`
    # and `welcome_email.text.eex` templates with the passed in assigns
    # Use string to render a specific template, e.g. `welcome_email.html.eex`
    |> render(:welcome_email, author: author)
  end

  defp author do
    User |> Repo.one
  end

  defp base_email do
    mail(from: "myapp@example.com")
  end
end

defimpl Bamboo.Formatter, for: User do
  # Used by `to`, `bcc`, `cc` and `from`
  def format_email_address(user, _opts) do
    fullname = "#{user.first_name} #{user.last_name}"
    %Bamboo.EmailAddress{name: fullname, email: email}
  end
end
```

## In development (coming soonish)

You can see the sent emails by forwarding a route to the `Bamboo.Preview`
module. You can see all the emails sent. It will live update with new emails
sent.

```elixir
# In your Phoenix router
forward "/delivered_emails", Bamboo.Mailbox

# If you want to see the latest email, add this to your socket
channel "/latest_email", Bamboo.LatestEmailChannel

# In your browser
localhost:4000/email_previews
```

## Testing

You can use the `Bamboo.TestAdapter` to make testing your emails a piece of cake.

```elixir
# Use the Bamboo.LocalAdapter in your config/test.exs file
config :my_app, MyApp.Mailer,
  adapter: Bamboo.TestAdapter

# Unit testing requires no special functions
defmodule MyApp.EmailsTest do
  use ExUnit.Case

  alias MyApp.Emails

  test "welcome email" do
    user = %User{...}
    email = Emails.welcome_email(user)

    assert email.to == "someone@foo.com"
    assert email.subject == "This is your welcome email"
    assert email.html_body =~ "Welcome to the app!"
  end
end

# Integration tests

defmodule MyApp.RegistrationControllerTest do
  use ExUnit.Case

  use Bamboo.Test
  alias MyApp.Emails

  test "registers user and sends welcome email" do
    ...post to registration controller

    newly_created_user = Repo.first(User)
    assert_delivered_email Emails.welcome_email(newly_created_user)
  end
end

```

## Installation

To use the latest from master.

  1. Add bamboo to your list of dependencies in `mix.exs`:

        def deps do
          [{:bamboo, github: "paulcsmith/bamboo"}]
        end

  2. Ensure bamboo is started before your application:

        def application do
          [applications: [:bamboo]]
        end