Packages
phoenix_kit
1.7.21
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
Current section
Files
lib/mix/tasks/phoenix_kit.sync_email_status.ex
defmodule Mix.Tasks.PhoenixKit.SyncEmailStatus do
@shortdoc "Sync email status by AWS SES message ID"
@moduledoc """
Mix task to manually sync email status by AWS SES message ID.
This task searches for a specific email by message ID and synchronizes
its delivery status by fetching events from AWS SQS queues.
## Usage
# Sync status for specific message ID
mix phoenix_kit.sync_email_status MESSAGE_ID
# With verbose output
mix phoenix_kit.sync_email_status MESSAGE_ID --verbose
## Examples
# Sync email with AWS SES message ID
mix phoenix_kit.sync_email_status "01000189971abc123-fed456-4e89-b012-defg345678hi"
# With detailed logging
mix phoenix_kit.sync_email_status "01000189971abc123-fed456-4e89-b012-defg345678hi" --verbose
## What this task does:
1. **Find Email Log**: Searches for email log by message_id
2. **Check SQS Queue**: Looks for events in main SQS queue
3. **Check DLQ**: Looks for events in Dead Letter Queue
4. **Process Events**: Updates email status based on found events
5. **Report Results**: Shows summary of synchronization
## Output
The task will show:
- Email log found/not found status
- Number of events found in SQS
- Number of events found in DLQ
- Processing results
- Final email status
## Requirements
- Email system must be enabled
- AWS SES integration must be configured
- SQS queue configuration must be set up
"""
use Mix.Task
alias PhoenixKit.Modules.Emails
alias PhoenixKit.Modules.Emails.{Log, SQSProcessor}
@impl Mix.Task
def run(args) do
{opts, args_list, _} =
OptionParser.parse(args,
strict: [verbose: :boolean, help: :boolean],
aliases: [v: :verbose, h: :help]
)
case args_list do
[] ->
print_help()
[message_id | _] ->
if opts[:help] do
print_help()
else
# Start the application
Mix.Task.run("app.start")
verbose = opts[:verbose] || false
if verbose do
IO.puts("🔍 Starting email status sync for message ID: #{message_id}")
end
case sync_email_status(message_id, verbose) do
{:ok, result} ->
print_success_result(result, verbose)
{:error, reason} ->
print_error(reason, verbose)
System.halt(1)
end
end
end
end
## --- Private Functions ---
defp sync_email_status(message_id, verbose) do
# Check if tracking is enabled
if Emails.enabled?() do
if verbose, do: IO.puts("✅ Email system is enabled")
# Step 1: Find existing email log
{existing_log, log_status} = find_existing_log(message_id, verbose)
# Step 2: Search for events in SQS and DLQ
{sqs_events, dlq_events} = fetch_events_from_queues(message_id, verbose)
total_events = length(sqs_events) + length(dlq_events)
if verbose do
IO.puts(
"📊 Found #{length(sqs_events)} events in SQS, #{length(dlq_events)} events in DLQ"
)
end
if total_events == 0 do
{:ok,
%{
log_found: existing_log != nil,
log_status: log_status,
events_found: 0,
events_processed: 0,
message: "No events found for this message ID",
final_status: existing_log && existing_log.status
}}
else
# Step 3: Process all events
process_results = process_events(sqs_events ++ dlq_events, verbose)
# Step 4: Get final status
final_log_status =
case find_existing_log(message_id, false) do
{log, _} when not is_nil(log) -> log.status
_ -> nil
end
{:ok,
%{
log_found: existing_log != nil,
log_status: log_status,
events_found: total_events,
events_processed: length(process_results[:successful]),
failed_events: length(process_results[:failed]),
message: "Synchronization completed",
final_status: final_log_status,
process_details: process_results
}}
end
else
{:error, "Email system is not enabled"}
end
end
defp find_existing_log(message_id, verbose) do
case Log.get_log_by_message_id(message_id) do
%PhoenixKit.Modules.Emails.Log{} = log ->
if verbose do
IO.puts("📧 Found existing email log: ID=#{log.id}, Status=#{log.status}")
end
{log, log.status}
nil ->
if verbose, do: IO.puts("❌ No existing email log found")
{nil, nil}
end
end
defp fetch_events_from_queues(message_id, verbose) do
if verbose, do: IO.puts("🔍 Searching for events in SQS queues...")
sqs_events = Emails.fetch_sqs_events_for_message(message_id)
dlq_events = Emails.fetch_dlq_events_for_message(message_id)
{sqs_events, dlq_events}
end
defp process_events(events, verbose) do
if verbose, do: IO.puts("⚡ Processing #{length(events)} events...")
results = %{successful: [], failed: []}
Enum.reduce(events, results, fn event, acc ->
case SQSProcessor.process_email_event(event) do
{:ok, result} ->
if verbose do
IO.puts(" ✅ Processed #{event["eventType"]} event successfully")
end
%{acc | successful: [result | acc.successful]}
{:error, reason} ->
if verbose do
IO.puts(" ❌ Failed to process #{event["eventType"]} event: #{inspect(reason)}")
end
%{acc | failed: [{event, reason} | acc.failed]}
end
end)
end
defp print_success_result(result, verbose) do
IO.puts("\n📊 Email Status Sync Results")
IO.puts("════════════════════════════")
IO.puts("📧 Message ID Status:")
if result.log_found do
IO.puts(" ✅ Email log found")
IO.puts(" 📍 Initial status: #{result.log_status || "unknown"}")
IO.puts(" 📍 Final status: #{result.final_status || "unknown"}")
else
IO.puts(" ❌ No email log found")
end
IO.puts("\n📈 Event Processing:")
IO.puts(" 🔍 Events found: #{result.events_found}")
IO.puts(" ✅ Events processed: #{result.events_processed}")
if result[:failed_events] && result.failed_events > 0 do
IO.puts(" ❌ Failed events: #{result.failed_events}")
end
IO.puts("\n💬 Result: #{result.message}")
if verbose && result[:process_details] do
print_process_details(result.process_details)
end
IO.puts("\n✅ Synchronization completed successfully!")
end
defp print_process_details(details) do
IO.puts("\n🔍 Processing Details:")
if not Enum.empty?(details.successful) do
IO.puts(" ✅ Successful events:")
Enum.each(details.successful, fn result ->
IO.puts(" • #{result[:type]} (Log ID: #{result[:log_id]})")
end)
end
if not Enum.empty?(details.failed) do
IO.puts(" ❌ Failed events:")
Enum.each(details.failed, fn {event, reason} ->
IO.puts(" • #{event["eventType"]}: #{inspect(reason)}")
end)
end
end
defp print_error(reason, verbose) do
IO.puts("\n❌ Email Status Sync Failed")
IO.puts("══════════════════════════")
IO.puts("Error: #{reason}")
if verbose do
IO.puts("\n🔍 Troubleshooting:")
IO.puts("• Check if email system is enabled")
IO.puts("• Verify AWS SES and SQS configuration")
IO.puts("• Ensure message ID is correct")
IO.puts("• Check AWS credentials and permissions")
end
end
defp print_help do
IO.puts("""
📧 PhoenixKit Email Status Sync
USAGE:
mix phoenix_kit.sync_email_status MESSAGE_ID [options]
ARGUMENTS:
MESSAGE_ID AWS SES message ID to sync
OPTIONS:
--verbose, -v Show detailed output
--help, -h Show this help
EXAMPLES:
mix phoenix_kit.sync_email_status "01000189971abc123-fed456-4e89-b012-defg345678hi"
mix phoenix_kit.sync_email_status "01000189971abc123-fed456-4e89-b012-defg345678hi" --verbose
DESCRIPTION:
This task synchronizes email delivery status by fetching events from AWS SQS
queues and updating the corresponding email log in the database.
""")
end
end