From 7f6fd012a5825ce2d4a82545dde31e3a794ccf08 Mon Sep 17 00:00:00 2001 From: jamey Date: Sat, 28 Feb 2026 23:52:11 +0000 Subject: [PATCH] add send test email button to campaign form Sends the campaign to the admin's own email address as a preview, with [Test] prefix in subject line. Uses the same HTML template and formatting as real sends. Does not affect campaign status or sent counts. Co-Authored-By: Claude Opus 4.6 --- lib/berrypod/newsletter/notifier.ex | 21 +++++++++++++ .../live/admin/newsletter/campaign_form.ex | 31 +++++++++++++++++++ test/berrypod/newsletter/notifier_test.exs | 15 +++++++++ 3 files changed, 67 insertions(+) diff --git a/lib/berrypod/newsletter/notifier.ex b/lib/berrypod/newsletter/notifier.ex index 3a82229..f8ec066 100644 --- a/lib/berrypod/newsletter/notifier.ex +++ b/lib/berrypod/newsletter/notifier.ex @@ -42,6 +42,27 @@ defmodule Berrypod.Newsletter.Notifier do deliver(subscriber.email, "Confirm your subscription", text, html) end + @doc "Sends a test/preview email of a campaign to the given address." + def deliver_test(campaign, to_email) do + shop_name = Berrypod.Settings.get_setting("shop_name", "Berrypod") + sample_unsub = BerrypodWeb.Endpoint.url() <> "/unsubscribe/test-preview" + + body_with_url = + String.replace(campaign.body, "{{unsubscribe_url}}", sample_unsub) + + text = """ + [TEST] #{body_with_url} + + --- + This is a test email. No subscribers received this. + """ + + html_content = text_to_html(body_with_url, sample_unsub) + html = wrap_html(shop_name, html_content, sample_unsub) + + deliver(to_email, "[Test] #{campaign.subject}", text, html) + end + @doc "Sends a campaign email to a single subscriber." def deliver_campaign(campaign, subscriber) do shop_name = Berrypod.Settings.get_setting("shop_name", "Berrypod") diff --git a/lib/berrypod_web/live/admin/newsletter/campaign_form.ex b/lib/berrypod_web/live/admin/newsletter/campaign_form.ex index 28ad949..2057c12 100644 --- a/lib/berrypod_web/live/admin/newsletter/campaign_form.ex +++ b/lib/berrypod_web/live/admin/newsletter/campaign_form.ex @@ -74,6 +74,29 @@ defmodule BerrypodWeb.Admin.Newsletter.CampaignForm do end end + def handle_event("send_test", _params, socket) do + params = current_form_params(socket) + to_email = socket.assigns.current_scope.user.email + + if params["subject"] == "" || params["body"] == "" do + {:noreply, put_flash(socket, :error, "Fill in subject and body first")} + else + # Build a temporary campaign struct for the notifier + campaign = %Newsletter.Campaign{ + subject: params["subject"], + body: params["body"] + } + + case Newsletter.Notifier.deliver_test(campaign, to_email) do + {:ok, _} -> + {:noreply, put_flash(socket, :info, "Test email sent to #{to_email}")} + + {:error, _} -> + {:noreply, put_flash(socket, :error, "Failed to send test email")} + end + end + end + def handle_event("schedule", _params, socket) do params = current_form_params(socket) scheduled_at = parse_schedule_time(params["scheduled_at"]) @@ -184,6 +207,14 @@ defmodule BerrypodWeb.Admin.Newsletter.CampaignForm do Save draft + +