defmodule Mix.Tasks.PhoenixKit.Email.SendTest do @shortdoc "Send test email to specific address" @moduledoc """ Mix task to send a test email to verify email system functionality. This task sends a test email to a specific address without requiring email system system configuration. Useful for basic email delivery testing. ## Usage # Send to specific email address mix phoenix_kit.email.send_test --to admin@example.com # Send to multiple addresses mix phoenix_kit.email.send_test --to admin@example.com,user@example.com # Send with custom subject mix phoenix_kit.email.send_test --to admin@example.com --subject "Custom Test Subject" # Include system (requires configured repo) mix phoenix_kit.email.send_test --to admin@example.com --track ## Options --to EMAIL Email address to send to (required) --subject SUBJECT Custom email subject (optional) --track Enable email system (requires repo configuration) --from EMAIL From email address (optional) ## Examples # Basic test email mix phoenix_kit.email.send_test --to admin@example.com # Multiple recipients with custom subject mix phoenix_kit.email.send_test --to "admin@example.com,user@example.com" --subject "PhoenixKit Test Email" # Test with system enabled mix phoenix_kit.email.send_test --to test@example.com --track """ use Mix.Task import Swoosh.Email @impl Mix.Task def run(args) do Mix.Task.run("app.start") {options, _remaining} = parse_options(args) recipient = options[:to] unless recipient do Mix.shell().error("--to option is required. Please specify recipient email address.") exit({:shutdown, 1}) end Mix.shell().info(IO.ANSI.cyan() <> "\nšŸ“§ Sending Test Email" <> IO.ANSI.reset()) Mix.shell().info(String.duplicate("=", 30)) send_test_email(options) end defp parse_options(args) do {options, remaining, _errors} = OptionParser.parse(args, strict: [ to: :string, subject: :string, track: :boolean, from: :string ] ) # Set defaults options = options |> Keyword.put_new(:subject, "PhoenixKit Test Email") |> Keyword.put_new(:track, false) |> Keyword.put_new(:from, "noreply@phoenixkit.dev") {options, remaining} end defp send_test_email(options) do recipients = parse_recipients(options[:to]) subject = options[:subject] from_email = options[:from] track_email = options[:track] Mix.shell().info("Recipients: #{Enum.join(recipients, ", ")}") Mix.shell().info("Subject: #{subject}") Mix.shell().info("From: #{from_email}") Mix.shell().info("Tracking: #{if track_email, do: "enabled", else: "disabled"}") Mix.shell().info("") timestamp = DateTime.utc_now() |> DateTime.to_string() Enum.each(recipients, fn recipient -> Mix.shell().info("šŸ“¤ Sending email to #{recipient}...") email = new() |> to(recipient) |> from({from_email, "PhoenixKit Test"}) |> subject(subject) |> html_body(html_email_body(recipient, timestamp, track_email)) |> text_body(text_email_body(recipient, timestamp, track_email)) result = if track_email do # Use PhoenixKit.Mailer with system PhoenixKit.Mailer.deliver_email(email, template_name: "test_email", campaign_id: "manual_test" ) else # Use basic Swoosh delivery without system send_via_configured_mailer(email) end case result do {:ok, _} -> Mix.shell().info("āœ… Email sent successfully to #{recipient}") {:error, reason} -> Mix.shell().error("āŒ Failed to send email to #{recipient}: #{inspect(reason)}") end # Small delay between emails Process.sleep(500) end) Mix.shell().info("\nšŸŽ‰ Test email sending completed!") end defp parse_recipients(recipient_string) do recipient_string |> String.split(",") |> Enum.map(&String.trim/1) |> Enum.reject(&(&1 == "")) end defp send_via_configured_mailer(email) do # Try to use PhoenixKit.Mailer directly, falling back to simple delivery mailer = PhoenixKit.Mailer.get_mailer() if mailer == PhoenixKit.Mailer do PhoenixKit.Mailer.deliver(email) else mailer.deliver(email) end rescue error -> Mix.shell().error("Mailer delivery failed: #{inspect(error)}") Mix.shell().info("Attempting basic Swoosh delivery...") # Fallback to basic SMTP if available deliver_with_basic_config(email) end defp deliver_with_basic_config(email) do # Simple SMTP configuration for testing # This is just for development/testing purposes adapter_config = [ adapter: Swoosh.Adapters.SMTP, relay: "smtp.gmail.com", port: 587, username: System.get_env("SMTP_USERNAME"), password: System.get_env("SMTP_PASSWORD"), tls: :if_available, retries: 1, no_mx_lookups: false ] if adapter_config[:username] && adapter_config[:password] do Swoosh.Mailer.deliver(email, adapter_config) else {:error, "No mailer configuration found. Please configure PhoenixKit.Mailer or set SMTP_USERNAME and SMTP_PASSWORD environment variables."} end end defp html_email_body(recipient, timestamp, track_enabled) do """ PhoenixKit Test Email

šŸ“§ PhoenixKit Test Email

Email System Verification

āœ… Success! This email was sent successfully through the PhoenixKit email system.

Hello,

This is a test email to verify your email system configuration. If you received this email, it indicates:

šŸ“Š Email Details:
Recipient: #{recipient}
Sent at: #{timestamp}
Tracking: #{if track_enabled, do: "Enabled", else: "Disabled"}
Type: Manual Test Email

You can safely ignore this email - it's just for testing purposes.

""" end defp text_email_body(recipient, timestamp, track_enabled) do """ PHOENIXKIT TEST EMAIL - EMAIL SYSTEM VERIFICATION ================================================ Success! This email was sent successfully through the PhoenixKit email system. Hello, This is a test email to verify your email system configuration. If you received this email, it indicates: āœ… Email delivery is working correctly āœ… SMTP/Email provider configuration is valid āœ… PhoenixKit mailer is functioning properly #{if track_enabled, do: "āœ… Email system system is operational", else: "ā„¹ļø Email system was not enabled for this test"} EMAIL DETAILS: -------------- Recipient: #{recipient} Sent at: #{timestamp} Tracking: #{if track_enabled, do: "Enabled", else: "Disabled"} Type: Manual Test Email You can safely ignore this email - it's just for testing purposes. --- This is an automated test email from PhoenixKit Email System. Generated at: #{timestamp} """ end end