-1

To manage emails I am using the php library PHPMailer. On the client side, I validate the email address using the email method of jquery validator plugin.

$("#regForm").validate({
   rules:{
              email:
                        {
                            required: true,
                            email: true            
                        }
          }

Now, the problem is that the set of allowed characters of validator email method and the set of allowed characters on PHPMailer is not the same. For example, email method allows the '$' character but when email address contains the '$' character the send() method of Phpmailer returns false (failed sending email) and the error: 'The following recipients failed: example$@mail.it : Invalid Email address'.

I could fix the problem making a new custom method, using a done on purpose regex, to validate email addresses on client side. But what are the allowed characters for email addresses on PHPMailer send method, and where can i find them?

Ricla
  • 105
  • 1
  • 9
  • 1
    In this case the jQuery validate logic is correct - `$` (and many other symbols) are completely valid in email addresses. If you want to change this behaviour I'd suggest you write you own validation Regex. I'd also suggest contacting the authors of PHPMailer as the behaviour is pretty poor if their email validation logic does not reflect RFC standards – Rory McCrossan Feb 14 '17 at 16:53
  • 1
    For your reference, here are the valid character for email addresses: http://stackoverflow.com/questions/2049502/what-characters-are-allowed-in-email-address – Rory McCrossan Feb 14 '17 at 16:53
  • @RoryMcCrossan I know what are the valid characters for email addresses, but phpmailer send method doesn't allow all of them. So i need to know what are the allowed characters for phpmailer? i need this info to build a custom regex. – Ricla Feb 14 '17 at 16:57
  • It's not PHPMailer (which knows quite well what's valid, thank you very much) - it's the receiving server. – Synchro Feb 14 '17 at 17:10

2 Answers2

1

Per the documentation on PHPMailer, you can setup your own validation (they already offer several). The Docblock states:

/**
 * Check that a string looks like an email address.
 * @param string $address The email address to check
 * @param string|callable $patternselect A selector for the validation pattern to use :
 * * `auto` Pick best pattern automatically;
 * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
 * * `pcre` Use old PCRE implementation;
 * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
 * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
 * * `noregex` Don't use a regex: super fast, really dumb.
 * Alternatively you may pass in a callable to inject your own validator, for example:
 * PHPMailer::validateAddress('user@example.com', function($address) {
 *     return (strpos($address, '@') !== false);
 * });
 * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
 * @return boolean
 * @static
 * @access public
 */

$phpmailer->send() automatically invokes the validateAddress method via the preSend method. You can set the validation method via (untested):

$phpMailer->validator = function($email) { return true; };

Alternatively, you can override the method by creating your own phpmailer class, such as:

class myMailer extends PHPMailer {
  public static function validateAddress($address) {
    return true;
  }
} 

Side note, I typically just use filter_var: filter_var($email, FILTER_VALIDATE_EMAIL)

Rob W
  • 9,134
  • 1
  • 30
  • 50
1

You're jumping to conclusions. PHPMailer's validator (which is very thoroughly tested) considers that address valid.

The error you're getting is from the receiving mail server, not PHPMailer.

PHPMailer will reject addresses at the point you add them (e.g. using addAddress()) - and invalid addresses will never make it as far as sending. As an example, PHPMailer is happy to consider this address valid:

user+!#$%&'*-/=?+_{}|~test@example.com

PHPMailer's default address pattern in PHPMailer 5.6:

/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD

This is a pretty thorough validation (and is thus quite permissive) that allows many things that many other validators do not, such as IP literals.

PHPMailer 6.0 retains this pattern, but defaults to the more limited PHP built-in validator in filter_var with the FILTER_VALIDATE_EMAIL option - and the pattern used in that was originally written by the same author as the one in PHPMailer.

There is much discussion about validating for RFC822, however, that's usually irrelevant; RFC822 does NOT define valid email addresses to send to; that is defined in RFC821 (SMTP), which is a smaller subset. This is a valid RFC822 address, but it's not a valid RFC821 address, and so can't actually be sent to:

(foo)cal(bar)@(baz)example.com(queue)

There are also other non-RFC factors - ICANN banned 'dotless' domains, so addresses such as a@b (which are valid in 821 and 822) should be considered invalid.

The WHATWG HTML5 spec includes a simplified subset of addresses (a wilful violation of RFC5322) for the email input element, using this pattern, which I wrote:

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

This validator is also available in PHPMailer.

As the function comment block for the validateAddress function says (thank you @Half Crazed for mentioning it), if you don't like these, you can dynamically inject your own - though I really wouldn't bother!

Synchro
  • 35,538
  • 15
  • 81
  • 104