Non c'è motivo di scrivere a mano un'espressione regolare per controllare la validità di un indirizzo. filter_var lo fa già molto meglio delle espressioni regolari proposte nei messaggi precedenti:
Codice PHP:
filter_var($email, FILTER_VALIDATE_EMAIL);
Per "molto meglio", intendo dire che le espressioni regolari proposte non sono complete, ovvero funzionano con alcuni indirizzi email, ma possono produrre falsi negativi.
Volendo fare questo controllo con le espressioni regolari, il codice diventa di una lunghezza e complessità non banali:
Codice PHP:
function validate_email($email, $strict = true) {
$dot_string = $strict ?
'(?:[A-Za-z0-9!#$%&*+=?^_`{|}~\'\\/-]|(?<!\\.|\\A)\\.(?!\\.|@))' :
'(?:[A-Za-z0-9!#$%&*+=?^_`{|}~\'\\/.-])'
;
$quoted_string = '(?:\\\\\\\\|\\\\"|\\\\?[A-Za-z0-9!#$%&*+=?^_`{|}~()<>[\\]:;@,. \'\\/-])';
$ipv4_part = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
$ipv6_part = '(?:[A-fa-f0-9]{1,4})';
$fqdn_part = '(?:[A-Za-z](?:[A-Za-z0-9-]{0,61}?[A-Za-z0-9])?)';
$ipv4 = "(?:(?:{$ipv4_part}\\.){3}{$ipv4_part})";
$ipv6 = '(?:' .
"(?:(?:{$ipv6_part}:){7}(?:{$ipv6_part}|:))" . '|' .
"(?:(?:{$ipv6_part}:){6}(?::{$ipv6_part}|:{$ipv4}|:))" . '|' .
"(?:(?:{$ipv6_part}:){5}(?:(?::{$ipv6_part}){1,2}|:{$ipv4}|:))" . '|' .
"(?:(?:{$ipv6_part}:){4}(?:(?::{$ipv6_part}){1,3}|(?::{$ipv6_part})?:{$ipv4}|:))" . '|' .
"(?:(?:{$ipv6_part}:){3}(?:(?::{$ipv6_part}){1,4}|(?::{$ipv6_part}){0,2}:{$ipv4}|:))" . '|' .
"(?:(?:{$ipv6_part}:){2}(?:(?::{$ipv6_part}){1,5}|(?::{$ipv6_part}){0,3}:{$ipv4}|:))" . '|' .
"(?:(?:{$ipv6_part}:){1}(?:(?::{$ipv6_part}){1,6}|(?::{$ipv6_part}){0,4}:{$ipv4}|:))" . '|' .
"(?::(?:(?::{$ipv6_part}){1,7}|(?::{$ipv6_part}){0,5}:{$ipv4}|:))" .
')';
$fqdn = "(?:(?:{$fqdn_part}\\.)+?{$fqdn_part})";
$local = "({$dot_string}++|(\"){$quoted_string}++\")";
$domain = "({$fqdn}|\\[{$ipv4}]|\\[{$ipv6}]|\\[{$fqdn}])";
$pattern = "/\\A{$local}@{$domain}\\z/";
return preg_match($pattern, $email, $matches) &&
(
!empty($matches[2]) && !isset($matches[1][66]) && !isset($matches[0][256]) ||
!isset($matches[1][64]) && !isset($matches[0][254])
)
;
}
(fonte: filter_var)
Altra osservazione: hai modificato la funzione get_domain che avevo proposto, ma così facendo ora non è più necessariamente corretta:
Codice PHP:
function get_domain($address) {
return array_pop(explode('@', $address));
}
Ad esempio, passandole la stringa "@it@com" restituisce "com", mentre il comportamento atteso è la restituzione della stringa nulla "".
Nel tuo codice non è un gran problema (poiché effettui un controllo precedente, quindi l'errore viene comunque segnalato), ma questo rende la funzione non riutilizzabile.