diff --git a/administrator/components/com_admin/models/forms/profile.xml b/administrator/components/com_admin/models/forms/profile.xml
index 35f6fbd87a0c0..4c451639facb3 100644
--- a/administrator/components/com_admin/models/forms/profile.xml
+++ b/administrator/components/com_admin/models/forms/profile.xml
@@ -1,8 +1,8 @@
diff --git a/components/com_users/models/forms/registration.xml b/components/com_users/models/forms/registration.xml
index 8cf8c2a6bfb4e..0a648ffeef207 100644
--- a/components/com_users/models/forms/registration.xml
+++ b/components/com_users/models/forms/registration.xml
@@ -67,11 +67,11 @@
description="COM_USERS_REGISTER_EMAIL1_DESC"
field="id"
filter="string"
- message="COM_USERS_REGISTER_EMAIL1_MESSAGE"
required="true"
size="30"
unique="true"
validate="email"
+ validDomains="com_users.domains"
autocomplete="email"
/>
diff --git a/language/en-GB/en-GB.com_users.ini b/language/en-GB/en-GB.com_users.ini
index 0fed26601179c..d3d5748e9441a 100644
--- a/language/en-GB/en-GB.com_users.ini
+++ b/language/en-GB/en-GB.com_users.ini
@@ -68,6 +68,7 @@ COM_USERS_PROFILE_CUSTOM_LEGEND="Custom Profile"
COM_USERS_PROFILE_DEFAULT_LABEL="Edit Your Profile"
COM_USERS_PROFILE_EMAIL1_DESC="Enter your email address."
COM_USERS_PROFILE_EMAIL1_LABEL="Email Address"
+; The following string is deprecated and will be removed with 4.0
COM_USERS_PROFILE_EMAIL1_MESSAGE="The email address you entered is already in use or invalid. Please enter another email address."
COM_USERS_PROFILE_EMAIL2_DESC="Confirm your email address."
COM_USERS_PROFILE_EMAIL2_LABEL="Confirm Email Address"
@@ -99,6 +100,7 @@ COM_USERS_PROFILE_WELCOME="Welcome, %s"
COM_USERS_REGISTER_DEFAULT_LABEL="Create An Account"
COM_USERS_REGISTER_EMAIL1_DESC="Enter your email address."
COM_USERS_REGISTER_EMAIL1_LABEL="Email Address"
+; The following string is deprecated and will be removed with 4.0
COM_USERS_REGISTER_EMAIL1_MESSAGE="The email address you entered is already in use or invalid. Please enter another email address."
COM_USERS_REGISTER_EMAIL2_DESC="Confirm your email address."
COM_USERS_REGISTER_EMAIL2_LABEL="Confirm Email Address"
diff --git a/language/en-GB/en-GB.ini b/language/en-GB/en-GB.ini
index ed15ed340b334..461a0080927d0 100644
--- a/language/en-GB/en-GB.ini
+++ b/language/en-GB/en-GB.ini
@@ -201,6 +201,7 @@ JGLOBAL_DISPLAY_NUM="Display #"
JGLOBAL_EDIT="Edit"
JGLOBAL_EDIT_TITLE="Edit article"
JGLOBAL_EMAIL="Email"
+JGLOBAL_EMAIL_DOMAIN_NOT_ALLOWED="The email domain %s is not allowed. Please enter another email address."
JGLOBAL_EMAIL_TITLE="Email this link to a friend"
JGLOBAL_EXPAND_CATEGORIES="Show more categories"
JGLOBAL_FIELD_ADD="Add"
diff --git a/language/en-GB/en-GB.lib_joomla.ini b/language/en-GB/en-GB.lib_joomla.ini
index 6ccd43d954329..dc60b56f5da32 100644
--- a/language/en-GB/en-GB.lib_joomla.ini
+++ b/language/en-GB/en-GB.lib_joomla.ini
@@ -166,7 +166,7 @@ JLIB_DATABASE_ERROR_DATABASE_UPGRADE_FAILED="MySQL Database Upgrade failed. Plea
JLIB_DATABASE_ERROR_DELETE_CATEGORY="Left-Right data inconsistency. Can't delete category."
JLIB_DATABASE_ERROR_DELETE_FAILED="%s: :delete failed - %s"
JLIB_DATABASE_ERROR_DELETE_ROOT_CATEGORIES="Root categories can't be deleted."
-JLIB_DATABASE_ERROR_EMAIL_INUSE="This email address is already registered."
+JLIB_DATABASE_ERROR_EMAIL_INUSE="The email address you entered is already in use. Please enter another email address."
JLIB_DATABASE_ERROR_EMPTY_ROW_RETURNED="The database row is empty."
JLIB_DATABASE_ERROR_FUNCTION_FAILED="DB function failed with error number %s
%s"
JLIB_DATABASE_ERROR_GET_NEXT_ORDER_FAILED="%s: :getNextOrder failed - %s"
@@ -224,7 +224,7 @@ JLIB_DATABASE_ERROR_USERLEVEL_NAME_EXISTS="Level with the name "%s" al
JLIB_DATABASE_ERROR_USERNAME_CANNOT_CHANGE="Can't use this username."
JLIB_DATABASE_ERROR_USERNAME_INUSE="Username in use."
JLIB_DATABASE_ERROR_VALID_AZ09="Please enter a valid username. No space at beginning or end, at least %d characters and must not have the following characters: < > \ " ' % ; ( ) &."
-JLIB_DATABASE_ERROR_VALID_MAIL="Please enter a valid email address."
+JLIB_DATABASE_ERROR_VALID_MAIL="The email address you entered is invalid. Please enter another email address."
JLIB_DATABASE_ERROR_VIEWLEVEL="Viewlevel must have a title."
JLIB_DATABASE_FUNCTION_NOERROR="DB function reports no errors."
JLIB_DATABASE_QUERY_FAILED="Database query failed (error # %s): %s"
diff --git a/libraries/src/Form/Rule/EmailRule.php b/libraries/src/Form/Rule/EmailRule.php
index 7043bef0f5663..edeada5e98c8b 100644
--- a/libraries/src/Form/Rule/EmailRule.php
+++ b/libraries/src/Form/Rule/EmailRule.php
@@ -10,6 +10,7 @@
defined('JPATH_PLATFORM') or die;
+use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormRule;
use Joomla\Registry\Registry;
@@ -41,7 +42,7 @@ class EmailRule extends FormRule
* @param Registry $input An optional Registry object with the entire data set to validate against the entire form.
* @param Form $form The form object for which the field is being tested.
*
- * @return boolean True if the value is valid, false otherwise.
+ * @return mixed Boolean true if field value is valid, Exception on failure.
*
* @since 11.1
*/
@@ -75,7 +76,7 @@ public function test(\SimpleXMLElement $element, $value, $group = null, Registry
// Test the value against the regular expression.
if (!parent::test($element, $value, $group, $input, $form))
{
- return false;
+ return new \UnexpectedValueException(\JText::_('JLIB_DATABASE_ERROR_VALID_MAIL'));
}
}
else
@@ -90,7 +91,76 @@ public function test(\SimpleXMLElement $element, $value, $group = null, Registry
// Test the value against the regular expression.
if (!parent::test($element, $value, $group, $input, $form))
{
- return false;
+ return new \UnexpectedValueException(\JText::_('JLIB_DATABASE_ERROR_VALID_MAIL'));
+ }
+ }
+ }
+
+ /**
+ * validDomains value should consist of component name and the name of domain list field in component's configuration, separated by a dot.
+ * This allows different components and contexts to use different lists.
+ * If value is incomplete, com_users.domains is used as fallback.
+ */
+ $validDomains = (isset($element['validDomains']) && $element['validDomains'] != 'false');
+
+ if ($validDomains && !$multiple)
+ {
+ $config = explode('.', $element['validDomains'], 2);
+
+ if (count($config) > 1)
+ {
+ $domains = ComponentHelper::getParams($config[0])->get($config[1]);
+ }
+ else
+ {
+ $domains = ComponentHelper::getParams('com_users')->get('domains');
+ }
+
+ if ($domains)
+ {
+ $emailDomain = explode('@', $value);
+ $emailDomain = $emailDomain[1];
+ $emailParts = array_reverse(explode('.', $emailDomain));
+ $emailCount = count($emailParts);
+ $allowed = true;
+
+ foreach ($domains as $domain)
+ {
+ $domainParts = array_reverse(explode('.', $domain->name));
+ $status = 0;
+
+ // Don't run if the email has less segments than the rule.
+ if ($emailCount < count($domainParts))
+ {
+ continue;
+ }
+
+ foreach ($emailParts as $key => $emailPart)
+ {
+ if (!isset($domainParts[$key]) || $domainParts[$key] == $emailPart || $domainParts[$key] == '*')
+ {
+ $status++;
+ }
+ }
+
+ // All segments match, check whether to allow the domain or not.
+ if ($status === $emailCount)
+ {
+ if ($domain->rule == 0)
+ {
+ $allowed = false;
+ }
+ else
+ {
+ $allowed = true;
+ }
+ }
+ }
+
+ // If domain is not allowed, fail validation. Otherwise continue.
+ if (!$allowed)
+ {
+ return new \UnexpectedValueException(\JText::sprintf('JGLOBAL_EMAIL_DOMAIN_NOT_ALLOWED', $emailDomain));
}
}
}
@@ -119,7 +189,7 @@ public function test(\SimpleXMLElement $element, $value, $group = null, Registry
if ($duplicate)
{
- return false;
+ return new \UnexpectedValueException(\JText::_('JLIB_DATABASE_ERROR_EMAIL_INUSE'));
}
}