8

In my app I have to send email to recipient who has umlauts in domain name. Example: "test@äöü.test.com"

I'm using cfmail tag and I'm getting such error: "invalid definition for attribute to at tag mail" "Invalid E-Mail Address definition (test@äöü.test.com)"

Is there any way to send email to such recipients in coldfusion?

balytskyi
  • 303
  • 3
  • 10
  • 2
    The syntax `Test` works for me as does swapping the `from` and `to` values. Can you provide code and the message in exception.log? – orangepips Jun 15 '11 at 15:53
  • What version of ColdFusion? 9? – Sean Coyne Jun 15 '11 at 18:53
  • 1
    @orangepips: are you using Railo by any chance? I get the same error as the OP on ACF8 and 9, which is expected since ACF uses the javax.mail.internet.InternetAddress parser which only allows ASCII values as per RFC822 (see http://tjordahl.blogspot.com/2006/09/coldfusion-email-validation-isvalid.html ) – CfSimplicity Jun 17 '11 at 11:14
  • @CFSimplicty: I'm using ACF 9.01. Good link from Tom Jordahl's blog. – orangepips Jun 17 '11 at 11:55
  • @orangepips. How odd. Can't think why you're not seeing the error then. – CfSimplicity Jun 17 '11 at 12:41
  • Btw, here's the start of the stack trace from the exception.log "Error","jrpp-4","06/17/11","08:28:37",,"Attribute validation error for tag CFMAIL.The value of the attribute to, which is currently test@äöü.test.com, is invalid. The specific sequence of files included or processed is: C:\Dev\servers\simplicity\webroot\test\index.cfm, line: 3 " coldfusion.tagext.InvalidTagAttributeException: Attribute validation error for tag CFMAIL. at coldfusion.tagext.net.MailTag.validate(MailTag.java:666) at coldfusion.tagext.net.MailTag.processAttributes(MailTag.java:766) – CfSimplicity Jun 17 '11 at 13:18

2 Answers2

6

There is even a easier solution! Why not use Oracles built in class: http://download.oracle.com/javase/6/docs/api/java/net/IDN.html#toUnicode(java.lang.String)

Then you only have to do this (example shows from punycode to Unicode):

<cfset strUrl = "xn--land-poa.se" />

<!--- Create a Java URL. --->
<cfset jUrl = CreateObject( "java", "java.net.IDN" ).toUnicode(strUrl) />

<cfoutput>
#jUrl#

You don´t have to download anything!

Molnfront
  • 450
  • 6
  • 9
3

I'm no I18N expert but I was intrigued enough to investigate and come up with the following solution.

The problem is essentially how to send mail to Internationalised Domain Names (IDN), i.e. those which contain non-ASCII characters. IDNs are valid nowadays but not recognized by many systems including Java (and therefore ColdFusion, which uses the Java validation for CFMAIL address fields - hence the error you're seeing).

For a system to recognise an IDN it needs to be converted to an ASCII form called Punycode. For example müller.org needs to be converted to xn--mller-kva.org

LibIdn is an OS java library that will do this and the following code shows how you can hook it up to CF using Mark Mandel's JavaLoader.

<cffunction name="convertIdnToAscii" returntype="string" output="false">
    <cfargument name="domain" type="string" required="true">
    <cfscript>
        var local   =   {};
        // these paths assume the JavaLoader folder and the libidn-1.22.jar are in the same folder as the cfm template.
        local.javaLoaderPath    =   "javaLoader.JavaLoader";
        local.idnLibPath    =   ExpandPath( "libidn-1.22.jar" );
        // convert the IDN lib path to an array which is what JavaLoader expects
        local.libPathArray  =   [ local.idnLibPath ];
        //load the IDN Lib
        loader  =   CreateObject( "component",local.javaLoaderPath ).init( local.libPathArray );
        // create an instance of the IDN lib
        local.idn   =   loader.create( "gnu.inet.encoding.IDNA" ).init();
        // convert the domain name
        return local.idn.toASCII( arguments.domain );
    </cfscript>
</cffunction>

<cffunction name="convertIdnAddress" returntype="string" output="false">
    <cfargument name="address" type="string" required="true">
    <cfscript>
        var local   =   {};
        local.domain    =   GetToken( arguments.address,2,"@" );
        local.converted =   convertIdnToAscii( local.domain );
        return  Replace( arguments.address,local.domain,local.converted );
    </cfscript>
</cffunction>

<!--- Loop over a list of addresses and convert them if necessary --->
<cfset processedAddresses   =   []>
<cfloop list="test@äöü.test.com,test@example.com" index="address">
    <cfif( NOT IsValid( "email",address ) )>
        <cfset address  =   convertIdnAddress( address )>
    </cfif>
    <cfmail server="0.0.0.0" from="sender@mydomain.com" to="#address#" subject="test">Message</cfmail>
    <cfset ArrayAppend( processedAddresses,address )>
</cfloop>
<cfdump var="#processedAddresses#">

This will send 2 emails (to a non-existent mailserver) and dump the converted addresses:

test@xn--4ca0bs.test.com

test@example.com

Notes:

  1. To get the libidn jar file, download and extract the tar and look for it in the Java directory
  2. The above assumes the libidn jar and JavaLoader package are located in the same folder as the template contain the CF code
  3. The above should work on CF8 and above, although I've only tested it on CF9.
  4. Be aware there's no error handling for addresses that might be invalid for reasons other than it containing an IDN.
CfSimplicity
  • 2,338
  • 15
  • 17
  • 1
    @orangepips. OK thanks for the suggestion - edited. Although to be honest I was trying just to focus on the form of the domain which is the issue here. – CfSimplicity Jun 17 '11 at 13:06