Skip to content

Commit

Permalink
Allow choice of email validation method
Browse files Browse the repository at this point in the history
Following implementation of 50d235a the
validation of email addresses was done by PHPMailer::validateAddress()
instead of filter_var() with FILTER_SANITIZE_EMAIL to allow RFC5322-
compliant emails like 'user@domain' that are rejected by PHP's method
which only accepts 'user@domain.tld'.

However, these 'top-level-domain-only' addresses are often considered as
invalid by SMTP servers but there is a strong use-case for them in
intranet environments.

To enable both scenarios, this commit introduces new constants for
$g_validate_email, allowing the admin to pick whether they want
validation using the PHP method (default) or strict RFC5322.

Backwards compatibility is maintained because EMAIL_VALIDATE_PHP == ON,
and validation can still be disabled with OFF.
  • Loading branch information
dregad committed Apr 18, 2015
1 parent 4bb1dca commit 2eebb74
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
27 changes: 25 additions & 2 deletions config_defaults_inc.php
Expand Up @@ -530,10 +530,33 @@
$g_email_receive_own = OFF;

/**
* set to OFF to disable email check
* Email addresses validation
*
* Determines if and how email addresses are validated. Possible values for
* this config are:
* - EMAIL_VALIDATE_PHP (default): validate using PHP's built-in method (see
* {@link http://php.net/filter_var} with FILTER_SANITIZE_EMAIL filter
* {@link http://php.net/filter.filters.validate}
* This should be used with internet-facing installations.
* Emails must have the form 'user@domain.tld'
* - EMAIL_VALIDATE_RFC5322: validate using an RFC5322-compliant regex
* (see {@link http://squiloople.com/2009/12/20/email-address-validation/}.
* This is useful for intranet installations, when relying on addresses
* without a top-level domain (e.g. 'user@domain')
* - EMAIL_VALIDATE_AUTO: let PHPMailer's
* {@link http://phpmailer.github.io/PHPMailer/classes/PHPMailer.html#method_validateAddress validateAddress()}
* method pick the best validation pattern. On recent systems, this is
* generally the same as EMAIL_VALIDATE_RFC5322.
* - OFF: disable email validation
*
* NOTE: Regardless of how this option is set, validation is not performed
* when using LDAP email (i.e. when $g_use_ldap_email = ON), as we assume that
* it is handled by the directory.
* @see $g_use_ldap_email
*
* @global integer $g_validate_email
*/
$g_validate_email = ON;
$g_validate_email = EMAIL_VALIDATE_PHP;

/**
* set to OFF to disable email check
Expand Down
5 changes: 5 additions & 0 deletions core/constant_inc.php
Expand Up @@ -569,6 +569,11 @@
define( 'EMAIL_SHUTDOWN_GENERATED', 1 );
define( 'EMAIL_SHUTDOWN_FORCE', 2 );

# Email address validation types
define( 'EMAIL_VALIDATE_PHP', 1 );
define( 'EMAIL_VALIDATE_AUTO', 2 );
define( 'EMAIL_VALIDATE_RFC5322', 3 );

# Lengths - NOTE: these may represent hard-coded values in db schema and should not be changed.
define( 'DB_FIELD_SIZE_USERNAME', 255 );
define( 'DB_FIELD_SIZE_REALNAME', 255 );
Expand Down
15 changes: 12 additions & 3 deletions core/email_api.php
Expand Up @@ -117,19 +117,28 @@ function email_regex_simple() {
* @return boolean
*/
function email_is_valid( $p_email ) {
$t_validate_email = config_get( 'validate_email' );

# if we don't validate then just accept
# If blank email is allowed or current user is admin, then accept blank emails which are useful for
# accounts that should never receive email notifications (e.g. anonymous account)
if( OFF == config_get( 'validate_email' ) ||
if( OFF == $t_validate_email ||
ON == config_get( 'use_ldap_email' ) ||
( is_blank( $p_email ) && ( ON == config_get( 'allow_blank_email' ) || current_user_is_administrator() ) )
) {
return true;
}

# E-mail validation method
switch( $t_validate_email ) {
case EMAIL_VALIDATE_PHP: $t_method = 'php'; break;
case EMAIL_VALIDATE_RFC5322: $t_method = 'pcre8'; break;
default: $t_method = 'auto'; break;
}

# check email address is a valid format
$t_email = filter_var( $p_email, FILTER_SANITIZE_EMAIL );
if( PHPMailer::ValidateAddress( $t_email ) ) {
if( PHPMailer::ValidateAddress( $t_email, $t_method ) ) {
$t_domain = substr( $t_email, strpos( $t_email, '@' ) + 1 );

# see if we're limited to a set of known domains
Expand Down Expand Up @@ -158,7 +167,7 @@ function email_is_valid( $p_email ) {
}
}
} else {
# Email format was valid but did't check for valid mx records
# Email format was valid but didn't check for valid mx records
return true;
}
}
Expand Down
45 changes: 44 additions & 1 deletion docbook/Admin_Guide/en-US/config/email.xml
Expand Up @@ -136,7 +136,50 @@
<varlistentry>
<term>$g_validate_email</term>
<listitem>
<para>Set to OFF to disable email checking. Default is ON.</para>
<para>Determines if and how email addresses are validated.
Possible values for this config option are:
</para>
<itemizedlist>
<listitem><para>
<literal>EMAIL_VALIDATE_PHP</literal> (default):
validate using PHP's built-in method (see
<ulink url="http://php.net/filter_var">
filter_var() function</ulink> with
<ulink url="http://php.net/filter.filters.validate">
FILTER_SANITIZE_EMAIL</ulink> filter).
This should be used with internet-facing
installations. Emails must have the form
<emphasis>user@domain.tld</emphasis>.
</para></listitem>
<listitem><para>
<literal>EMAIL_VALIDATE_RFC5322</literal>:
validate using an
<ulink url="http://squiloople.com/2009/12/20/email-address-validation/">
RFC5322-compliant regex</ulink>.
This is useful for intranet installations, when
relying addresses without a top-level domain (e.g.
<emphasis>user@domain</emphasis>).
</para></listitem>
<listitem><para>
<literal>EMAIL_VALIDATE_AUTO</literal>:
let PHPMailer's
<ulink url="http://phpmailer.github.io/PHPMailer/classes/PHPMailer.html#method_validateAddress">
validateAddress() method</ulink>
pick the best validation pattern.
On recent systems, this is generally the same as
<literal>EMAIL_VALIDATE_RFC5322</literal>.
</para></listitem>
<listitem><para>
<literal>OFF</literal>:
disable email check.
</para></listitem>
</itemizedlist>
<note><para>
Regardless of how this option is set, validation is
not performed when using LDAP email (i.e. when
$g_use_ldap_email = ON), as we assume that it is
handled by the directory.
</para></note>
</listitem>
</varlistentry>
<varlistentry>
Expand Down

0 comments on commit 2eebb74

Please sign in to comment.