
/**
 * The idea is that any email address accepted by this function is valid by
 * RFC 2822 although not all valid email addresses are accepted by this function.
 *
 * We allow emails addresses of the following form:
 *
 *		address         =       mailbox
 *      mailbox         =       addr-spec
 *      addr-spec       =       local-part "@" domain
 *      local-part      =       dot-atom
 *      domain          =       dot-atom
 *      dot-atom        =       dot-atom-text
 *      dot-atom-text   =       1*atext *("." 1*atext)
 *      atext           =       [see RFC 2822 or implementation below]
 *
 * This is a much simplified version of the specification given in RFC 2822
 * section 3; in particular we do not accept 'name-addr', 'domain-literal' or
 * 'quoted-string' expressions.
 *
 * The above specification allows for character in 'domain' that are not
 * often seen; on the other hand, the syntax for 'domain' given in
 * RFC1034 section 3.5 is too restrictive (see also RFC 952 & RFC 1122).
 *
 * Note: We avoid regular expressions in implementation to support older user agents.
 *
 * @author Andrew Cottrell
 */
function EmailValidation_validate(email, optional, debug) {

    if (debug) {alert("Validating email address: " + email);}

    var LENGTH = email.length;

    if (LENGTH == 0) {
        if (debug) {alert("Email address is " + (optional ? "optional" : "mandatory") + ".");}
        return optional;
    }

    /* Constants. */
    var ALPHA_LOWER = "abcdefghijklmnopqrstuvwxyz";
    var ALPHA_UPPER = ALPHA_LOWER.toUpperCase();
    var ALPHA       = ALPHA_LOWER + ALPHA_UPPER;
    var DIGIT       = "0123456789";
    var ATEXT       = ALPHA + DIGIT + "!#$%&'*+-/=?^_`{|}~";

    /* Initialize local variables. */
    var index              = 0;
    var charAt             = email.charAt(index);

    /* Check initial character of local-part. */
    if (ATEXT.indexOf(charAt) == -1) {
        if (debug) {alert("Unexpected character in local-part: " + charAt);}
        return false;
    }

    var scanningLocalPart = true;

    /* Accept local-part */
    while (scanningLocalPart) {

        /* Accept all characters in ATEXT. */
        while (ATEXT.indexOf(charAt) != -1) {
            /* Move to next character. */
            index++;
            if (index == LENGTH) {
                if (debug) {alert("Unexpected end of String.");}
                return false;
            }
            charAt = email.charAt(index);
        }

        if (charAt == '@') {

            /* We've got to the end of the local-part. */
            scanningLocalPart = false;

            /* Move to next character. */
            index++;
            if (index == LENGTH) {
                if (debug) {alert("Unexpected end of String.");}
                return false;
            }
            charAt = email.charAt(index);

        } else if (charAt == '.') {

            /* Move to next character. */
            index++;
            if (index == LENGTH) {
                if (debug) {alert("Unexpected end of String.");}
                return false;
            }
            charAt = email.charAt(index);

            /* Check that next character is in ATEXT */
            if (ATEXT.indexOf(charAt) == -1) {
                if (debug) {alert("Unexpected character in local-part: " + charAt);}
                return false;
            }

        } else {
            if (debug) {alert("Unexpected character in local-part: " + charAt);}
            return false;
        }
    }

    /* AMENDED 2007-08-01 Check that domain contains at least one dot. */
    if (email.lastIndexOf(".") < index) {
        if (debug) {alert("Domain must contain at least one dot.");}
        return false;
    }

    /* Accept domain until end of String. */

    /* Check initial character of domain. */
    if (ATEXT.indexOf(charAt) == -1) {
        if (debug) {alert("Unexpected character in domain: " + charAt);}
        return false;
    }

    /* Accept domain until end of String. */
    while (true) {

        /* Accept all characters in ATEXT. */
        while (ATEXT.indexOf(charAt) != -1) {
            /* Move to next character. */
            index++;
            if (index == LENGTH) {
                if (debug) {alert("Email address is valid.");}
                return true;
            }
            charAt = email.charAt(index);
        }

        if (charAt == '.') {

            /* Move to next character. */
            index++;
            if (index == LENGTH) {
                if (debug) {alert("Unexpected end of string.");}
                return false;
            }
            charAt = email.charAt(index);

            /* Check that next character is in ATEXT. */
            if (ATEXT.indexOf(charAt) == -1) {
                if (debug) {alert("Unexpected character in domain: " + charAt);}
                return false;
            }

        } else {
            if (debug) {alert("Unexpected character in domain: " + charAt);}
            return false;
        }
    }

    /* This should be unreachable. */
    return false;
}
