Keplers Mail Service

Phoenix Elixir

Phoenix Elixir integration examples for Keplers Mail Service

Send emails using Phoenix Elixir with Keplers Mail Service REST API.

Installation

Add to your mix.exs:

defp deps do
  [
    {:httpoison, "~> 2.0"},
    {:jason, "~> 1.4"}
  ]
end

Basic Setup

# config/config.exs
import Config

config :your_app,
  keplers_api_key: System.get_env("KEPLERS_API_KEY")

REST API Integration

Basic Client

# lib/your_app/services/keplers_email_client.ex
defmodule YourApp.Services.KeplersEmailClient do
  @base_url "https://api.keplars.com"

  defstruct [:api_key, :base_url]

  def new(api_key, base_url \\ @base_url) do
    %__MODULE__{
      api_key: api_key,
      base_url: String.trim_trailing(base_url, "/")
    }
  end

  def send_email(client, to, subject, body, is_html \\ false) do
    make_request(client, "/api/v1/send-email/queue", %{
      to: [to],
      subject: subject,
      body: body,
      is_html: is_html
    })
  end

  def send_instant_email(client, to, subject, body, is_html \\ false) do
    make_request(client, "/api/v1/send-email/instant", %{
      to: [to],
      subject: subject,
      body: body,
      is_html: is_html
    })
  end

  defp make_request(client, endpoint, payload) do
    url = client.base_url <> endpoint
    headers = [
      {"Authorization", "Bearer #{client.api_key}"},
      {"Content-Type", "application/json"}
    ]

    case Jason.encode(payload) do
      {:ok, json_payload} ->
        case HTTPoison.post(url, json_payload, headers, timeout: 30_000) do
          {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
            case Jason.decode(body) do
              {:ok, response} -> {:ok, response}
              {:error, _} -> {:error, :invalid_json}
            end

          {:ok, %HTTPoison.Response{status_code: status_code, body: body}} ->
            {:error, {:http_error, status_code, body}}

          {:error, %HTTPoison.Error{reason: reason}} ->
            {:error, {:request_failed, reason}}
        end

      {:error, _} ->
        {:error, :invalid_payload}
    end
  end
end

Usage Examples

# lib/your_app/services/email_service.ex
defmodule YourApp.Services.EmailService do
  alias YourApp.Services.KeplersEmailClient

  def client do
    api_key = Application.get_env(:your_app, :keplers_api_key)
    KeplersEmailClient.new(api_key)
  end

  def send_welcome_email(user_email, user_name) do
    html_body = """
    <h1>Welcome #{user_name}!</h1>
    <p>Thank you for joining our platform.</p>
    """

    case KeplersEmailClient.send_email(client(), user_email, "Welcome #{user_name}!", html_body, true) do
      {:ok, response} ->
        {:ok, response}
      {:error, reason} ->
        {:error, reason}
    end
  end

  def send_verification_email(user_email, code) do
    body = "Your verification code: #{code}"

    case KeplersEmailClient.send_instant_email(client(), user_email, "Verify Your Email", body, false) do
      {:ok, response} ->
        {:ok, response}
      {:error, reason} ->
        {:error, reason}
    end
  end
end

Phoenix Controller Integration

# lib/your_app_web/controllers/email_controller.ex
defmodule YourAppWeb.EmailController do
  use YourAppWeb, :controller

  alias YourApp.Services.EmailService

  def send_welcome(conn, %{"email" => email, "name" => name}) do
    case EmailService.send_welcome_email(email, name) do
      {:ok, _response} ->
        json(conn, %{success: true, message: "Welcome email sent successfully"})

      {:error, reason} ->
        conn
        |> put_status(:internal_server_error)
        |> json(%{success: false, error: "Failed to send email: #{inspect(reason)}"})
    end
  end

  def send_verification(conn, %{"email" => email, "code" => code}) do
    case EmailService.send_verification_email(email, code) do
      {:ok, _response} ->
        json(conn, %{success: true, message: "Verification email sent successfully"})

      {:error, reason} ->
        conn
        |> put_status(:internal_server_error)
        |> json(%{success: false, error: "Failed to send verification email: #{inspect(reason)}"})
    end
  end
end

LiveView Integration

# lib/your_app_web/live/email_live.ex
defmodule YourAppWeb.EmailLive do
  use YourAppWeb, :live_view

  alias YourApp.Services.EmailService

  def mount(_params, _session, socket) do
    {:ok, assign(socket, email: "", name: "", loading: false, message: nil)}
  end

  def handle_event("send_email", %{"email" => email, "name" => name}, socket) do
    socket = assign(socket, loading: true, message: nil)

    case EmailService.send_welcome_email(email, name) do
      {:ok, _response} ->
        {:noreply, assign(socket, loading: false, message: "Email sent successfully!", email: "", name: "")}

      {:error, _reason} ->
        {:noreply, assign(socket, loading: false, message: "Failed to send email")}
    end
  end

  def render(assigns) do
    ~H"""
    <div class="max-w-md mx-auto mt-8">
      <h1 class="text-2xl font-bold mb-4">Send Email</h1>
      
      <form phx-submit="send_email" class="space-y-4">
        <div>
          <label for="email" class="block text-sm font-medium">Email</label>
          <input type="email" id="email" name="email" value={@email} class="mt-1 block w-full rounded border" required />
        </div>
        
        <div>
          <label for="name" class="block text-sm font-medium">Name</label>
          <input type="text" id="name" name="name" value={@name} class="mt-1 block w-full rounded border" required />
        </div>
        
        <button type="submit" disabled={@loading} class="w-full bg-blue-500 text-white py-2 px-4 rounded disabled:opacity-50">
          <%= if @loading, do: "Sending...", else: "Send Email" %>
        </button>
      </form>
      
      <%= if @message do %>
        <div class="mt-4 p-4 rounded bg-green-100 text-green-800">
          <%= @message %>
        </div>
      <% end %>
    </div>
    """
  end
end

Phoenix Context Integration

# lib/your_app/accounts.ex
defmodule YourApp.Accounts do
  alias YourApp.Services.EmailService

  def register_user(attrs) do
    with {:ok, user} <- create_user(attrs),
         {:ok, _response} <- EmailService.send_welcome_email(user.email, user.name) do
      {:ok, user}
    else
      {:error, reason} -> {:error, reason}
    end
  end

  def send_verification_code(user) do
    code = generate_verification_code()
    
    with {:ok, _response} <- EmailService.send_verification_email(user.email, code) do
      {:ok, code}
    else
      {:error, reason} -> {:error, reason}
    end
  end

  defp generate_verification_code do
    :rand.uniform(900_000) + 100_000
    |> Integer.to_string()
  end

  defp create_user(_attrs) do
    # Your user creation logic here
    {:ok, %{email: "[email protected]", name: "John Doe"}}
  end
end

GenServer Background Worker

# lib/your_app/workers/email_worker.ex
defmodule YourApp.Workers.EmailWorker do
  use GenServer

  alias YourApp.Services.EmailService

  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  def send_welcome_email_async(email, name) do
    GenServer.cast(__MODULE__, {:send_welcome, email, name})
  end

  def init(_opts) do
    {:ok, %{}}
  end

  def handle_cast({:send_welcome, email, name}, state) do
    case EmailService.send_welcome_email(email, name) do
      {:ok, _response} ->
        IO.puts("Welcome email sent to #{email}")

      {:error, reason} ->
        IO.puts("Failed to send welcome email: #{inspect(reason)}")
    end

    {:noreply, state}
  end
end

Router Configuration

# lib/your_app_web/router.ex
defmodule YourAppWeb.Router do
  use YourAppWeb, :router

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/api", YourAppWeb do
    pipe_through :api

    post "/emails/welcome", EmailController, :send_welcome
    post "/emails/verification", EmailController, :send_verification
  end

  scope "/", YourAppWeb do
    pipe_through :browser

    live "/email", EmailLive, :index
  end
end

Phoenix Elixir provides robust email integration with Keplers Mail Service using HTTPoison for HTTP requests and built-in JSON handling.

On this page