Contao 3: Newsletter-Abo mit Sicherheitsabfrage (Captcha)

(Kommentare: 6)

Das Newsletter-Abonnement kann z.B. von Spam bots missbraucht werden und so können sich viele unbrauchbare Einträge in der Abonnenten-Liste in der Datenbank sammeln. Wenn die Email-Einträge echt sind, bekommen dann ggf. viele Menschen eine Email mit der Behauptung, Sie hätten den Newsletter abonniert.
Offenbar erst in Contao 4 wird die Newsletter-Bestellung (subcribe und unsubscribe) mit einer Captcha-Sicherheitsabfrage (optional) geschützt.

Newseltter bestellen mit Sicherheitsabfrage (Captcha) in einem bestehenden Contao-3-Projekt:

Annahme: Es gibt bereits ein eigenes "Projekt-Modul" TL_ROOT/system/modules/x_project/. Wenn nicht, siehe unten. Auch wichtig: das eigene "Projekt-Modul" muss einen Namen haben, der im Alphabet nach "newsletter" kommt, siehe unten.


Neue bzw. zu ändernde Dateien:

TL_ROOT/system/modules/x_project/config/config.php

<?php
// ... 
$GLOBALS['FE_MOD']['newsletter']['subscribe'] = 'ModuleSubscribeSecure'; $GLOBALS['FE_MOD']['newsletter']['unsubscribe'] = 'ModuleUnsubscribeSecure'; // ...



TL_ROOT/system/modules/x_project/modules/ModuleSubscribeSecure.php

<?php
/** Extension of ModuleSubscribe to add security question (captcha) to newsletter subscribe form, Contao 3.
  *
  * @author Ingmar Decker
  */
class ModuleSubscribeSecure extends \ModuleSubscribe
{
	protected $objCaptcha;
	
	protected function compile()
	{
		$this->objCaptcha = new FormCaptcha(array('id'=> 'captcha_'.$this->id, 'label' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'], 'placeholder' => $GLOBALS['TL_LANG']['MSC']['securityQuestion']));
		
		parent::compile();
		
		$this->Template->captcha = $this->objCaptcha->parse();

	}
	
	protected function addRecipient()
	{
		$this->objCaptcha->validate();
		
		if ($this->objCaptcha->hasErrors())
		{
			$_SESSION['SUBSCRIBE_ERROR'] = $this->objCaptcha->getErrorsAsString();
			$this->reload();
		}
		
		parent::addRecipient();
	}
	
}



TL_ROOT/system/modules/x_project/modules/ModuleUnsubscribeSecure.php

<?php
/** Extension of ModuleUnsubscribe to add security question (captcha) to newsletter subscribe form, Contao 3.
  *
  * @author Ingmar Decker
  */
class ModuleUnsubscribeSecure extends \ModuleUnsubscribe
{
	protected $objCaptcha;
	
	protected function compile()
	{
		$this->objCaptcha = new FormCaptcha(array('id'=> 'captcha_'.$this->id, 'label' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'], 'placeholder' => $GLOBALS['TL_LANG']['MSC']['securityQuestion']));
		
		parent::compile();
		
		$this->Template->captcha = $this->objCaptcha->parse();;
	}
	
	protected function removeRecipient()
	{
		$this->objCaptcha->validate();
		
		if ($this->objCaptcha->hasErrors())
		{
			$_SESSION['UNSUBSCRIBE_ERROR'] = $this->objCaptcha->getErrorsAsString();
			$this->reload();
		}
		
		parent::removeRecipient();
	}
	
}



TL_ROOT/templates/nl_default.html5 (Kopie des Originals aus TL_ROOT/system/modules/newsletter/templates/newsletter/)

	// code after email input field
	<?php if ($this->captcha): ?>
		<?php echo $this->captcha ?>
	<?php endif ?>



 

 

Falls das Contao-Modul / Extension komplett neu aufgesetzt werden muss: Verzeichnisse erstellen:
TL_ROOT/system/modules/x_project/
TL_ROOT/system/modules/x_project/config/
TL_ROOT/system/modules/x_project/modules/

 

Hinweis: Die eigene Extension (also das Verzeichnis, hier "x_project") muss einen Namen > "newsletter" haben, damit es nach der Standard-Newsletter-Extension geladen wird. Ansonsten gibt es Probleme, weil in der Config für FE_MOD 'subscribe" ein Array steht und nicht der gewollte Name 'ModuleSubscribe'.

 

Dateien:

TL_ROOT/system/modules/x_project/config/autoload.ini

register_namespaces = true
register_classes    = true
register_templates  = true



TL_ROOT/system/modules/x_project/config/autoload.php

<?php
$namespace = '';
$module = basename(dirname(dirname(__FILE__)));

/** Register the classes */
foreach (array('classes', 'elements', 'models', 'modules', 'widgets', 'forms') as $d) {
	$dir = TL_ROOT . "/system/modules/$module/$d";
	if (file_exists($dir) && is_dir($dir)) {
		foreach (scandir($dir) as $f) {
			if (!preg_match('/.php$/', $f)) continue;
			$pathinfo = pathinfo($f);
			if ($namespace) {
				ClassLoader::addClasses(array
				(
					$namespace . '\\' . $pathinfo['filename'] => "system/modules/$module/$d/$f"
				));
			} else {
				ClassLoader::addClasses(array
				(
					$pathinfo['filename'] => "system/modules/$module/$d/$f"
				));
			}
		}
	}
}

/** Register the templates */
$dir = TL_ROOT . "/system/modules/$module/templates";
if (file_exists($dir) && is_dir($dir)) {
	foreach (scandir($dir) as $f) {
		if (!preg_match('/.html5$/', $f) && !preg_match('/.tpl$/', $f)) continue;
		$pathinfo = pathinfo($f);
		TemplateLoader::addFiles(array
		(
			$pathinfo['filename'] => "system/modules/$module/templates"
		));
	}
}

TL_ROOT/system/modules/x_project/config/config.php

Siehe ganz oben.

Die o.g. Module-PHP-Dateien natürlich in TL_ROOT/system/modules/x_project/modules/ legen.

 

 

Ergänzung 5.3.2020: nach Feedback durch Emails und Kommentare: ggf. unter Einstellungen "den internen Cache umgehen" anhaken. (Vorher ggf. mal versuchen, via Systemwartung den Seitencache und den internen Cache zu leeren.)

Ergänzung 22.5.2020: im Text Ergänzungen zur Benennung der "Extension" (alphabetisch nach "newsletter").

 

 

Zurück

Kommentare

Kommentar von Gerd |

Hatte leider tatsächlich das Problem von tausenden Fake-Newsletteranmeldungen und habe jetzt dieses Modul ausprobiert (Contao 3.0.1).

Newsletter-Anmeldung (Formular) funktioniert einwandfrei mit Captcha, die Abmeldung jedoch leider überhaupt nicht...

Wäre dankbar für jeden Tipp!

Kommentar von Gerd |

Sorry - war ein Fehler meinerseits!

Deshalb:
Vielen Dank für diese Lösung!

Kommentar von Raffa |

Habe das Captcha eingebunden und seit dem auch keine Fake-E-Mail-Adressen mehr im Verteiler.
Vielen Dank noch mal -->funktioniert einwandfrei.

Unter Contao 3.5.2 funktioniert des Captcha sowohl beim An- als auch beim Abmelden.
Habe mir unter Contao 3.5.30 eine Testumgebung eingerichtet und dort ebenfalls dass Captcha eingebunden.
***
Hier musste ich allerdings den internen Cache umgehen, da mir sonst das ganze Abonnieren-Modul im FE nicht angezeigt wurde. Einfach im Contao Backend unter "System>>Einstellungen>>Globale Einstellungen>>Internen Cache umgehen" ein Häkchen setzen.
Funktioniert also auch mit der momentan aktuellsten 3.5 Contao-Version.

Super Lösung und besten Dank

Grüße
Raffa

Antwort von webdecker

Danke für die Hinweise!

Im übrigen macht u.U. auch noch Sinn, das Captcha mit tableless = 1 zu versorgen, so dass das Widget (ich ändere das nl_default-Template in der Regel auch immer so, dass das HTML dem der sonstigen Formularfelder (siehe Template form_row) entspricht).

 

    $this->objCaptcha = new FormCaptcha(array('id'=> 'captcha_'.$this->id, 'label' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'], 'placeholder' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'], 'tableless' => 1));

 

Kommentar von Dee |

Super Sache, war ne Weile am tüfteln bis ich diesen Beitrag gefunden habe. Hat mit Contao 3.5.40 wunderbar funktioniert.

Antwort von webdecker

Freut mich! Contao 4 hat ja'n Captcha drin, aber falls das mit der Datenschutz-Checkbox interessant ist, siehe Artikel contao-4-4-newsletter-abo-mit-datenschutz-abfrage.html.

Kommentar von chris |

Hallo. Habe diesen Post hier gefunden und wollte es für Contao 3.5.40 implementieren. Geht aber irgendwie nicht.
Interner Cache wird umgangen und Caches sind gelöscht.

Hier meine Ausgabe:
https://www.shaba-baden.ch/newsletter.html

Danke für Tips und Anregungen.
Chris.

Antwort von webdecker

Text oben ergänzt. Das eigene Modul-Verzeichnis muss einen Namen bekommen, der alphabetisch nach "newsletter" kommt, sonst wird "unsere" Konfiguration durch die Newsletter-Extension-Konfiguration überschrieben bzw. ungünstig gemergt.

Kommentar von Cyprian |

Wäre es möglich, sich irgendwie in das Rocksolid-Antispam - Modul zu integrieren?

Antwort von webdecker

Das kenne ich leider nicht... Da kann ich nichts zu sagen... :(

Einen Kommentar schreiben


Bitte geben Sie den Code ein, den Sie im Bild sehen.