Packages

Elixir client for Apostle.io.

Current section

Files

Jump to
apostle lib mail.ex
Raw

lib/mail.ex

defmodule Apostle.Mail do
defstruct email: nil, from: nil, headers: %{}, layout_id: nil, name: nil, reply_to: nil, template_id: nil, data: %{}, attachments: %{}
@moduledoc """
Functions for working with individual emails.
"""
@doc """
Generates an `Apostle.Mail` struct based on the supplied options.
Options:
* `:email` - the destination email address
* `:from` - the from address
* `:name` - not sure. ask @snikch
* `:reply_to` - the reply to address
* `:layout_id` - the "slug" of your template layout should you not want to use the default
* `:template_id` - the "slug" of the template to send
* `:cc` - contents of the `CC` header
* `:bcc` - contents of the `BCC` header
* `:headers` - a `Map` containing additional mail headers to send
* `:attachments` - a `List` of paths on the filesystem to files you wish to attach
* _any_other_key_ - set as template variable values (aka `data`).
"""
def init opts do
{%Apostle.Mail{}, opts}
|> parse_value(:email)
|> parse_value(:from)
|> parse_value(:name)
|> parse_value(:reply_to)
|> parse_value(:layout_id)
|> parse_value(:template_id)
|> parse_header(:cc)
|> parse_header(:bcc)
|> parse_attachments
|> parse_data
end
def set_value %Apostle.Mail{}=mail, _key, nil do
mail
end
@doc """
Set a value on the mail struct.
"""
def set_value %Apostle.Mail{}=mail, key, value do
Map.put mail, key, value
end
def set_header %Apostle.Mail{}=mail, _name, nil do
mail
end
@doc """
Set an email header.
"""
def set_header %Apostle.Mail{}=mail, name, value do
headers = Map.put mail.headers, name, value
Map.put mail, :headers, headers
end
def set_data %Apostle.Mail{}=mail, _key, nil do
mail
end
@doc """
Set a key and value to the mail's data (ie template variables)
"""
def set_data %Apostle.Mail{}=mail, key, value do
data = Map.put mail.data, key, value
Map.put mail, :data, data
end
@doc """
Add a file attachment, using a path on the filesystem.
"""
def add_attachment(%Apostle.Mail{}=mail, path) when is_binary(path) do
file_name = Path.basename path
{:ok, content} = File.read path
add_attachment mail, file_name, content
end
@doc """
Add a file attachment by passing in a file name and content.
"""
def add_attachment %Apostle.Mail{}=mail, file_name, content do
attachments = Map.put mail.attachments, file_name, content
Map.put mail, :attachments, attachments
end
# Move values directly from the options map into the mail struct
defp parse_value {%Apostle.Mail{}=mail, opts}, key do
value = Dict.get opts, key
opts = Dict.delete opts, key
mail = set_value mail, key, value
{mail, opts}
end
# Move header values from the options mail into the mail's header map.
defp parse_header {%Apostle.Mail{}=mail, opts}, key do
value = Dict.get opts, key
opts = Dict.delete opts, key
mail = set_header mail, key, value
{mail, opts}
end
defp parse_attachments {%Apostle.Mail{}=mail, opts} do
attachments = Dict.get opts, :attachments, []
mail = Enum.reduce(attachments, mail, fn
({file_name, content}, mail) -> add_attachment mail, file_name, content
(path, mail) -> add_attachment mail, path
end)
opts = Dict.delete opts, :attachments
{mail, opts}
end
# Merge all remaining options into the mail's data map.
defp parse_data {%Apostle.Mail{}=mail, opts} do
Enum.reduce opts, mail, fn({k,v},r)-> set_data r, k, v end
end
end