Why is My Browser NOT Supported?

I don't know about you, but whenever I run into a "Browser Not Supported" message, I just start to growl. Here's a screen grab of one I ran into this morning from Eloqua.com.

Um, yeah, here we are, coming into the year 2009 and there are still several companies in the marketplace that throw "Browser Not Supported" messages to the end user. It's not like I'm using some antiquated, or completely custom browser either, I'm using Firefox here. This is not what I call user friendly, especially for a company that tracks user behavior, among other services. I'm quite surprised by this. Am I alone here?

CFMail Best-Practices for Sending Web-Generated E-mail (e-cards, forward-to-a-friend, etc.)

There are a number of ColdFusion articles available addressing CFMail being detected as spam, etc. which primarily deal with the "Message-ID" contained in an email's header. Charlie Arehart has a couple of detailed examples on his blog which I recommend other ColdFusion developers consider reading:

While we will also be dealing with email headers, this article is primarily concerned with addressing suggestions brought forth by the Sender Policy Framework (SPF) and their article titled How web-generated e-mailers can avoid looking like forgers. In addition, the vast majority of projects I'm involved with are hosted in a shared-hosting environment. So we won't be modifying anything in the CFAdmin area.

If you're wondering how to view email headers, I found a pretty good link on the University of Delaware Police Computer Forensics Lab web site (I know, sounds pretty serious, doesn't it).

The code examples I use here have been tested on ColdFusion 8.0.1. However, these should work with CF 6, 7 and 8.0.0 with very little, if any, modifications.

To send a web-generated email, you should collect at a minimum the "From" email, the "To" email, a "Message," and preferably the senders "Name." Obviously, there are several other things you could collect such as "Subject" and who to "Cc" or "Bcc," but let's just keep this simple for now. So let's create a form to send a simple message using the following code:


<div style="padding:20px; background-color:#CCCCCC; border:1px solid #000000; width:325px;">
    <cfform id="form1"
            name="form1"
            method="post"
            action="#cgi.SCRIPT_NAME#?#cgi.QUERY_STRING#">

        <p><label for="messageFromName">From Name:</label><br />
        <cfinput     type="text"
                    name="messageFromName"
                    id="messageFromName"
                    value="Suzie Visitor"
                    validate="noblanks"
                    size="30"
                    required="yes"
                    message="Name is required." />
</p>
        <p><label for="messageFromEmail">From Email:</label><br />
        <cfinput     type="text"
                    name="messageFromEmail"
                    id="messageFromEmail"
                    value="suzie.vistor@gmail.com"
                    validate="email"
                    size="30"
                    required="yes"
                    message="A valid email FROM is required." />
</p>
        <p><label for="messageTo">To:</label><br />
        <cfinput     type="text"
                    name="messageTo"
                    id="messageTo"
                    value="friend@theirdomain.com"
                    validate="email"
                    size="30"
                    required="yes"
                    message="A valid email TO is required." />
</p>
        <p><label for="messageText">Message:</label><br />
        <cfinput    type="text"
                    name="messageText"
                    id="messageText"
                    value="My simple message goes here."
                    validate="noblanks"
                    maxlength="160"
                    size="50"
                    required="yes"
                    message="Message is required." />
</p>
        <p><cfinput type="hidden" name="submitted" value="1" />
        <cfinput     type="submit"
                    name="submit"
                    value="Submit"
                    validate="submitonce" />
</p>
    </cfform>
    <!--- place cursor in the first form element --->
    <script type="text/javascript" language="JavaScript">
        document.forms['form1'].elements['messageFromName'].focus();
    </script>
</div>

Running the code should produce something similar to this:

Form Sample 1

The form doesn't do anything just yet other than post to the page/template it resides on. So let's go over the important stuff and then add some processing to the page.

According to SPF's article previously mentioned, when a web site sends web-generated e-mail, a user interacts with the web site, and an e-mail goes out on their behalf. Unfortunately, under SPF, mail from this type of service appears to be a forgery thereby being flagged as spam — unless certain precautions are taken. SPF claims that evite.com and egreetings.com have made the necessary changes and holds them up as examples other developers should emulate.

Your knee-jerk reaction to creating a CFMail to handle the form submission above might look like this:


<!---
    in a shared-hosting environment, you'll need to supply "server"
    and more than likely "username" and "password" too
--->

<cfmail    to="#trim(FORM.messageTo)#"
        from="#trim(FORM.messageFromName)# <#trim(FORM.messageFromEmail)#>"
        server="mail.yourdomain.com"
        username="info@yourdomain.com"
        password="y0urP@55w0rdH3r3"
        subject="Message from: #trim(FORM.messageFromName)#"
        type="text"
        charset="utf-8">

<cfmailpart type="text/plain" charset="utf-8">
#trim(FORM.messageText)#
</cfmailpart>
</cfmail>

However, this might (probably will) appear to be spam because it would generate something like this whilst using mail.yourdomain.com to send it:

Return-Path: suzie.visitor@gmail.com
From: "Suzie Visitor" <suzie.visitor@gmail.com>
Subject: Message from Suzie Visitor

SPF claims that "messages that use the user's address, but come from your mail servers are considered suspicious by SPF. To solve this problem, just change the headers ...

Here's a recommended example from SPF:

Return-Path: info@yourdomain.com
From: "Suzie Visitor" <info@yourdomain.com>
Reply-To: "Suzie Visitor" <suzie.visitor@gmail.com>
Subject: Message from Suzie Visitor

Keys to remember:

  • Choose a general address from your domain (info@yourdomain.com)
  • Add / Change the return-path (or "failto" in the CFMail tag) to that address
  • Change the "From" header ("from" in the CFMail tag) to that same address
  • Add a "Reply-To" header (yep, you guessed it, "replyto" in the CFMail tag) that contains your user's email address

So, to summarize, you can simply add the following code directly after the form and update the appropriate fields as necessary:


<cfparam name="REQUEST.errors" default="" />

<!--- PROCESS FORM SUBMISSION --->
<cfif isDefined("FORM.submitted") and FORM.submitted EQ 1>

    <!--- create an implicit empty array to track form validation errors --->
    <!--- if using CF 6 or 7, you will have to modify the following line by
    changing the square brackets [] to ArrayNew(1) --->

    <cfset REQUEST.errors = [] />

    <!--- validate required form field entries --->
    <cfif NOT len(trim(FORM.messageFromName))>
        <cfset ArrayAppend(REQUEST.errors, "Name is required.") />
    </cfif>
    <cfif NOT isValid("email", trim(FORM.messageFromEmail))>
        <cfset ArrayAppend(REQUEST.errors, "A valid email FROM is required.") />
    </cfif>
    <cfif NOT isValid("email", trim(FORM.messageTo))>
        <cfset ArrayAppend(REQUEST.errors, "A valid email TO is required.") />
    </cfif>
    <cfif NOT len(trim(FORM.messageText))>
        <cfset ArrayAppend(REQUEST.errors, "Message is required.") />
    </cfif>

    <!--- as long as there are NO errors, then process the contents --->
    <cfif NOT ArrayLen(REQUEST.errors)>

    <cftry>
        <!--- send the email --->
        <cfmail    to="#trim(FORM.messageTo)#"
                from="#trim(FORM.messageFromName)# <info@yourdomain.com>"
                failto="info@yourdomain.com"
                username="info@yourdomain.com"
                password="y0urP@55w0rdH3r3"
                replyto="#trim(FORM.messageFromName)# <#trim(FORM.messageFromEmail)#>"
                server="mail.yourdomain.com"
                subject="Message from: #trim(FORM.messageFromName)#"
                type="text"
                charset="utf-8">

        <cfmailpart type="text/plain" charset="utf-8">
        #trim(FORM.messageText)#
        </cfmailpart>
        </cfmail>
        <cfcatch>
            <cfoutput>#cfcatch.Message#</cfoutput>
        </cfcatch>
    </cftry>

    <!--- show friendly message to submitter --->
    <cfoutput>
        <p>Your message has been sent at <em>#dateformat(now(), "long")# #timeformat(now(), "long")#</em> as follows:</p>
        <p>TO: #FORM.messageTo#<br />
        SUBJECT: Message from: #FORM.messageFromName#<br />
        MESSAGE:<br /></p>
        #htmleditformat(FORM.messageText)#        
    </cfoutput>
    
    <cfelse>
        <!--- if required form values weren't given, show message to submitter --->
        <cfoutput>
            <h4>Please review the following issues:</h4>
            <ul>
                <cfloop index="intError" from="1" to="#ArrayLen(REQUEST.errors)#" step="1">
                    <li>#REQUEST.errors[intError]#</li>
                </cfloop>
            </ul>        
        </cfoutput>
    
    </cfif>

</cfif>

By following this example, you should be able to create some pretty interesting web-generated email applications that fit within the Sender Policy Framework guidelines.

If you have additional information, please feel free to share it! I hope this helps you in your next project.

How to Opt-Out of IE8 Standards Mode and Other Useful Internet Explorer Troubleshooting Information

As a web designer/developer, we should strive to make each visitors experience as pleasant as possible. So, whether you like it or not, if you've chosen the web designer/developer career, you have to work with Windows® Internet Explorer® (IE).

I use Microsoft's Virtual PC to test web site display and functionality on various versions of IE (6, 7 and 8 at the moment). Unfortunately, I was experiencing a display issue only in IE8. Now, I realize the number of people currently using IE8 is extremely small. Soon enough though, there will be tens of thousands of people using it right? I might as well try to correct it now rather than pull my hair out later.

Rather than go into the display issue itself, I found a very useful technique to opt-out of IE8 standards mode. Or, in regular terms, how to make IE8 display a web page as if it were IE7.

First, I should explain why I chose this route. For one thing, it quickly fixed the display issue. Is there a better reason?

All I had to do was include a simple meta tag to the page(s) where the problem was occurring.


<meta http-equiv="X-UA-Compatible" content="IE=7" />

Personally, I like to wrap IE specific tags with a bit of ColdFusion:


<cfif cgi.HTTP_USER_AGENT contains "msie">
    <meta http-equiv="X-UA-Compatible" content="IE=7" />
</cfif>

The downside to using this technique is that you will not be able to use the latest rendering features available in IE8. Sniff, sniff (cue smallest violin in the world) … oh well.

According to information I found on the IE8 Readiness Toolkit, you can also address this on a per-site bases by adding a HTTP header:

X-UA-Compatible:IE=EmulateIE7

Alternatively, you could use a slightly different meta tag on a per-page basis while still accessing "all Internet Explorer 8 has to offer."


<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

Word of caution here, using the "EmulateIE7" technique did not fix my display issue though. I ended up using the first technique with "IE=7" to "correct" the problem.

Here are some other helpful links relating to working with Internet Explorer, IE8 (Beta 1), etc.:

More Entries

© 2024, Stephen J. Withington, Jr.  |  Hosted by Hostek.com

Creative Commons License   |   This work is licensed under a Creative Commons Attribution 3.0 Unported License.