Elixir
Elixir SDK for the Poodle email sending API.
Table of Contents
Section titled “Table of Contents”- Features
- Installation
- Quick Start
- Configuration
- Usage Examples
- API Reference
- Error Types
- Phoenix Integration
- Development
- Contributing
- License
Features
Section titled “Features”- 🚀 Simple and intuitive API
- 📧 HTML and plain text email support
- 🔒 Comprehensive error handling
- ⚡ Asynchronous email sending
- 🛡️ Built-in input validation
- 📊 Rate limiting support
- 🔧 Configurable via environment variables
- 🎯 Pattern-matchable error tuples
- 📖 Complete documentation and examples
- ✅ Elixir 1.14+ support
Installation
Section titled “Installation”Add poodle
to your list of dependencies in mix.exs
:
def deps do [ {:poodle, "~> 1.0"} ]end
Then run:
mix deps.get
Quick Start
Section titled “Quick Start”1. Set your API key
Section titled “1. Set your API key”export POODLE_API_KEY=your_api_key_here
2. Send your first email
Section titled “2. Send your first email”# Send an HTML email{:ok, response} = Poodle.send_html( "Hello from Poodle!", "<h1>Welcome!</h1><p>This is a test email.</p>")
IO.puts("Email sent! Message: #{response.message}")
Configuration
Section titled “Configuration”The SDK can be configured via environment variables or application config:
Environment Variables
Section titled “Environment Variables”export POODLE_API_KEY=your_api_keyexport POODLE_BASE_URL=https://api.usepoodle.comexport POODLE_TIMEOUT=30000export POODLE_DEBUG=false
Application Config
Section titled “Application Config”config :poodle, api_key: "your_api_key", base_url: "https://api.usepoodle.com", timeout: 30_000, debug: false
Usage Examples
Section titled “Usage Examples”Basic Email Sending
Section titled “Basic Email Sending”# HTML email{:ok, response} = Poodle.send_html( "Welcome!", "<h1>Hello World!</h1><p>Welcome to our service!</p>")
# Plain text email{:ok, response} = Poodle.send_text( "Welcome!", "Hello World! Welcome to our service!")
# Both HTML and text{:ok, response} = Poodle.send( "Welcome!", html: "<h1>Hello World!</h1>", text: "Hello World!")
Using Email Structs
Section titled “Using Email Structs”# Create an email struct{:ok, email} = Poodle.Email.new( "Welcome!", html: "<h1>Hello World!</h1>", text: "Hello World!")
# Send the email{:ok, response} = Poodle.send_email(email)
Asynchronous Sending
Section titled “Asynchronous Sending”# Send email asynchronouslytask = Poodle.send_async( "Welcome!", html: "<h1>Hello World!</h1>")
# Wait for result{:ok, response} = Task.await(task)
Error Handling
Section titled “Error Handling”case Poodle.send_html(from, to, subject, html) do {:ok, response} -> IO.puts("Email sent! Message: #{response.message}")
# Check rate limit info if response.rate_limit do IO.puts("Rate limit remaining: #{response.rate_limit.remaining}") end
{:error, %Poodle.Error{type: :unauthorized}} -> IO.puts("Invalid API key")
{:error, %Poodle.Error{type: :rate_limit_exceeded, retry_after: retry_after}} -> IO.puts("Rate limited. Retry after #{retry_after} seconds")
{:error, %Poodle.Error{type: :validation_error, message: message}} -> IO.puts("Validation error: #{message}")
{:error, %Poodle.Error{type: :payment_required}} -> IO.puts("Subscription expired or limit reached")
{:error, error} -> IO.puts("Error: #{error.message}")end
API Reference
Section titled “API Reference”Main Functions
Section titled “Main Functions”Poodle.send/4
- Send email with HTML and/or text contentPoodle.send_html/5
- Send HTML emailPoodle.send_text/5
- Send plain text emailPoodle.send_email/3
- Send email using Email structPoodle.send_async/4
- Send email asynchronouslyPoodle.validate_config/1
- Validate configuration
Data Structures
Section titled “Data Structures”Email Struct
Section titled “Email Struct”%Poodle.Email{ subject: "Email Subject", html: "<h1>HTML content</h1>", # optional text: "Plain text content" # optional}
Response Struct
Section titled “Response Struct”%Poodle.Response{ success: true, message: "Email queued for sending", rate_limit: %Poodle.RateLimit{ limit: 2, remaining: 1, reset: 1640995200 }}
Error Struct
Section titled “Error Struct”%Poodle.Error{ type: :rate_limit_exceeded, message: "Rate limit exceeded", status_code: 429, retry_after: 30, details: %{...}}
Error Types
Section titled “Error Types”The SDK provides specific error types for different scenarios:
:validation_error
- Invalid input data:unauthorized
- Invalid or missing API key:forbidden
- Account suspended:payment_required
- Subscription issues:rate_limit_exceeded
- Rate limit exceeded:server_error
- Server-side errors:network_error
- Network connectivity issues:timeout
- Request timeout:dns_error
- DNS resolution failed:ssl_error
- SSL/TLS errors
Phoenix Integration
Section titled “Phoenix Integration”In a Phoenix Controller
Section titled “In a Phoenix Controller”defmodule MyAppWeb.EmailController do use MyAppWeb, :controller
def send_welcome(conn, %{"email" => email, "name" => name}) do case Poodle.send_html( email, "Welcome, #{name}!", render_welcome_email(name) ) do {:ok, _response} -> json(conn, %{success: true, message: "Welcome email sent"})
{:error, error} -> conn |> put_status(:unprocessable_entity) |> json(%{success: false, error: error.message}) end end
defp render_welcome_email(name) do """ <h1>Welcome, #{name}!</h1> <p>Thank you for joining our service.</p> """ endend
Background Jobs with Oban
Section titled “Background Jobs with Oban”defmodule MyApp.Workers.EmailWorker do use Oban.Worker, queue: :emails
@impl Oban.Worker def perform(%Oban.Job{args: %{"type" => "welcome", "email" => email, "name" => name}}) do case Poodle.send_html( email, "Welcome, #{name}!", render_welcome_email(name) ) do {:ok, _response} -> :ok {:error, _error} -> {:error, "Failed to send email"} end end
defp render_welcome_email(name) do """ <h1>Welcome, #{name}!</h1> <p>Thank you for joining our service.</p> """ endend
Development
Section titled “Development”Running Tests
Section titled “Running Tests”# Set test environment variablesexport POODLE_API_KEY=test_api_key
# Run testsmix test
# Run tests with coveragemix test --cover
Code Quality
Section titled “Code Quality”# Format codemix format
# Run Credomix credo
# Run Dialyzermix dialyzer
Contributing
Section titled “Contributing”Contributions are welcome! Please read our Contributing Guide for details on the process for submitting pull requests and our Code of Conduct.
License
Section titled “License”This project is licensed under the MIT License - see the LICENSE file for details.