Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for new Marketing API (Contacts and Lists) #44

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ config :sendgrid,
sandbox_enable: true,
phoenix_view: SendGrid.EmailView,
test_address: System.get_env("SENDGRID_TEST_EMAIL")

config :phoenix, :json_library, Jason
18 changes: 18 additions & 0 deletions lib/sendgrid.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ defmodule SendGrid do
|> parse_response()
end

@doc """
Performs a PUT request.

## Options

* `:api_key` - API key to use with the request.
* `:query` - Keyword list of query params to use with the request.
"""
@spec put(path :: String.t(), body :: map(), options :: options()) ::
{:ok, Response.t()} | {:error, any()}
def put(path, body, opts \\ []) when is_map(body) and is_list(opts) do
opts
|> api_key()
|> build_client()
|> Tesla.put(path, body, query_opts(opts))
|> parse_response()
end

@doc """
Performs a PATCH request.

Expand Down
82 changes: 82 additions & 0 deletions lib/sendgrid/marketing_campaigns/contacts.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
defmodule SendGrid.Marketing.Contacts do
@moduledoc """
Module to interact with contacts.

See SendGrid's [Contact API Docs](https://sendgrid.api-docs.io/v3.0/contacts)
for more detail.
"""

@base_api_url "/v3/marketing/contacts"

@doc """
Adds one or multiple contacts to one or multiple lists available in Marketing Campaigns.

When adding a contact, an email address must be provided at a minimum.
The process is asynchrnous and SendGrid will return a Job ID to check the status.

## Options

* `:api_key` - API key to use with the request.

## Examples

{:ok, recipient_id} = add(["111-222-333"], [%{email: "[email protected]", first_name: "Test"}])
"""
@spec add(list(String.t()), list(), [SendGrid.api_key()]) ::
{:ok, String.t()} | {:error, [String.t(), ...]}
def add(list_ids, contacts, opts \\ []) when is_list(opts) do
data = %{list_ids: list_ids, contacts: contacts}

with {:ok, response} <- SendGrid.put(@base_api_url, data, opts) do
handle_result(response)
end
end

@doc """
Deletes a contact.
The process is asynchrnous and SendGrid will return a Job ID to check the status.

## Options

* `:api_key` - API key to use with the request.
"""
@spec delete(list(), [SendGrid.api_key()]) :: {:ok, String.t()} | {:error, any()}
def delete(contact_ids, opts \\ []) when is_list(opts) do
ids = Enum.join(contact_ids, ",")
url = "#{@base_api_url}?ids=#{ids}"

with {:ok, response} <- SendGrid.delete(url, opts) do
handle_result(response)
end
end

@doc """
Deletes all contacts.
The process is asynchrnous and SendGrid will return a Job ID to check the status.

## Options

* `:api_key` - API key to use with the request.
"""
@spec delete_all([SendGrid.api_key()]) :: {:ok, String.t()} | {:error, any()}
def delete_all(opts \\ []) when is_list(opts) do
url = "#{@base_api_url}?delete_all_contacts=true"

with {:ok, response} <- SendGrid.delete(url, opts) do
handle_result(response)
end
end

# Handles the result when it's valid.
defp handle_result(%{body: %{"job_id" => job_id}}) do
{:ok, job_id}
end

# Handles the result when errors are present.
defp handle_result(%{body: %{"error_count" => count} = body}) when count > 0 do
errors = Enum.map(body["errors"], & &1["message"])
{:error, errors}
end

defp handle_result(data), do: {:error, data}
end
36 changes: 0 additions & 36 deletions lib/sendgrid/marketing_campaigns/contacts/recipient.ex

This file was deleted.

50 changes: 0 additions & 50 deletions lib/sendgrid/marketing_campaigns/contacts/recipients.ex

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
defmodule SendGrid.Contacts.Lists do
defmodule SendGrid.Marketing.Lists do
@moduledoc """
Module to interact with modifying email lists.

See SendGrid's [Contact API Docs](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html)
See SendGrid's [Contact API Docs](https://sendgrid.api-docs.io/v3.0/lists)
for more detail.
"""

@base_api_url "/v3/contactdb/lists"
@base_api_url "/v3/marketing/lists"

@doc """
Retrieves all email lists.
Expand All @@ -17,7 +17,7 @@ defmodule SendGrid.Contacts.Lists do
"""
@spec all([SendGrid.api_key()]) :: {:ok, [map()]} | {:error, any()}
def all(opts \\ []) when is_list(opts) do
with {:ok, %{status: 200, body: %{"lists" => lists}}} <- SendGrid.get(@base_api_url, opts) do
with {:ok, %{status: 200, body: %{"result" => lists}}} <- SendGrid.get(@base_api_url, opts) do
{:ok, lists}
end
end
Expand Down Expand Up @@ -67,34 +67,33 @@ defmodule SendGrid.Contacts.Lists do
end

@doc """
Adds a recipient to an email list.
Removes a contact from a list.

## Options

* `:api_key` - API key to use with the request.
"""
@spec add_recipient(integer(), String.t(), [SendGrid.api_key()]) :: :ok | {:error, any()}
def add_recipient(list_id, recipient_id, opts \\ []) when is_list(opts) do
url = "#{@base_api_url}/#{list_id}/recipients/#{recipient_id}"

with {:ok, %{status: 201}} <- SendGrid.post(url, %{}, opts) do
:ok
@spec remove_contact(list(String.t()), list(String.t())[SendGrid.api_key()]) ::
{:ok, String.t()} | {:error, any()}
def remove_contact(list_id, contact_ids, opts \\ []) when is_list(opts) do
ids = Enum.join(contact_ids, ",")
url = "#{@base_api_url}/#{list_id}/contacts?contact_ids=#{ids}"

with {:ok, response} <- SendGrid.delete(url, opts) do
handle_result(response)
end
end

@doc """
Deletes a recipient from an email list.

## Options

* `:api_key` - API key to use with the request.
"""
@spec delete_recipient(integer, String.t(), [SendGrid.api_key()]) :: :ok | {:error, any()}
def delete_recipient(list_id, recipient_id, opts \\ []) when is_list(opts) do
url = "#{@base_api_url}/#{list_id}/recipients/#{recipient_id}"
# Handles the result when it's valid.
defp handle_result(%{body: %{"job_id" => job_id}}) do
{:ok, job_id}
end

with {:ok, %{status: 204}} <- SendGrid.delete(url, opts) do
:ok
end
# Handles the result when errors are present.
defp handle_result(%{body: %{"error_count" => count} = body}) when count > 0 do
errors = Enum.map(body["errors"], & &1["message"])
{:error, errors}
end

defp handle_result(data), do: {:error, data}
end
12 changes: 6 additions & 6 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ defmodule SendGrid.Mixfile do

# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
defp elixirc_paths(_), do: ["lib"]

defp deps do
[
{:dialyxir, "~> 1.0.0-rc.4", only: [:dev, :test], runtime: false},
{:earmark, "~> 1.2", only: :dev},
{:ex_doc, "~> 0.19", only: :dev},
{:jason, "~> 1.1"},
{:phoenix, "~> 1.2", only: :test},
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false},
{:earmark, "~> 1.2", only: :dev},
{:ex_doc, "~> 0.19", only: :dev},
{:jason, "~> 1.2"},
{:phoenix, "~> 1.2", only: :test},
{:phoenix_html, "~> 2.9", only: :test},
{:tesla, "~> 1.2"}
]
Expand Down
Loading