
	/*
	
	Address syntax
	
     address        = mailbox                      ; one addressee
     mailbox        = addr-spec                    ; simple address
     addr-spec      = local-part "@" domain        ; global address
     
     local-part     = word *("." word)             ; uninterpreted case-preserved
     word           =  atom / quoted-string
     quoted-string  = <"> *(qtext/quoted-pair) <"> ; Regular qtext or quoted chars.
     
     domain         = sub-domain *("." sub-domain)
     sub-domain     = domain-ref / domain-literal
     domain-ref     = atom                         ; symbolic reference
     domain-literal = "[" *(dtext / quoted-pair) "]"
     
     atom           =  1*<any CHAR except specials, SPACE and CTLs>
     dtext          =  <any CHAR excluding "[", "]", "\" & CR, & including linear-white-space> ; => may be folded
     
                                                 ; (  Octal, Decimal.)
     CHAR        =  <any ASCII character>        ; (  0-177,  0.-127.)
     specials    =  "(" / ")" / "<" / ">" / "@"  ; Must be in quoted-
                 /  "," / ";" / ":" / "\" / <">  ;  string, to use
                 /  "." / "[" / "]"              ;  within a word.
     SPACE       =  <ASCII SP, space>            ; (     40,      32.)
     CTL         =  <any ASCII control           ; (  0- 37,  0.- 31.)
                     character and DEL>          ; (    177,     127.)
     linear-white-space =  1*([CRLF] LWSP-char)  ; semantics = SPACE
                                                 ; CRLF => folding
	
	 */

	_debug = false;
//	_debug = true;

	/**
	 * addr-spec = local-part "@" domain
	 *
	 * local-part および domain ともに、
	 * ASCII コード文字（specials, SPACE, CTL を除く）のみ許可します。
	 * また、domain は、少なくとも２つのサブドメインから構成されるものとします。
	 */
	function checkMailAddress (addr) {
		if (addr == null || addr.length <= 0) return false;
		
		var tokens = addr.split("@");
		if (tokens.length != 2) return false;
		
		return checkLocalPart(tokens[0]) && checkDomain(tokens[1]);
	}


	/**
	 *
	 */
	function checkLocalPart (localPart) {
		if (localPart == null || localPart.length <= 0) return false;
		
		var tokens = localPart.split(".");
		if (tokens.length <= 0) return false;
		
		for (i = 0; i < tokens.length; i++) {
			if (!checkWord(tokens[i])) return false;
		}
		
		return true;
	}


	/**
	 *
	 */
	function checkWord (word) {
		if (word == null || word.length <= 0) return false;
		
		return checkAtom(word) /* || checkQuotedString(word) */;
	}


	/**
	 *
	 */
	function checkDomain (domain) {
		if (domain == null || domain.length <= 0) return false;
		
		var tokens = domain.split(".");
		if (tokens.length <= 1) return false;
		
		for (i = 0; i < tokens.length; i++) {
			if (!checkSubDomain(tokens[i])) return false;
		}
		
		return true;
	}


	/**
	 *
	 */
	function checkSubDomain (subDomain) {
		if (subDomain == null || subDomain.length <= 0) return false;
		
		return checkAtom(subDomain);
	}


	/**
	 *
	 */
	function checkAtom(atom) {
		if (atom == null || atom.length <= 0) return false;
		
		if (!checkCHAR(atom)) {
			if (_debug) alert("imcomplete (checkCHAR) " + atom);
			return false;
		}
		
		if (!checkSpecials(atom)) {
			if (_debug) alert("imcomplete (checkSpecials) " + atom);
			return false;
		}
		
		if (!checkSpace(atom)) {
			if (_debug) alert("imcomplete (checkSpace) " + atom);
			return false;
		}
		
		if (!checkCtl(atom)) {
			alert("imcomplete (checkCtl) " + atom);
			return false;
		}
		
		return true;
	}


	/**
	 *
	 */
	function checkCHAR (CHAR) {
		var patt = "[\\x00-\\x7f]+";
		var regExp = new RegExp(patt);
		
		return CHAR.match(regExp) == CHAR;
	}


	/**
	 * specials =    ( ) < > @ , ; : \ " . [ ]
	 *
	 * ( : \\(
	 * ) : \\)
	 * \\: \\\\
	 * " : \"
	 * . : \\.
	 * [ : \\[
	 * ] : \\]
	 */
	function checkSpecials(specials) {
		if (specials == null || specials.length <= 0) return false;
		
		var patt =  "[\\(\\)<>@,;:\\\\\"\\.\\[\\]]";
//		var specials =  "\\(\\)<>@,;:\\\\\\\"\\.\\[\\]";
		var regExp = new RegExp(patt);
		
		return specials.match(regExp) == null;
	}


	/**
	 *
	 */
	function checkSpace(space) {
		if (space == null || space.length <= 0) return false;
		
		var patt =  " ";
		var regExp = new RegExp(" ");
		
		return space.match(regExp) == null;
	}


	/**
	 *
	 */
	function checkCtl(ctl) {
		if (ctl == null || ctl.length <= 0) return false;
		
		var patt = "[0x00-0x1f] | 0x7f";
		var regExp = new RegExp(patt);
		
		return ctl.match(regExp) == null;
	}

