docs: function _handleAddress(tokens) {
      var token,
          isGroup = false,
          state = 'text',
          address,
          addresses = [],
          data = {
              address: [],
              comment: [],
              group: [],
              text: []
          },
          i, len;
  
      // Filter out <addresses>, (comments) and regular text
      for (i=0, len = tokens.length; i<len; i++) {
          token = tokens[i];
  
          if (token.type == 'operator') {
              switch(token.value) {
                  case '<':
                      state = 'address';
                      break;
                  case '(':
                      state = 'comment';
                      break;
                  case ':':
                      state = 'group';
                      isGroup = true;
                      break;
                  default:
                      state = 'text';
              }
          } else {
              if (token.value) {
                  data[state].push(token.value);
              }
          }
      }
  
      // If there is no text but a comment, replace the two
      if (!data.text.length && data.comment.length) {
          data.text = data.comment;
          data.comment = [];
      }
  
      if (isGroup) {
          // http://tools.ietf.org/html/rfc2822#appendix-A.1.3
          data.text = data.text.join(' ');
          addresses.push({
              name: data.text,
              group: data.group.length ? parse(data.group.join(',')) : []
          });
      } else {
          // If no address was found, try to detect one from regular text
          if (!data.address.length && data.text.length) {
              for (i = data.text.length - 1; i>=0; i--) {
                  if (data.text[i].match(/^[^@\s]+@[^@\s]+$/)) {
                      data.address = data.text.splice(i,1);
                      break;
                  }
              }
  
              var _regexHandler = function(address) {
                  if (!data.address.length) {
                      data.address = [address.trim()];
                      return ' ';
                  } else {
                      return address;
                  }
              };
  
              // still no address
              if (!data.address.length) {
                  for (i = data.text.length - 1; i>=0; i--) {
                      data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^@\s]+\b\s*/, _regexHandler).trim();
                      if (data.address.length) {
                          break;
                      }
                  }
              }
          }
  
          // If there's still is no text but a comment exixts, replace the two
          if (!data.text.length && data.comment.length) {
              data.text = data.comment;
              data.comment = [];
          }
  
          // Keep only the first address occurence, push others to regular text
          if (data.address.length > 1) {
              data.text = data.text.concat(data.address.splice(1));
          }
  
          // Join values with spaces
          data.text = data.text.join(' ');
          data.address = data.address.join(' ');
  
          if (!data.address && isGroup) {
              return [];
          } else {
              address = {
                  address: data.address || data.text || '',
                  name: data.text || data.address || ''
              };
  
              if (address.address == address.name) {
                  if ((address.address || '').match(/@/)) {
                      address.name = '';
                  } else {
                      address.address = '';
                  }
  
              }
  
              addresses.push(address);
          }
      }
  
      return addresses;
  }