32

I want to extract email address from a string, for example:

<?php // code
$string = 'Ruchika <ruchika@example.com>';
?>

From the above string I only want to get email address ruchika@example.com.

Kindly, recommend how to achieve this.

Happy Coding
  • 2,517
  • 1
  • 13
  • 24
Liz.
  • 795
  • 2
  • 13
  • 31
  • You should use phps preg* functions to do so. Building a regular expression that matches each and every mail address is not an easy task, see this discussion for details: http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address – maxhb Nov 23 '15 at 06:54
  • Here you can find a useful article to get all email address from string in java, you can modify it to use for PHP. https://handyopinion.com/utility-method-to-get-all-email-addresses-from-a-string-in-java/ – Asad Ali Choudhry Nov 10 '19 at 06:54
  • Why wasn't `filter_var_array($string,FILTER_VALIDATE_EMAIL)` proposed? – ina Dec 05 '20 at 06:32

10 Answers10

51

Try this

<?php 
    $string = 'Ruchika < ruchika@example.com >';
    $pattern = '/[a-z0-9_\-\+\.]+@[a-z0-9\-]+\.([a-z]{2,4})(?:\.[a-z]{2})?/i';
    preg_match_all($pattern, $string, $matches);
    var_dump($matches[0]);
?>

see demo here

Second method

<?php 
    $text = 'Ruchika < ruchika@example.com >';
    preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $text, $matches);
    print_r($matches[0]);
?>

See demo here

Ricardo Martins
  • 5,702
  • 3
  • 40
  • 59
Niranjan N Raju
  • 12,047
  • 4
  • 22
  • 41
  • 3
    FYI - only works on basic domain names such as gmail.com. It will work on an email address from a mail sub-domain name such as email@mg.website.com – Dylan Glockler May 23 '17 at 22:27
  • The first version (/[a-z0-9_\-\+\.]+@[a-z0-9\-]+\.([a-z]{2,4})(?:\.[a-z]{2})?/i) omits "foo" from "foo.bar@example.com"! – Henno Jun 28 '19 at 05:50
  • 1
    I think this Regular expression is better to find email. "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" Details are here https://handyopinion.com/utility-method-to-get-all-email-addresses-from-a-string-in-java/ – Asad Ali Choudhry Nov 10 '19 at 06:56
  • This pattern (specifically the 2nd pattern) is not refined. `.` does not need to be escaped within a character class. `[_a-zA-Z0-9]` is the same as `\w`; regardless, the `i` pattern flag is pointless. The pattern boils down to `/[\w.-]+@[\w.-]+/`, but this does not cover ranges of valid email addresses. The same for the first pattern. The `+` in the character class doesn't need to be escaped. It's simply too under-developed to use in a professional environment. – mickmackusa Nov 26 '21 at 02:11
  • Yeah the second method will find "blah@gmail.com." ... including the ending period. – designosis Jan 24 '22 at 01:04
40

Parsing e-mail addresses is an insane work and would result in a very complicated regular expression. For example, consider this official regular expression to catch an e-mail address: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html

Amazing right?

Instead, there is a standard php function to do this called mailparse_rfc822_parse_addresses() and documented here.

It takes a string as argument and returns an array of associative array with keys display, address and is_group.

So,

$to = 'Wez Furlong <wez@example.com>, doe@example.com';
var_dump(mailparse_rfc822_parse_addresses($to));

would yield:

array(2) {
  [0]=>
  array(3) {
    ["display"]=>
    string(11) "Wez Furlong"
    ["address"]=>
    string(15) "wez@example.com"
    ["is_group"]=>
    bool(false)
  }
  [1]=>
  array(3) {
    ["display"]=>
    string(15) "doe@example.com"
    ["address"]=>
    string(15) "doe@example.com"
    ["is_group"]=>
    bool(false)
  }
}
Jacques
  • 991
  • 1
  • 12
  • 15
  • 2
    This is a great way to grab email addresses from a list of email addresses, but it does not work quite so well on email addresses in random free text... – ftrotter Oct 21 '19 at 09:11
  • 3
    @ftrotter that's right, and it is not intended to do so and that's not what the OP asked either. It is intended to extract e-mail address from a list like the ones found in mail envelops. – Jacques Oct 22 '19 at 10:18
  • 1
    This is the only correct answer. Surprised that out of 14 answers only one guy got it right. – I wrestled a bear once. Aug 17 '21 at 16:45
9

try this code.

<?php

function extract_emails_from($string){
  preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $string, $matches);
  return $matches[0];
}

$text = "blah blah blah blah blah blah email2@address.com";

$emails = extract_emails_from($text);

print(implode("\n", $emails));

?>

This will work.

Thanks.

Priya Rajaram
  • 340
  • 2
  • 14
  • Thank you. This *correctly* handles email addresses with periods. Ex: bob.smith@example.co.whatever.com. Some of the other solutions listed do not. – Richard Nov 29 '20 at 03:41
  • GIven "blah blah someone@place.com. blah blah" ... this function will return `someone@place.com.` ... with the ending period, breaking the email. – designosis Jan 24 '22 at 01:05
7

This is based on Niranjan's response, assuming you have the input email enclosed within < and > characters). Instead of using a regular expression to grab the email address, here I get the text part between the < and > characters. Otherwise, I use the string to get the entire email. Of course, I didn't make any validation on the email address, this will depend on your scenario.

<?php 
    $string = 'Ruchika <ruchika@example.com>';
    $pattern = '/<(.*?)>/i';

    preg_match_all($pattern, $string, $matches);
    var_dump($matches);
    $email = $matches[1][0] ?? $string;
    echo $email;
?>

Here is a forked demo.

Of course, if my assumption isn't correct, then this approach will fail. But based on your input, I believe you wanted to extract emails enclosed within < and > chars.

julianm
  • 869
  • 8
  • 13
  • The 'i' modifier is ambiguous within the regex, since there is no alphabet characters in the given pattern. – Oliver Tappin Apr 13 '21 at 15:13
  • If you are going to lazily match to the first occurring `>`, then why not use a greedy negated characters class for better performance? (`[^>]+`) – mickmackusa Nov 26 '21 at 02:15
1

This function extract all email from a string and return it in an array.

function extract_emails_from($string){
    preg_match_all( '/([\w+\.]*\w+@[\w+\.]*\w+[\w+\-\w+]*\.\w+)/is', $string, $matches );
    return $matches[0];
};
Giuseppe Canale
  • 470
  • 7
  • 15
0

This works great and it's minimal:

$email = strpos($from, '<') ? substr($from, strpos($from, '<') + 1, -1) : $from

-1

use (my) function getEmailArrayFromString to easily extract email adresses from a given string.

<?php

function getEmailArrayFromString($sString = '')
{
    $sPattern = '/[\._\p{L}\p{M}\p{N}-]+@[\._\p{L}\p{M}\p{N}-]+/u';
    preg_match_all($sPattern, $sString, $aMatch);
    $aMatch = array_keys(array_flip(current($aMatch)));

    return $aMatch;
}

// Example
$sString = 'foo@example.com XXX bar@example.com XXX <baz@example.com>';

$aEmail = getEmailArrayFromString($sString);

/**
* array(3) {
    [0]=>
        string(15) "foo@example.com"
    [1]=>
        string(15) "bar@example.com"
    [2]=>
        string(15) "baz@example.com"
    }
*/
var_dump($aEmail);
-1

Based on Priya Rajaram's code, I have optimised the function a little more so that each email address only appears once.

If, for example, an HTML document is parsed, you usually get everything twice, because the mail address is also used in the mailto link, too.

function extract_emails_from($string){
  preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $string, $matches);
  return array_values(array_unique($matches[0]));
}
Marco
  • 3,470
  • 4
  • 23
  • 35
  • If you want to show researchers how to remove duplicates and re-index an array, please find a more appropriate page. You could have also, just added `array_values(array_unique($matches[0]))` as a comment under Priya's answer. – mickmackusa Nov 26 '21 at 02:22
-2

This will work even on subdomains. It extracts all emails from text.

$marches[0] has all emails.

$pattern = "/[a-zA-Z0-9-_]{1,}@[a-zA-Z0-9-_]{1,}(.[a-zA-Z]{1,}){1,}/";
preg_match_all ($pattern , $string, $matches);
print_r($matches);

$marches[0] has all emails.

Array
(
    [0] => Array
        (
            [0] => clotdesormakilgehr@prednisonecy.com
            [1] => **********@******.co.za.com
            [2] => clotdesormakilgehr@prednisonecy.com
            [3] => clotdesormakilgehr@prednisonecy.mikedomain.com
            [4] => clotdesormakilgehr@prednisonecy.com
        )

    [1] => Array
        (
            [0] => .com
            [1] => .com
            [2] => .com
            [3] => .com
            [4] => .com
        )

)
katwekibs
  • 1,342
  • 14
  • 17
  • Sorry, but as-is, this fails if the email address has a period in it. Ex: bob.smith@example.com. It returns only "smith@example.com" – Richard Nov 29 '20 at 03:39
-2

A relatively straight forward approach is to use PHP built-in methods for splitting texts into words and validating E-Mails:

function fetchEmails($text) {
    $words = str_word_count($text, 1, '.@-_1234567890');
    return array_filter($words, function($word) {return filter_var($word, FILTER_VALIDATE_EMAIL);});
}

Will return the e-mail addresses within the text variable.

klawipo
  • 153
  • 5
  • doesn't work when the email has non alphabetical chars such as digits – Amaynut Dec 09 '20 at 21:36
  • Well it worked not with numbers, I corrected this. You can add the missing characters allowed in e-mail by addresses, but this will match most real-world email addresses. – klawipo Dec 18 '20 at 11:02