Packages

phoenix_kit

1.7.33
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps โ€” SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib mix tasks phoenix_kit email_test_webhook.ex
Raw

lib/mix/tasks/phoenix_kit/email_test_webhook.ex

defmodule Mix.Tasks.PhoenixKit.Email.TestWebhook do
@shortdoc "Test email webhook functionality"
@moduledoc """
Mix task to test email webhook functionality with sample events.
## Usage
# Test bounce event
mix phoenix_kit.email.test_webhook --event bounce
# Test open event with specific message ID
mix phoenix_kit.email.test_webhook --event open --message-id abc123
# Test delivery event
mix phoenix_kit.email.test_webhook --event delivery
# Test all event types
mix phoenix_kit.email.test_webhook --all
## Options
--event TYPE Event type to test: bounce, delivery, send, open, click, complaint
--message-id ID Use specific message ID (uses random if not provided)
--all Test all event types
--endpoint URL Custom webhook endpoint URL
--no-verify Skip signature verification (for testing)
## Event Types
send - Email send confirmation
delivery - Successful delivery
bounce - Hard/soft bounce
complaint - Spam complaint
open - Email opened (AWS SES)
click - Link clicked
## Examples
# Test bounce handling
mix phoenix_kit.email.test_webhook --event bounce --message-id test-123
# Test all events with custom endpoint
mix phoenix_kit.email.test_webhook --all --endpoint {prefix}/webhooks/email
# Where {prefix} is your configured PhoenixKit URL prefix
# Quick delivery test
mix phoenix_kit.email.test_webhook --event delivery
"""
use Mix.Task
alias PhoenixKit.Modules.Emails
@impl Mix.Task
def run(args) do
Mix.Task.run("app.start")
{options, _remaining} = parse_options(args)
unless Emails.enabled?() do
Mix.shell().error("Email is not enabled.")
exit({:shutdown, 1})
end
Mix.shell().info(IO.ANSI.cyan() <> "\n๐Ÿงช Email Webhook Testing" <> IO.ANSI.reset())
Mix.shell().info(String.duplicate("=", 40))
if options[:all] do
test_all_events(options)
else
event_type = options[:event] || "delivery"
test_single_event(event_type, options)
end
end
defp parse_options(args) do
{options, remaining, _errors} =
OptionParser.parse(args,
strict: [
event: :string,
message_id: :string,
all: :boolean,
endpoint: :string,
no_verify: :boolean
]
)
# Set defaults
options =
options
|> Keyword.put_new(:all, false)
|> Keyword.put_new(:no_verify, false)
{options, remaining}
end
defp test_all_events(options) do
event_types = ["send", "delivery", "bounce", "complaint", "open", "click"]
Mix.shell().info("Testing all event types...\n")
results =
Enum.map(event_types, fn event_type ->
result = test_single_event(event_type, options)
# Small delay between tests
Process.sleep(500)
{event_type, result}
end)
# Summary
Mix.shell().info("\n๐Ÿ“‹ Test Summary:")
for {event_type, result} <- results do
status_icon = if result == :ok, do: "โœ…", else: "โŒ"
Mix.shell().info(" #{status_icon} #{String.pad_trailing(event_type, 12)} #{result}")
end
end
defp test_single_event(event_type, options) do
Mix.shell().info("๐Ÿงช Testing #{event_type} event...")
# Create test email log if needed
message_id = options[:message_id] || generate_test_message_id()
test_log = ensure_test_log(message_id)
# Generate test event
test_event = generate_test_event(event_type, message_id, test_log)
# Test webhook processing
case test_webhook_processing(test_event, options) do
:ok ->
Mix.shell().info("โœ… #{event_type} event processed successfully")
:ok
{:error, reason} ->
Mix.shell().error("โŒ #{event_type} event failed: #{reason}")
{:error, reason}
end
end
defp generate_test_message_id do
timestamp = DateTime.utc_now() |> DateTime.to_unix()
"test-webhook-#{timestamp}-#{:rand.uniform(9999)}"
end
defp ensure_test_log(message_id) do
case Emails.get_log_by_message_id(message_id) do
{:error, :not_found} ->
# Create a test log
{:ok, log} =
Emails.create_log(%{
message_id: message_id,
to: "test@example.com",
from: "noreply@phoenixkit.dev",
subject: "Test Email for Webhook",
status: "sent",
provider: "test_provider",
sent_at: DateTime.utc_now()
})
Mix.shell().info("๐Ÿ“ง Created test email log: #{message_id}")
log
{:ok, log} ->
Mix.shell().info("๐Ÿ“ง Using existing email log: #{message_id}")
log
{:error, reason} ->
Mix.shell().error("โŒ Error getting email log: #{inspect(reason)}")
nil
end
end
defp generate_test_event(event_type, message_id, _log) do
base_event = %{
"Type" => "Notification",
"MessageId" => "webhook-test-#{:rand.uniform(99999)}",
"Timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"Message" => Jason.encode!(generate_ses_message(event_type, message_id))
}
base_event
end
defp generate_ses_message("send", message_id) do
%{
"eventType" => "send",
"mail" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"messageId" => message_id,
"source" => "test@phoenixkit.dev",
"destination" => ["test@example.com"]
},
"send" => %{}
}
end
defp generate_ses_message("delivery", message_id) do
%{
"eventType" => "delivery",
"mail" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"messageId" => message_id,
"source" => "test@phoenixkit.dev",
"destination" => ["test@example.com"]
},
"delivery" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"processingTimeMillis" => 2000,
"recipients" => ["test@example.com"],
"smtpResponse" => "250 2.0.0 OK"
}
}
end
defp generate_ses_message("bounce", message_id) do
%{
"eventType" => "bounce",
"mail" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"messageId" => message_id,
"source" => "test@phoenixkit.dev",
"destination" => ["bounce@example.com"]
},
"bounce" => %{
"bounceType" => "Permanent",
"bounceSubType" => "General",
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"feedbackId" => "test-bounce-#{:rand.uniform(9999)}",
"bouncedRecipients" => [
%{
"emailAddress" => "bounce@example.com",
"status" => "5.1.1",
"action" => "failed",
"diagnosticCode" => "smtp; 550 5.1.1 User unknown"
}
]
}
}
end
defp generate_ses_message("complaint", message_id) do
%{
"eventType" => "complaint",
"mail" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"messageId" => message_id,
"source" => "test@phoenixkit.dev",
"destination" => ["complaint@example.com"]
},
"complaint" => %{
"complainedRecipients" => [
%{
"emailAddress" => "complaint@example.com"
}
],
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"feedbackId" => "test-complaint-#{:rand.uniform(9999)}",
"complaintFeedbackType" => "abuse"
}
}
end
defp generate_ses_message("open", message_id) do
%{
"eventType" => "open",
"mail" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"messageId" => message_id,
"source" => "test@phoenixkit.dev",
"destination" => ["test@example.com"]
},
"open" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"userAgent" => "Mozilla/5.0 (Test Webhook)",
"ipAddress" => "192.0.2.1"
}
}
end
defp generate_ses_message("click", message_id) do
%{
"eventType" => "click",
"mail" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"messageId" => message_id,
"source" => "test@phoenixkit.dev",
"destination" => ["test@example.com"]
},
"click" => %{
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"userAgent" => "Mozilla/5.0 (Test Webhook)",
"ipAddress" => "192.0.2.1",
"link" => "https://example.com/test-link",
"linkTags" => %{
"campaign" => "test"
}
}
}
end
defp test_webhook_processing(webhook_data, _options) do
# Process the webhook event using EmailTracking
case Emails.process_webhook_event(webhook_data) do
{:ok, _event} ->
:ok
{:error, :email_log_not_found} ->
# This might be expected for some test cases
Mix.shell().info("โ„น๏ธ Note: Email log not found (this may be expected for test events)")
:ok
{:error, reason} ->
{:error, reason}
end
rescue
error ->
{:error, Exception.message(error)}
end
end