Plugin to check for existant, non-suspended email addresses during contact form submission

Do you have an Open Source Product available for Joomla!? Let everyone know here.
Post Reply
jamesfu
Joomla! Fledgling
Joomla! Fledgling
Posts: 1
Joined: Tue Mar 01, 2016 9:30 am

Plugin to check for existant, non-suspended email addresses during contact form submission

Post by jamesfu » Fri May 06, 2022 6:27 am

TLDR
I got tired of spam messages from eric.jones.z.mail@gmail.com and wrote a plugin to check that a sender's email address exists and is actually accepting messages before allowing the form submission, but it currently requires a slight core modification to work. (This is also why I'm breaking the rule about listing on Joomla! Extensions Directory first.) With your help, I hope to get the core changes included in Joomla! 4.2 so the plugin can be fully functional out of the box and share it on JED.

How it works
Joomla! 3 & 4 come with PHPMailer included. This lightweight plugin first checks if the target domain has valid SMTP server(s) configured then makes use of PHPMailer's SMTP class to step though the process of sending a message to verify that the target SMTP server is accepting messages to the target mailbox (i.e. isn't suspended, full, etc). It aborts upon confirming whether messages are being accepted without actually sending anything.

What isn't working
In Joomla! 3 & 4, the com_contact component has in-built server-side validation. This is to block invalid (and malicious) input from slipping through client-side validation. When it flags something, the visitor is returned to the contact form, with the previously entered information prefilled and a message explaining why the submission was unsuccessful.

In Joomla! 3 & 4, plugins may listen for the "onValidateContact" event, and perform additional, custom validation such as captcha. Documentation states that the function should return nothing on successful validation, and an exception on failure. However, for failing submissions, users are currently returned to the contact form URL, with none of the contact form components or any message explaining the failure. The user might even think the submission was successful.

How it currently looks:
Image

How it should look:
Image

The quick and dirty fix
By changing a few lines in Joomla! core, we can make com_contact handle plugins that reject a submission the same way native server-side validation is handled (i.e. redirect to prefilled contact form with message explaining why submission was rejected).

Via command-line
If you have access to the command-line, you can download a patch and apply it with git:

Joomla! 3

Code: Select all

cd <joomla installation root>
wget https://github.com/joomla/joomla-cms/commit/6132f7a898b92a295ea3c336ce6d141d5c98a2ca.patch
git apply 6132f7a898b92a295ea3c336ce6d141d5c98a2ca.patch

# to uninstall
git apply -R 6132f7a898b92a295ea3c336ce6d141d5c98a2ca.patch
Joomla! 4

Code: Select all

cd <joomla installation root>
wget https://patch-diff.githubusercontent.com/raw/joomla/joomla-cms/pull/37540.patch
git apply 37540.patch

# to uninstall
git apply -R 37540.patch
OR

By hand

Joomla! 3
Navigate to "components/com_contact/controllers/contact.php" in your preferred text editor, and replace the code from lines 142 - 148 (the "foreach" loop) with:

Code: Select all

		$passValidation = true;

		foreach ($results as $result)
		{
			if ($result instanceof Exception)
			{
				$passValidation = false;
				$app->enqueueMessage($result->getMessage(), 'error');
			}
		}

		if (!$passValidation)
		{
			$app->setUserState('com_contact.contact.data', $data);

			$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contact&id=' . $id . '&catid=' . $contact->catid, false));

			return false;
		}
Joomla! 4
Navigate to "components/com_contact/src/Controller/ContactController.php" in your preferred text editor, and replace the code from lines 182 - 188 (the "foreach" loop) with:

Code: Select all

		$passValidation = true;

		foreach ($results as $result)
		{
			if ($result instanceof \Exception)
			{
				$passValidation = false;
				$app->enqueueMessage($result->getMessage(), 'error');
			}
		}

		if (!$passValidation)
		{
			$app->setUserState('com_contact.contact.data', $data);

			$this->setRedirect(Route::_('index.php?option=com_contact&view=contact&id=' . $id . '&catid=' . $contact->catid, false));

			return false;
		}
The Email Validator Plugin
You can download the plugin here (click the "Download" button, top left of page). Install it like any other extension, and after enabling, you should be good to go. Here are some example email addresses that should be blocked:
  • user@notarealdomain (Malformed domain name)
  • user@notanexistingdomain.com (Non-existing domain name)
  • thisisnotanexistinguser@gmail.com (Non-existent mailbox)
  • eric.jones.z.mail@gmail.com (Mailbox not in good standing)
Options
The default plugin parameters are pretty reasonable and should be good to go out of the box. For those hoping to fine-tune its behaviour:
  • 'From' Address: By default, the sender address used for opening the SMTP session is the system email address. Change this if you wish to use something else.
  • Use 'A' Record: If no 'MX' records are configured for the target email domain, try opening an SMTP session to its domain name.
  • Debug to system log: Whether to log debug messages.
  • Allow if unable to connect: Whether to validate email address as passed if unable to connect to any SMTP server.
  • Connect Timeout (seconds): The timeout in seconds when attempting to connect to each SMTP server. Caution: If a domain has 5 MX records configured and none of them are online, a timeout of 60 seconds would mean the script gets tied up for 5 minutes and a user will be waiting that long for an error message.
  • Allow if domain rejected: Whether to validate email address if error encountered on the "HELO/EHLO" command.
  • Allow if email address rejected: Whether to validate email address if error encountered on the "MAIL FROM" command.
  • Allow on status code XXX: Whether to validate email address if error encountered on the "RCPT TO" command. This wikipedia page provides detailed explanation of each of the status codes.
  • Currently, exception messages shown to users are only customisable from the language file (<joomla installation root>/administrator/language/en-GB/plg_contact_validation.ini), final section, under "; Exception Messages (shown on public site)". If there is interest, we could make the messages customisable from plugin configuration in a later release.
Fixing Joomla! Core
I have made a pull request to allow com_contact to show exception messages like native server-side validation. It has passed maintainer checks and just needs 2 passing human tests to be merged into Joomla! 4.2. If you have a GitHub account and tested the quick and dirty fix above to be working, it would be a great help if you could go to the issue tracker, login, and click the blue "Test this" button near the top of the page and report your result. With your help, this and other plugins that listen for the "onValidateContact" event will be able to display exception messages without core modifications from Joomla! 4.2. Unfortunately, this was classified as an enhancement and not a bug fix, so Joomla! 3 will not accept this pull request. If you are still on Joomla! 3, please use the quick and dirty fix above, and you may need to patch 'contact.php' again if it is overwritten in a later security release (somewhat unlikely).

Finally
Thank you for reading my novel, and thank you if you tried testing my pull request and reported your results on Joomla! Issue Tracker. As this forum does not allow replies, my PM is open if you have questions or need help getting things working.

Post Reply

Return to “Open Source Products for Joomla!”