function isValidEmail(str) {
  // These comments use the following terms from RFC2822:
  // local-part, domain, domain-literal and dot-atom.
  // Does the address contain a local-part followed an @ followed by a domain?
  // Note the use of lastIndexOf to find the last @ in the address
  // since a valid email address may have a quoted @ in the local-part.
  // Does the domain name have at least two parts, i.e. at least one dot,
  // after the @? If not, is it a domain-literal?
  // This will accept some invalid email addresses
  // BUT it doesn't reject valid ones. 
  var atSym = str.lastIndexOf("@");
  if (atSym < 1) { return false; } // no local-part
  if (atSym == str.length - 1) { return false; } // no domain
  if (atSym > 64) { return false; } // there may only be 64 octets in the local-part
  if (str.length - atSym > 255) { return false; } // there may only be 255 octets in the domain

  // Is the domain plausible?
  var lastDot = str.lastIndexOf(".");
  //alert(str.charAt(atSym - 1));
  // Check if it is a dot-atom such as example.com
  if(str.charAt(0) == '.')	{ return false; }
  else if(str.charAt(atSym - 1) == '.') { return false; }		
  else if (lastDot > atSym + 1 && lastDot < str.length - 1) {
	if (str.charAt(lastDot-1)== '.') { return false; }
	else
		return true;
 }
  
  //  Check if could be a domain-literal.
  if (str.charAt(atSym + 1) == '[' &&  str.charAt(str.length - 1) == ']') { return true; }
  return false;

}

function testIsValidEmail(str) {
  alert("'" + str + "' is " + (isValidEmail(str) ? "" : "NOT ") + " a valid email address.");
}

function checkSamples() {
  var validAddress = [
    'me@example.com',
    'a.nonymous@example.com',
    'name+tag@example.com',
    'name\\@tag@example.com',
    'spaces\\ are\\ allowed@example.com',
    '"spaces may be quoted"@example.com',
    '!#$%&\'*+-/=.?^_`{|}~@[1.0.0.127]',
    '!#$%&\'*+-/=.?^_`{|}~@[IPv6:0123:4567:89AB:CDEF:0123:4567:89AB:CDEF]',
    'me(this is a comment)@example.com'
  ];
  var invalidAddress = [
    'me@',
    '@example.com',
    'me.@example.com',
    '.me@example.com',
    'me@example..com',
    'me.example@com',
    'me\\@example.com'
  ];

  var results = new StringBuffer();

  var handlesValidAddressesCorrectly = true;
  results.append('<table border="1">');
  results.append('<caption>Does the function accept all the valid sample addresses?</caption>');
  results.append('<tr><th>Valid address</th><th>Function returns</th></tr>');
  for (var i = 0; i < validAddress.length; i++) {
    results.append('<tr><td>');
    results.append(validAddress[i]);
    results.append('</td><td>');
    if (isValidEmail(validAddress[i])) {
      results.append('<span class="good">true</span>');
    } else {
      handlesValidAddressesCorrectly = false;
      results.append('<strong class="fail">false</strong>');
    }
    results.append('</td></tr>');
  }
  results.append('</table>');

  var handlesInvalidAddressesCorrectly = true;
  results.append('<table border="1">');
  results.append('<caption>Does the function reject all the invalid sample addresses?</caption>');
  results.append('<tr><th>Valid address</th><th>Function returns</th></tr>');
  for (var i = 0; i < invalidAddress.length; i++) {
    results.append('<tr><td>');
    results.append(invalidAddress[i]);
    results.append('</td><td>');
    if (!isValidEmail(invalidAddress[i])) {
      results.append('<span class="good">false</span>');
    } else {
      handlesInvalidAddressesCorrectly = false;
      results.append('<em class="warning">true</em>');
    }
    results.append('</td></tr>');
  }
  results.append('</table>');

  var conclusion;
  if (handlesValidAddressesCorrectly) {
    if (handlesInvalidAddressesCorrectly) {
      conclusion = '<p><strong class="good">The function works correctly with all the sample addresses.</strong></p>';
    } else {
      conclusion = '<p><em class="warning">The function incorrectly accepts some invalid addresses.</em></p>';
    }
  } else {
    conclusion = '<p><strong class="fail">The function incorrectly rejects some valid addresses.</strong></p>';
  }

  document.getElementById('testResults').innerHTML = conclusion + results.toString();
}

function StringBuffer() {
  this.buffer = [];
}

StringBuffer.prototype.append = function append(string) {
  this.buffer.push(string);
  return this;
};

StringBuffer.prototype.toString = function toString() {
  return this.buffer.join("");
};

