5

I am working with SYmfony 1.4 and swift mailer to send a bulk array of emails through Sendgrid.

I am getting an RFC compliance error on some of the email addresses.

One solution would be to remove the condition to throw the error, and it does work, but it involves changing the core. How would you extend MailboxHeader.php in the site files and not the symfony core. Something like this, but not this because it doesn't work:

class overrideRFCError extends Swift_Mime_Headers_AbstractHeader
{
    private function _assertValidAddress($address)
    {
        if (!preg_match('/^' . $this->getGrammar('addr-spec') . '$/D',
          $address))
        {
          // throw new Swift_RfcComplianceException(
          //   'Address in mailbox given [' . $address .
          //   '] does not comply with RFC 2822, 3.6.2.'
          //   );
        }
    }
}

This also seems a little heavy handed. Is there a way to validate the email for RFC compliance. If so, I could then just unset it from the array.

UPDATE 07/17/13

I was able to put a thorough cleaning on each address to make it RFC compliant, which solves the problem. However, I would like to know if a function exists in the SwiftMailer that does this check, rather then writing a custom function.

UPDATE 07/18/13

Here is what I got to work. I tried to sanitize the entries as much as possible.

Load an array of addresses in a variable called $emailList

in actions:

$cleanList = sendGridEmailer::validateEmails($emailList);

in sendGridEmailer class:

// loop and validate each email address
    public static function validateEmails($emailList) {
        foreach($emailList as $address => $name) {
            try {
                $v = new sfValidatorEmail();
                $email = $v->clean($address);

            } catch (sfValidatorError $e) {
                unset($emailList[$address]);
            }
        }
        foreach($emailList as $address => $name) {
            $rfcTesting = validateEmailForRFC::is_email($address);
            if(!$rfcTesting) {
                unset($emailList[$address]);
            }
            if (!preg_match('/^[a-zA-Z0-9_.-@]/', $address)) {
                unset($emailList[$address]);
            }
        }
        // List should be clean
        return $emailList;
    }

So this first uses the sfValidator to kick out the initial bad addresses. Next, I got a RFC compliance script here and execute that in the validateEmailForRFC class which should make them RFC Compliant.

Last, I do a final pregmatch for any stragglers with weird chars that the previous checks did not catch.

This allowed me to keep the Symfony core untouched and prepped the addresses for Swift with no Compliance errors.

Carey Estes
  • 1,534
  • 2
  • 31
  • 59
  • Do you have any details on the addresses that raise the error? Avoiding the error by overriding may be a workaround but not a solution. – Sven Schneider Jul 16 '13 at 16:24
  • Actually, there is quite no chance to avoid this. The check for wrong addresses complies to RFC though providers may accept this. Checking rules are hardcoded in Swift. Change the core, don't throw the error but write to a log file the address. So you can check if the address is wrong or it is just the strict checking. – Sven Schneider Jul 16 '13 at 16:35
  • I would rather not remove the error check. I would think there is a SwiftMailer function that would check RFC validation. Does this exist? – Carey Estes Jul 16 '13 at 16:38
  • The problem is the internal checking of SwiftMailer. You don't have parameters to turn this checking on/off. Many people are having this issue, SwiftMailer team says they know about it, but strict checking is better and more reliable than any weak checking. So only workarounds will work. – Sven Schneider Jul 17 '13 at 12:00
  • Nice solution but I think I don't get your problem then. This is more from a product view rather than a programmer's view. If you have mail addresses in a database you want to send mails to, those typically are user addresses. Users entered them somewhere on your site. Either at this point the check should happen or latest at the opt-in of the user. Wrong email address -> no opt-in mail -> no junk in the database. But I like your solution, have to keep that in mind. – Sven Schneider Jul 17 '13 at 19:59
  • @Sven In a perfect world, you are correct. the user would be uploading a valid email and there would be a validation process at the submission level. However, there are also clever little robots that work diligently at breaking the submission validation. We also are pulling from a db that is a collection that has accumulated throughout ~10 yrs. My secondary solution was to create a cron which will check & delete all invalid marked addresses. – Carey Estes Jul 18 '13 at 14:20

1 Answers1

5

You can use symfony's sfValidatorEmail or the filter-var function. They work good enough with SwiftMailer, but neither of them are RFC compliant IIRC. For validating against RFCs you can use https://github.com/egulias/EmailValidator or https://github.com/dominicsayers/isemail.

1ed
  • 3,668
  • 15
  • 25
  • The problem is not "no validation is done". The SwiftMailer built in checking is RFC compliant and this is too strict for a lot of mail providers out there who allow less strict addresses (local part of an email address) – Sven Schneider Jul 17 '13 at 12:02
  • Because `SwiftMailer` checks email addresses before sending an email and throws an exception if it's invalid so you should validate emails before inserting them into the database or before sending an email. When sending to one recipient only you can use `try ... catch` but for bulk sending it's not so good. – 1ed Jul 17 '13 at 15:31
  • IIRC `SwiftMailer's` check is actually stricter than RFCs e.g. http://isemail.info/root%40localhost fails in `SwiftMailer` IIRC... and thats can be a problem, for user with exotic email addresses, but in general it's OK. – 1ed Jul 17 '13 at 15:40