
Building a Robust Email API with Phoenix and Amazon SES
Juma Baraka / March 5, 2025
In the world of web development, sending emails programmatically is a crucial feature for many applications. As an Elixir and Phoenix developer, I recently created a reliable email API using Phoenix and Amazon Simple Email Service (SES). This blog post walks through my implementation, highlighting the power and elegance of Elixir for building scalable backend services.
Why Phoenix and Amazon SES?
Choosing the right technology stack is critical for any project. I opted for:
- Phoenix: A powerful Elixir web framework known for its performance and reliability
- Amazon SES: A cost-effective, scalable email sending service
- Elixir: A functional programming language that excels in concurrent and distributed systems
Technical Implementation
Dependencies
First, I added the necessary dependencies to my mix.exs
:
def deps do
[
{:swoosh, "~> 1.8"} # Email library for Elixir
{:gen_smtp, "~> 1.0"}
]
end
Configuration
defmodule YourApp.Mailer do
use Swoosh.Mailer, otp_app: :your_app
end
Configuring Amazon SES required careful management of credentials:
# config/config.exs
config :your_app, YourApp.Mailer,
adapter: Swoosh.Adapters.AmazonSES,
region: "us-east-1",
access_key: System.get_env("AWS_ACCESS_KEY_ID"),
secret: System.get_env("AWS_SECRET_ACCESS_KEY")
Email Context Module
I created a dedicated context module to handle email-related logic:
defmodule YourApp.Email do
import Swoosh.Email
def welcome_email(user) do
new()
|> to({user.name, user.email})
|> from("alerts@yourapp.net")
|> subject("Welcome to Your App")
|> html_body("<h1>Welcome to Your App!</h1><p>We're excited to have you on board!</p>")
|> text_body("Welcome to Your App! We're excited to have you on board!")
end
def notification_email(recipient, subject, body) do
new()
|> to(recipient)
|> from("YourApp Support <alerts@yourapp.net>")
|> subject(subject)
|> html_body(body)
|> text_body(String.replace(body, ~r/<[^>]*>/, ""))
end
end
Phoenix Controller Integration
Integrating the email sending into a Phoenix controller:
defmodule YourAppWeb.EmailController do
use YourAppWeb, :controller
alias YourApp.Email
alias YourApp.Mailer
def send(conn, email_params) do
with {:ok, _result} <- send_email(email_params) do
conn
|> put_status(:ok)
|> json(%{status: "success", message: "Email sent successfully"})
else
{:error, reason} ->
conn
|> put_status(:bad_request)
|> json(%{status: "error", message: reason})
end
end
defp send_email(%{to: to, subject: subject, body: body}) do
try do
packet = Email.notification_email(to, subject, body)
result = packet |> Mailer.deliver()
case result do
{:ok, _} ->
{:ok, "Email sent successfully"}
{:error, reason} ->
{:error, "Failed to send email: #{inspect(reason)}"}
end
rescue
e ->
{:error, "Exception while sending email: #{inspect(e)}"}
end
end
end
Performance Considerations
Elixir's concurrency model shines when handling email sending:
- Lightweight processes allow for async email dispatching
- Built-in fault tolerance prevents system-wide failures
- Easy to scale horizontally
Security Measures
- Use environment variables for AWS credentials
- Implement rate limiting
- Add logging for tracking email events
- Use secure email templates
Lessons Learned
- Always handle potential failures in email sending
- Use environment-specific configurations
- Leverage Elixir's pattern matching for clean code
- Implement proper error tracking and logging
Conclusion
Building an email API with Phoenix and Amazon SES showcases the power of Elixir for creating robust, scalable backend services. The combination of functional programming principles and powerful libraries makes complex tasks like email sending straightforward and reliable.
About the Developer
I'm a passionate Elixir and Phoenix developer with a focus on building scalable, maintainable backend systems. This project demonstrates my ability to:
- Integrate third-party services
- Write clean, functional code
- Handle complex scenarios with elegant solutions
Looking for an Elixir developer? Let's connect!
Technologies Used:
- Elixir
- Phoenix Framework
- Amazon SES
- Swoosh