Posted By

ginoplusio on 12/27/09


Tagged

mail validation checker phpsmtpmail validationemail


Versions (?)

Who likes this?

5 people have marked this snippet as a favorite

kamakazuu
ginoplusio
wireplay
robertstefan
Priestd09


Validate emails with SMTP and PHP


 / Published in: PHP
 

URL: http://www.barattalo.it/2009/12/27/validate-email-with-smtp/

This function validate a mail address in a smart way: if the address to validate has a correct syntax (checked with regular expression), it tries to connect to the mx server of the address. This means that the program have to use the smtp protocol to talk with each mx server registered in the dns for that domain address. When a connection with an mx server is established, the program presents himself with the $probeaddress (if no probeaddress is specified it will use the SERVER_ADMIN setting of the php.ini file) and asks to send a mail message to the address to validate. If the server responds that the destination mailbox is ok, it stops and return ok value, else it gives you the bad answer of the mail server.

  1. function validateEmailSmtp($email, $probe_address="", $debug=false) {
  2. # --------------------------------
  3. # function to validate email address
  4. # through a smtp connection with the
  5. # mail server.
  6. # by Giulio Pons
  7. # http://www.barattalo.it
  8. # --------------------------------
  9. $output = "";
  10. # --------------------------------
  11. # Check syntax with regular expression
  12. # --------------------------------
  13. if (!$probe_address) $probe_address = $_SERVER["SERVER_ADMIN"];
  14. if (preg_match('/^([a-zA-Z0-9\._\+-]+)\@((\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,7}|[0-9]{1,3})(\]?))$/', $email, $matches)) {
  15. $user = $matches[1];
  16. $domain = $matches[2];
  17. # --------------------------------
  18. # Check availability of DNS MX records
  19. # --------------------------------
  20. if (function_exists('checkdnsrr')) {
  21. # --------------------------------
  22. # Construct array of available mailservers
  23. # --------------------------------
  24. if(getmxrr($domain, $mxhosts, $mxweight)) {
  25. for($i=0;$i<count($mxhosts);$i++){
  26. $mxs[$mxhosts[$i]] = $mxweight[$i];
  27. }
  28. asort($mxs);
  29. $mailers = array_keys($mxs);
  30. } elseif(checkdnsrr($domain, 'A')) {
  31. $mailers[0] = gethostbyname($domain);
  32. } else {
  33. $mailers=array();
  34. }
  35. $total = count($mailers);
  36. # --------------------------------
  37. # Query each mailserver
  38. # --------------------------------
  39. if($total > 0) {
  40. # --------------------------------
  41. # Check if mailers accept mail
  42. # --------------------------------
  43. for($n=0; $n < $total; $n++) {
  44. # --------------------------------
  45. # Check if socket can be opened
  46. # --------------------------------
  47. if($debug) { $output .= "Checking server $mailers[$n]...\n";}
  48. $connect_timeout = 2;
  49. $errno = 0;
  50. $errstr = 0;
  51. # --------------------------------
  52. # controllo probe address
  53. # --------------------------------
  54. if (preg_match('/^([a-zA-Z0-9\._\+-]+)\@((\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,7}|[0-9]{1,3})(\]?))$/', $probe_address,$fakematches)) {
  55. $probe_domain = str_replace("@","",strstr($probe_address, '@'));
  56.  
  57. # --------------------------------
  58. # Try to open up socket
  59. # --------------------------------
  60. if($sock = @fsockopen($mailers[$n], 25, $errno , $errstr, $connect_timeout)) {
  61. $response = fgets($sock);
  62. if($debug) {$output .= "Opening up socket to $mailers[$n]... Success!\n";}
  63. stream_set_timeout($sock, 5);
  64. $meta = stream_get_meta_data($sock);
  65. if($debug) { $output .= "$mailers[$n] replied: $response\n";}
  66. # --------------------------------
  67. # Be sure to set this correctly!
  68. # --------------------------------
  69. $cmds = array(
  70. "HELO $probe_domain",
  71. "MAIL FROM: <$probe_address>",
  72. "RCPT TO: <$email>",
  73. "QUIT",
  74. );
  75. # --------------------------------
  76. # Hard error on connect -> break out
  77. # --------------------------------
  78. if(!$meta['timed_out'] && !preg_match('/^2\d\d[ -]/', $response)) {
  79. $codice = trim(substr(trim($response),0,3));
  80. if ($codice=="421") {
  81. //421 #4.4.5 Too many connections to this host.
  82. $error = $response;
  83. break;
  84. } else {
  85. if($response=="" || $codice=="") {
  86. //c'è stato un errore ma la situazione è poco chiara
  87. $codice = "0";
  88. }
  89. $error = "Error: $mailers[$n] said: $response\n";
  90. break;
  91. }
  92. break;
  93. }
  94. foreach($cmds as $cmd) {
  95. $before = microtime(true);
  96. fputs($sock, "$cmd
  97. ");
  98. $response = fgets($sock, 4096);
  99. $t = 1000*(microtime(true)-$before);
  100. if($debug) {$output .= "$cmd\n$response" . "(" . sprintf('%.2f', $t) . " ms)\n";}
  101. if(!$meta['timed_out'] && preg_match('/^5\d\d[ -]/', $response)) {
  102. $codice = trim(substr(trim($response),0,3));
  103. if ($codice<>"552") {
  104. $error = "Unverified address: $mailers[$n] said: $response";
  105. break 2;
  106. } else {
  107. $error = $response;
  108. break 2;
  109. }
  110. # --------------------------------
  111. // il 554 e il 552 sono quota
  112. // 554 Recipient address rejected: mailbox overquota
  113. // 552 RCPT TO: Mailbox disk quota exceeded
  114. # --------------------------------
  115. }
  116. }
  117. fclose($sock);
  118. if($debug) { $output .= "Succesful communication with $mailers[$n], no hard errors, assuming OK\n";}
  119. break;
  120. } elseif($n == $total-1) {
  121. $error = "None of the mailservers listed for $domain could be contacted";
  122. $codice = "0";
  123. }
  124. } else {
  125. $error = "Il probe_address non è una mail valida.";
  126. }
  127. }
  128. } elseif($total <= 0) {
  129. $error = "No usable DNS records found for domain '$domain'";
  130. }
  131. }
  132. } else {
  133. $error = 'Address syntax not correct';
  134. }
  135. if($debug) {
  136. }
  137. if(!isset($codice)) {$codice="n.a.";}
  138. if(isset($error)) return array($error,$codice); else return true;
  139. }

Report this snippet  

You need to login to post a comment.