简体   繁体   中英

Retrieve full email address from string

I'm currently building a Slack bot using Laravel, and one of the features is that it can receive an email address and send a message to it.

The issue is that email addresses (eg bob@example.com ) come through as <mailto:bob@example.com|bob@example.com> from Slack.

I currently have a function that retrieves the email from this:

public function getEmail($string)
{
    $pattern = '/[a-z0-9_\-\+]+@[a-z0-9\-]+\.([a-z]{2,3})(?:\.[a-z]{2})?/i';
    preg_match_all($pattern, $string, $matches);
    $matches = array_filter($matches);

    return $matches[0][0];
}

This seemed to be working fine with email addresses like bob@example.com , however it seems to fail when working with email addresses like bob.jones@example.com (which would come through as <mailto:bob.jones@example.com|bob.jones@example.com> . In these cases, the function is returning jones@example.com as the email address.

I'm not great with regex, but is there something else I could use/change in my pattern, or a better way to fetch the email address from the string provided by Slack?

Could always take regex out of the equation if you know that's always the format it'll be in:

$testString = '<mailto:bob@example.com|bob@example.com>';

$testString = str_replace(['<mailto:', '>'], '', $testString);

$addresses = explode('|', $testString);

echo $addresses[0];

This method will do the job and you avoid to have regular expressions. and make sure the email being returned is a real email address by validating it with php functions.

function getEmailAddress($string) 
{
    $string = trim($string, '<>');
    $args = explode('|', $string);
    foreach ($args as $_ => $val) {
        if(filter_var($val, FILTER_VALIDATE_EMAIL) !== false) {
            return $val;
        }
    }

    return null;    
}

echo getEmailAddress('<mailto:bob@example.com|bob@example.com>');

Output

bob@example.com

You know the strings containing the e-mail address will always be of the form <mailto:bob@example.com|bob@example.com> , so use that. Specifically, you know the string will start with <mailto: , will contain a | , and will end with > .

An added difficulty though, is that the local part of an e-mail address may contain a pipe character as well, but the domain may not; see the following question.
What characters are allowed in an email address?

public function getEmail($string)
{
    $pattern = '/^<mailto:([^@]+@[^|]+)|(.*)>$/i';
    preg_match_all($pattern, $string, $matches);
    $matches = array_filter($matches);
    return $matches[1][0];
}

This matches the full line from beginning to end, but we capture the e-mail address within the first set of parentheses. $matches[1] contains all matches from the first capturing parentheses. You could use preg_match instead, since you're not looking for all matches, just the first one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM