Skip to content

Commit

Permalink
feature: optional-providers
Browse files Browse the repository at this point in the history
Make burner email domains optional. We do this
by accepting optional keyword list `opts`.

```
  @good_domains ["com.ar", ...]
  @providers Burnex.providers |> MapSet.delete(@good_domains)

  ...

  def is_burner?(email) do
     Burnex.is_burner?(email, providers: @providers)
  end
```
  • Loading branch information
alexbenic committed Sep 25, 2021
1 parent 7a66f17 commit 874c155
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 12 deletions.
47 changes: 35 additions & 12 deletions lib/burnex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,19 @@ defmodule Burnex do

@dialyzer {:nowarn_function, is_burner_domain?: 1}

@typep option :: {:providers, MapSet.t()}

@doc """
Check if email is a temporary / burner address.
Optionally resolve the MX record
## Options
* providers - (set of domains) this option specifies
burner email domains to match against. Defaults to:
[list of domains](https://github.com/Betree/burnex/blob/master/priv/burner-email-providers/emails.txt)
## Examples
iex> Burnex.is_burner?("[email protected]")
Expand All @@ -29,11 +37,13 @@ defmodule Burnex do
false
"""
@spec is_burner?(binary()) :: boolean()
def is_burner?(email) do
@spec is_burner?(binary(), list(option)) :: boolean()
def is_burner?(email, opts \\ []) when is_list(opts) do
providers = Keyword.get(opts, :providers, @providers)

case Regex.run(~r/@([^@]+)$/, String.downcase(email)) do
[_ | [domain]] ->
is_burner_domain?(domain)
is_burner_domain?(domain, providers: providers)

_ ->
# Bad email format
Expand All @@ -44,6 +54,12 @@ defmodule Burnex do
@doc """
Check a domain is a burner domain.
## Options
* providers - (set of domains) this option specifies
burner email domains to match against. Defaults to:
[list of domains](https://github.com/Betree/burnex/blob/master/priv/burner-email-providers/emails.txt)
## Examples
iex> Burnex.is_burner_domain?("yopmail.fr")
Expand All @@ -54,13 +70,15 @@ defmodule Burnex do
false
"""
@spec is_burner_domain?(binary()) :: boolean()
def is_burner_domain?(domain) do
case MapSet.member?(@providers, domain) do
@spec is_burner_domain?(binary(), list(option)) :: boolean()
def is_burner_domain?(domain, opts \\ []) when is_list(opts) do
providers = Keyword.get(opts, :providers, @providers)

case MapSet.member?(providers, domain) do
false ->
case Regex.run(~r/^[^.]+[.](.+)$/, domain) do
[_ | [higher_domain]] ->
is_burner_domain?(higher_domain)
is_burner_domain?(higher_domain, providers: providers)

_ ->
false
Expand All @@ -84,24 +102,29 @@ defmodule Burnex do
@providers
end

defp bad_mx_server_domains(mx_resolution) do
defp bad_mx_server_domains(mx_resolution, opts) do
providers = Keyword.get(opts, :providers, @providers)

Enum.filter(mx_resolution, fn item ->
case item do
{_port, server_domain} ->
server_domain
|> to_string()
|> is_burner_domain?()
|> is_burner_domain?(providers: providers)

_ ->
true
end
end)
end

@spec check_domain_mx_record(binary()) :: :ok | {:error, binary()}
def check_domain_mx_record(domain) do
@spec check_domain_mx_record(binary(), list(option)) :: :ok | {:error, binary()}
def check_domain_mx_record(domain, opts \\ []) when is_list(opts) do
providers = Keyword.get(opts, :providers, @providers)

with {:dns_resolve, {:ok, mx_resolution}} <- {:dns_resolve, DNS.resolve(domain, :mx)},
{:bad_server_domains, []} <- {:bad_server_domains, bad_mx_server_domains(mx_resolution)} do
{:bad_server_domains, []} <-
{:bad_server_domains, bad_mx_server_domains(mx_resolution, providers: providers)} do
:ok
else
{:dns_resolve, _} ->
Expand Down
7 changes: 7 additions & 0 deletions test/burnex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ defmodule BurnexTest do
refute Enum.any?(Burnex.providers(), &(String.downcase(&1) != &1))
end

test "should respect passed providers" do
good_provider = Burnex.providers() |> Enum.random()
providers = Burnex.providers() |> MapSet.delete(good_provider)

refute Burnex.is_burner?("test@" <> good_provider, providers: providers)
end

property "doesn't explode if email has bad format" do
check all(email <- StreamData.string(:alphanumeric)) do
refute Burnex.is_burner?(email)
Expand Down

0 comments on commit 874c155

Please sign in to comment.