public static function extractEmail($strString, $strAllowedTags='')
	{
		$arrEmails = array();

		if (strpos($strString, '@') === false)
		{
			return $arrEmails;
		}

		// Find all mailto: addresses
		preg_match_all('/mailto:(?:[^\x00-\x20\x22\x40\x7F]{1,64}+|\x22[^\x00-\x1F\x7F]{1,64}?\x22)@(?:\[(?:IPv)?[a-f0-9.:]{1,47}\]|[\w.-]{1,252}\.[a-z]{2,63}\b)/u', $strString, $matches);

		foreach ($matches[0] as &$strEmail)
		{
			$strEmail = str_replace('mailto:', '', $strEmail);

			if (Validator::isEmail($strEmail))
			{
				$arrEmails[] = $strEmail;
			}
		}

		unset($strEmail);

		// Encode opening arrow brackets (see #3998)
		$strString = preg_replace_callback('@</?([^\s<>/]*)@', function ($matches) use ($strAllowedTags)
		{
			if ($matches[1] == '' || stripos($strAllowedTags, '<' . strtolower($matches[1]) . '>') === false)
			{
				$matches[0] = str_replace('<', '&lt;', $matches[0]);
			}

			return $matches[0];
		}, $strString);

		// Find all addresses in the plain text
		preg_match_all('/(?:[^\x00-\x20\x22\x40\x7F]{1,64}|\x22[^\x00-\x1F\x7F]{1,64}?\x22)@(?:\[(?:IPv)?[a-f0-9.:]{1,47}\]|[\w.-]{1,252}\.[a-z]{2,63}\b)/u', strip_tags($strString), $matches);

		foreach ($matches[0] as &$strEmail)
		{
			$strEmail = str_replace('&lt;', '<', $strEmail);

			if (Validator::isEmail($strEmail))
			{
				$arrEmails[] = $strEmail;
			}
		}

		return array_unique($arrEmails);
	}