From bb4e968a25d136caf55cf49d6370700d8c3b3770 Mon Sep 17 00:00:00 2001 From: Roman Pyrih Date: Fri, 30 Jan 2026 15:13:05 +0100 Subject: [PATCH] Fix Newsletter unsubscribe box --- .../controllers/front/subscription.php | 16 ++++ .../mails/pl/newsletter_conf.html | 37 ++++++++- .../mails/pl/newsletter_verif.html | 35 +++++++- .../mails/pl/newsletter_voucher.html | 7 +- .../mails/pl/newsletter_voucher.txt | 1 + .../ps_emailsubscription.php | 79 ++++++++++++++++++- 6 files changed, 166 insertions(+), 9 deletions(-) diff --git a/modules/ps_emailsubscription/controllers/front/subscription.php b/modules/ps_emailsubscription/controllers/front/subscription.php index f92ea06a..aee1051e 100644 --- a/modules/ps_emailsubscription/controllers/front/subscription.php +++ b/modules/ps_emailsubscription/controllers/front/subscription.php @@ -38,6 +38,22 @@ class Ps_EmailsubscriptionSubscriptionModuleFrontController extends ModuleFrontC */ public function postProcess() { + // One-click unsubscribe via email link + if (Tools::getValue('unsubscribe')) { + $email = Tools::getValue('email', ''); + $token = Tools::getValue('token', ''); + + $msg = $this->module->unsubscribeByLink($email, $token); + + // показати повідомлення на сторінці + $this->variables['value'] = $email; + $this->variables['msg'] = $msg; + $this->variables['nw_error'] = false; + + // можна одразу рендерити template як і зараз + return; + } + $this->variables['value'] = Tools::getValue('email', ''); $this->variables['msg'] = ''; $this->variables['conditions'] = Configuration::get('NW_CONDITIONS', $this->context->language->id); diff --git a/modules/ps_emailsubscription/mails/pl/newsletter_conf.html b/modules/ps_emailsubscription/mails/pl/newsletter_conf.html index 08aa5c78..b5b52655 100644 --- a/modules/ps_emailsubscription/mails/pl/newsletter_conf.html +++ b/modules/ps_emailsubscription/mails/pl/newsletter_conf.html @@ -305,9 +305,40 @@ - - - +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + +
+
+ Nie chcemy zakłócać Twojego spokoju ????
+ Jeśli wolisz, by nasze wiadomości Cię nie budziły, Wypisz mnie +
+
+
+
+ +
+
diff --git a/modules/ps_emailsubscription/mails/pl/newsletter_verif.html b/modules/ps_emailsubscription/mails/pl/newsletter_verif.html index 8b0d5610..b819bd5e 100644 --- a/modules/ps_emailsubscription/mails/pl/newsletter_verif.html +++ b/modules/ps_emailsubscription/mails/pl/newsletter_verif.html @@ -308,7 +308,40 @@ - +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + +
+
+ Nie chcemy zakłócać Twojego spokoju ????
+ Jeśli wolisz, by nasze wiadomości Cię nie budziły, Wypisz mnie +
+
+
+
+ +
+
diff --git a/modules/ps_emailsubscription/mails/pl/newsletter_voucher.html b/modules/ps_emailsubscription/mails/pl/newsletter_voucher.html index 8ec4ad6c..829ebc60 100644 --- a/modules/ps_emailsubscription/mails/pl/newsletter_voucher.html +++ b/modules/ps_emailsubscription/mails/pl/newsletter_voucher.html @@ -296,7 +296,12 @@ Teraz będziesz na bieżąco z najlepszymi ofertami, nowościami i inspiracjami dotyczącymi aranżacji wnętrz.

🎁 Oto Twój kod rabatowy na pierwsze zakupy: {discount}

Wykorzystaj go na Masimmo.pl i stwórz wnętrze swoich marzeń już dziś! - + +
+
+ Nie chcemy zakłócać Twojego spokoju ????
+ Jeśli wolisz, by nasze wiadomości Cię nie budziły, Wypisz mnie +
diff --git a/modules/ps_emailsubscription/mails/pl/newsletter_voucher.txt b/modules/ps_emailsubscription/mails/pl/newsletter_voucher.txt index 4de5292b..47a42791 100644 --- a/modules/ps_emailsubscription/mails/pl/newsletter_voucher.txt +++ b/modules/ps_emailsubscription/mails/pl/newsletter_voucher.txt @@ -7,6 +7,7 @@ Witaj, Zapisz się do newslettera Dziękujemy za subskrypcję naszego newslettera. Z przyjemnością oferujemy następujący kupon: {discount} +Aby wypisać się z newslettera, kliknij tutaj:{unsubscribe_url} [{shop_name}]({shop_url}) diff --git a/modules/ps_emailsubscription/ps_emailsubscription.php b/modules/ps_emailsubscription/ps_emailsubscription.php index 18c9147d..f6e172d0 100644 --- a/modules/ps_emailsubscription/ps_emailsubscription.php +++ b/modules/ps_emailsubscription/ps_emailsubscription.php @@ -577,15 +577,26 @@ class Ps_Emailsubscription extends Module implements WidgetInterface return false; } - protected function unregister($email, $register_status) + function unregister($email, $register_status) { + $email = pSQL((string) $email); + if ($register_status == self::GUEST_REGISTERED) { - $sql = 'DELETE FROM ' . _DB_PREFIX_ . 'emailsubscription WHERE `email` = \'' . pSQL($_POST['email']) . '\' AND id_shop = ' . $this->context->shop->id; + $sql = 'DELETE FROM ' . _DB_PREFIX_ . 'emailsubscription + WHERE `email` = \'' . $email . '\' + AND id_shop = ' . (int) $this->context->shop->id; } elseif ($register_status == self::CUSTOMER_REGISTERED) { - $sql = 'UPDATE ' . _DB_PREFIX_ . 'customer SET `newsletter` = 0 WHERE `email` = \'' . pSQL($_POST['email']) . '\' AND id_shop = ' . $this->context->shop->id; + $sql = 'UPDATE ' . _DB_PREFIX_ . 'customer + SET `newsletter` = 0, + `newsletter_date_add` = NULL, + `ip_registration_newsletter` = NULL + WHERE `email` = \'' . $email . '\' + AND id_shop = ' . (int) $this->context->shop->id; + } else { + return false; } - if (!isset($sql) || !Db::getInstance()->execute($sql)) { + if (!Db::getInstance()->execute($sql)) { return false; } @@ -710,6 +721,65 @@ class Ps_Emailsubscription extends Module implements WidgetInterface return ''; } + /** + * One-click unsubscribe token (independent from date_add/newsletter_date_add). + */ + protected function getUnsubscribeToken($email) + { + // stable secret based on shop config + $salt = (string) Configuration::get('NW_SALT'); + $rand = (string) Configuration::get('PS_NEWSLETTER_RAND'); + + return md5(strtolower(trim($email)) . '|' . $salt . '|' . $rand); + } + + /** + * Builds unsubscribe URL for emails. + */ + public function getUnsubscribeUrl($email) + { + $token = $this->getUnsubscribeToken($email); + + return $this->context->link->getModuleLink( + 'ps_emailsubscription', + 'subscription', + [ + 'unsubscribe' => 1, + 'email' => $email, + 'token' => $token, + ], + true + ); + } + + /** + * Unsubscribe by email+token (used by one-click link). + */ + public function unsubscribeByLink($email, $token) + { + $email = trim((string) $email); + $token = (string) $token; + + if (!Validate::isEmail($email)) { + return $this->trans('Invalid email address.', [], 'Shop.Notifications.Error'); + } + + if ($token !== $this->getUnsubscribeToken($email)) { + return $this->trans('This link is invalid or expired.', [], 'Shop.Notifications.Error'); + } + + $register_status = $this->isNewsletterRegistered($email); + if ($register_status < 1) { + return $this->trans('This email address is not registered.', [], 'Modules.Emailsubscription.Shop'); + } + + if (!$this->unregister($email, $register_status)) { + return $this->trans('An error occurred while attempting to unsubscribe.', [], 'Modules.Emailsubscription.Shop'); + } + + return $this->trans('Unsubscription successful.', [], 'Modules.Emailsubscription.Shop'); + } + /** * Ends the registration process to the newsletter. * @@ -796,6 +866,7 @@ class Ps_Emailsubscription extends Module implements WidgetInterface ), [ '{discount}' => $code, + '{unsubscribe_url}' => $this->getUnsubscribeUrl($email), ], $email, null,