ColdFusion Email Validation, IsValid(), And CFMail Errors

Posted September 12, 2006 at 2:36 PM

Tags: ColdFusion

Who here hasn't had to validate an email address format at some point? Heck, I do that in practically every application that I build. And why do I do it? The truth is, I don't really care if people mess up entering their own email address. I mean sure, I validate that. But really, my main concern is NOT having the ColdFusion page request crap out. If you attempt to send a CFMail tag with a bad email address format, it will throw an error.

Sometimes, my email validation is not perfect and I end up not allowing some emails that are actually valid. This got me thinking - what is a valid email address? Or rather, what does ColdFusion think a valid email address is? There are two ways to look at this:

  1. What will pass an IsValid() method call?
  2. What will let a CFMail tag execute successfully?

To test this, I set up an array of emails and then tried sending emails out. In the example below, you will notice that I use ".ben" in the email extension a lot. That is because I don't actually want to send emails to valid addresses. I just want to test to see if they send action works (yes, I did get several hundred undeliverable emails).

 Launch code in new window » Download code as text file »

  • <!--- Set up emails to test format. --->
  • <cfset arrEmails = ArrayNew( 1 ) />
  •  
  • <!--- Add emails that we know are totally bunk. --->
  • <cfset ArrayAppend( arrEmails, "" ) />
  • <cfset ArrayAppend( arrEmails, "1" ) />
  • <cfset ArrayAppend( arrEmails, "@" ) />
  • <cfset ArrayAppend( arrEmails, ".ben" ) />
  • <cfset ArrayAppend( arrEmails, "." ) />
  • <cfset ArrayAppend( arrEmails, "..." ) />
  • <cfset ArrayAppend( arrEmails, "-.-.ben" ) />
  •  
  • <!--- Add emails that test the NAME part. --->
  • <cfset ArrayAppend( arrEmails, "sarah@hotties.ben" ) />
  • <cfset ArrayAppend( arrEmails, "mary-kate@equinox.ben" ) />
  • <cfset ArrayAppend( arrEmails, "mrs.molly@teacup.ben" ) />
  • <cfset ArrayAppend( arrEmails, "libby_star@blondes.ben" ) />
  • <cfset ArrayAppend( arrEmails, "d.d.busty@domain.ben" ) />
  • <cfset ArrayAppend( arrEmails, "heather..rose@gotglue.ben" ) />
  • <cfset ArrayAppend( arrEmails, "anne--fesekis@hackley.ben" ) />
  • <cfset ArrayAppend( arrEmails, ".anna.cooper.@hockeychicks.ben" ) />
  • <cfset ArrayAppend( arrEmails, "-christina.cox-@hollywoodhotties.ben" ) />
  • <cfset ArrayAppend( arrEmails, "@campuscuties.ben" ) />
  • <cfset ArrayAppend( arrEmails, "-@justlegal.ben" ) />
  • <cfset ArrayAppend( arrEmails, ".@swank.ben" ) />
  • <cfset ArrayAppend( arrEmails, "3@atatime.ben" ) />
  • <cfset ArrayAppend( arrEmails, "/@punctuation.ben" ) />
  • <cfset ArrayAppend( arrEmails, "*@punctuation.ben" ) />
  • <cfset ArrayAppend( arrEmails, "ben&molly@kittens.ben" ) />
  •  
  • <!--- Add emails that test the DOMAIN part. --->
  • <cfset ArrayAppend( arrEmails, "sarah@hot-girls.ben" ) />
  • <cfset ArrayAppend( arrEmails, "anne@got----blondes.ben" ) />
  • <cfset ArrayAppend( arrEmails, "jessica@-cool-girl-.ben" ) />
  • <cfset ArrayAppend( arrEmails, "julie@cool.beans.ben" ) />
  • <cfset ArrayAppend( arrEmails, "julia@brazil..buddies.ben" ) />
  • <cfset ArrayAppend( arrEmails, "kate@dorm.-.girls.ben" ) />
  • <cfset ArrayAppend( arrEmails, "lara@-.ben" ) />
  • <cfset ArrayAppend( arrEmails, "michelle@36-24-36.ben" ) />
  • <cfset ArrayAppend( arrEmails, "kimmie@ladies.who.smile.ben" ) />
  •  
  • <!--- Add emails that test the EXTENSION part. --->
  • <cfset ArrayAppend( arrEmails, "ye@whatwhat" ) />
  • <cfset ArrayAppend( arrEmails, "stacy@largeladies.4" ) />
  • <cfset ArrayAppend( arrEmails, "marci@totality.123" ) />
  • <cfset ArrayAppend( arrEmails, "jen@toocute.z" ) />
  • <cfset ArrayAppend( arrEmails, "jo@cutencurley.xy" ) />
  • <cfset ArrayAppend( arrEmails, "pam@waycute.xyz" ) />
  • <cfset ArrayAppend( arrEmails, "gina@cowgirls.a4b" ) />
  • <cfset ArrayAppend( arrEmails, "linda@lumpyladies.abcdef" ) />
  • <cfset ArrayAppend( arrEmails, "jane@ilikeemlarge.abcdefghij" ) />
  •  
  •  
  • <!--- Create a table to output the results. --->
  • <table border="0" cellspacing="0" cellpadding="0">
  • <tr>
  • <td>
  • Email
  • </td>
  • <td>
  • IsValid()
  • </td>
  • <td>
  • Email Success
  • </td>
  • </tr>
  •  
  • <!--- Loop over the emails and validate them. --->
  • <cfloop index="intI" from="1" to="#ArrayLen( arrEmails )#" step="1">
  •  
  • <!--- Try sending out email. --->
  • <cftry>
  •  
  • <!--- Send mail. --->
  • <cfmail
  • to="#arrEmails[ intI ]#"
  • from="xxx@yyy.zzz"
  • subject="This is a test email">
  •  
  • This is a test email.
  • </cfmail>
  •  
  • <!--- Set success flag. --->
  • <cfset blnEmailSuccess = true />
  •  
  • <!--- Catch email errors. --->
  • <cfcatch>
  •  
  • <!--- Email failed. Set success flag. --->
  • <cfset blnEmailSuccess = false />
  •  
  • </cfcatch>
  •  
  • </cftry>
  •  
  •  
  • <!--- Check for validity. --->
  • <cfset blnValid = IsValid( "email", arrEmails[ intI ] ) />
  •  
  • <tr>
  • <td>
  • #arrEmails[ intI ]#
  • </td>
  • <td>
  • #YesNoFormat( blnValid )#
  • </td>
  • <td>
  • #YesNoFormat( blnEmailSuccess )#
  • </td>
  • </tr>
  •  
  • </cfloop>
  • </table>

The results are kind of surprising. I was a bit shocked how many emails actually can get sent through CFMail with completely horrible email addresses. Here are the results (I have modified the table for display):


 
 
 

 
Email Form Errors Using IsValid() and CFMail  
 
 
 

As you can see, only THREE emails crashed the ColdFusion CFMail tag. It has hardly any issues. The salmon rows are the rows where IsValid() and CFMail disagree as to what is a valid email address. Very interesting indeed. Honestly, I think my email validation can be MUCH MUCH more simple (if only caring about the CFMail tag crashing). But I guess, I can start to use IsValid(). But, and I am no expert on email address formatting, but IsValid() seems very relaxed about some of the stuff above.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Sami Hoda
Sep 12, 2006 at 9:00 PM // reply »
18 Comments

This one is a good one for Damon Cooper for enhancement to Scorpio. You can contact him or I can file an enhancement if you'd like. Great work by the way.


Sep 12, 2006 at 10:44 PM // reply »
5,406 Comments

Sami,

I just emailed Damon. But I am a little fish and I never hear back from anyone. Feel free to get in contact with him if you think it will help things along.

Thanks!


Tom Jordahl
Sep 13, 2006 at 1:18 AM // reply »
1 Comments

Perhaps more information will help.

The IsValid() function uses the following regular expression to determine if the email is valid:
^[a-zA-Z0-9-'\+~]+(\.[a-zA-Z0-9-'\+~]+)*@([a-zA-Z_0-9-]+\.)+[a-zA-Z]{2,7}$

The CFMail tag uses the Sun Java class javax.mail.internet.InternetAddress parse() function. Since the implementation uses JavaMail, this is how we generate the InternetAddress objects that we pass in for the addresses (to, from, cc, etc).

The "strict" attribute is turned on. The JavaDoc says of this:

"Parse the given sequence of addresses into InternetAddress objects. If strict is false, simple email addresses separated by spaces are also allowed. If strict is true, many (but not all) of the RFC822 syntax rules are enforced. In particular, even if strict is true, addresses composed of simple names (with no "@domain" part) are allowed. Such "illegal" addresses are not uncommon in real messages.

Non-strict parsing is typically used when parsing a list of mail addresses entered by a human. Strict parsing is typically used when parsing address headers in mail messages"

See the JavaDoc at http://java.sun.com/products/javamail/javadocs/javax/mail/internet/InternetAddress.html

Hope that clears it up for you.


Sep 13, 2006 at 3:20 AM // reply »
29 Comments

i've done some work w/javamail & what tom says is true (of course). even strict parsing passes a lot of addresses some folks would consider "bad", though by the same definition so does the RFC.

i guess complain to sun: http://java.sun.com/products/javamail/index.jsp better yet, if you get on the javamail list you can complain directly to bill shannon.


Sep 13, 2006 at 7:26 AM // reply »
5,406 Comments

Hey guys, I really appreciate the information. I am not familiar at all with the javax classes. I see that I can create them using CreateObject(). That is kind of cool.

But please, I don't want to be misunderstood. I wasn't attacking email validation. I DON'T want to complain to anyone. It's not important to me that some emails get through that maybe are not the best. As I said, I don't want the page to crash and from what I can see, I can relax a bit of my email validation. That was really my main point.

But again, thanks for all the feedback.


Apr 17, 2007 at 1:41 PM // reply »
162 Comments

This is great information. Thanks for posting this, Ben and Tom.

However, it confirms my fears about using ColdFusion's email address validation (through isValid() or cfparam), since the regex Tom posted is a little crazy, IMO (despite my acceptance that an email validation regex should not follow RFC 822 to the letter). For example, it allows underscores in the hostname (which technically makes it an invalid domain name), and yet there's no support for internationalized domain names (or usernames). And what's with the seemingly arbitrary seven-character top-level domain cap, when the longest official TLDs (.museum and .travel) are six characters? Is it trying to support reserved TLDs like .example and .invalid? If so, what about .localhost, which is eight characters? There are a number of other issues I could point out as well.

In any case, that regex (and any others which control validation provided by isValid/cfparam) should be in the LiveDocs.


Stephen Cassady
Dec 6, 2007 at 3:14 PM // reply »
3 Comments

Ahh, email validation is not actually correct for many of those entries - http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx

I recently got a support request for an email that looks like

name&name@domain.com

On research, the "&" actually appears to be valid, although it is though to be not valid.

This is causing some problems.


Dec 10, 2007 at 8:14 AM // reply »
5,406 Comments

@Stephen,

I just recently heard of a big problem that was caused by the & characters. It was something bit, like New York Times email addresses or something. Can't remember where I heard it.

Just tried running this:

#IsValid( "email", "name&name@domain.com" )#

... and it returns NOT valid.


Ryan
Dec 4, 2008 at 11:06 AM // reply »
1 Comments

One of my e-mail addresses has the domain with format @xx.xxxxxx.com, yet it seems like you might exclude that as an invalid e-mail address (either that or you were checking to see if the system would trip over a perfectly valid e-mail address, I'm not clear what your expected result was). My point is, although validation will help reduce human error and keep out some spam, being too stringent may block out a perfectly valid e-mail. Please exercise caution!


Dec 4, 2008 at 11:17 AM // reply »
5,406 Comments

@Ryan,

I am not sure what you are saying. From my testing above, that format of email address IS valid. Notice that the address:

julie@cool.beans.ben

... passed both IsValid() and a successful CFMail execution. Sub-domains clearly work in ColdFusion.

Am I confused about what you are saying?


Post Comment  |  Ask Ben

Recent Blog Comments
Jul 4, 2009 at 4:00 AM
Terms Of Service / Privacy Policy Document Generator
thanks ben, I'm not a big fan of contracts so to find your no no-nesense ToS generator has helped me no end. all the best matt ... read »
Justice
Jul 3, 2009 at 11:10 PM
Create A Running Average Without Storing Individual Values
@Ben, I think you're going about this the wrong way. You're trying to use complicated techniques when there is a simple and beautiful technique readily available (a la Gary Funk's comment). Instead ... read »
Bob
Jul 3, 2009 at 9:19 PM
Project HUGE: Huge In A Hurry - Get Big - Phase 3 / Week 1
a good technical explanation http://crossfitphoenix.typepad.com/crossfit_phoenix_forging_/the-overhead-squat.html ... read »
Jul 3, 2009 at 9:03 PM
Create A Running Average Without Storing Individual Values
If I wanted to do this and only carry two numbers, I'd keep track of the sum and N. Then you are pretty much accurate all the time. average = (sum + new_number) / (N + 1) But all this was in a for ... read »
Roland Collins
Jul 3, 2009 at 8:58 PM
Create A Running Average Without Storing Individual Values
@Martin - not just floating point though. Depending on what langauge you're working in, decimals can cause just as many headaches if they're not precise enough. But again, for most applications, th ... read »
Isnogood
Jul 3, 2009 at 7:16 PM
Project HUGE: Huge In A Hurry - Get Big - Phase 3 / Week 1
Watch this http://www.nsca-lift.org/videos/default.shtml ... read »
Aaron
Jul 3, 2009 at 7:13 PM
Project HUGE: Get Big, Phase One (Chat Waterbury - Huge In A Hurry)
I've just finished the 3rd week of phase 3, and have to agree that the overhead squats are hard. I think this is most due to the wide grip on which places more pressure on your upper back. Only this ... read »
Isnogood
Jul 3, 2009 at 7:11 PM
Project HUGE: Huge In A Hurry - Get Big - Phase 3 / Week 1
Very good, there were some near perfect reps, and there were some dodgy ones, but you're getting there your body position is good. Work on your depth and do not let the bar move forward or backward, ... read »