PHP: getmxrr - Manual

downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

getprotobyname gethostbynamel

Last updated: Fri, 26 Jan 2007

view this page in

# getmxrr

(PHP 3, PHP 4, PHP 5)

getmxrr -- Get MX records corresponding to a given Internet host name

## Description

bool getmxrr ( string hostname, array &mxhosts [, array &weight] )

Searches DNS for MX records corresponding to `hostname`. Returns `TRUE` if any records are found; returns `FALSE` if no records were found or if an error occurred.

A list of the MX records found is placed into the array `mxhosts`. If the `weight` array is given, it will be filled with the weight information gathered.

> Замечание: This function should not be used for the purposes of address verification. Only the mailexchangers found in DNS are returned, however, according to RFC 2821 when no mail exchangers are listed, `hostname` itself should be used as the only mail exchanger with a priority of `0`.

> Замечание: This function is not implemented on Windows platforms. Try the PEAR class Net_DNS.

See also checkdnsrr(), dns_get_record(), gethostbyname(), gethostbynamel(), gethostbyaddr(), and the `named(8)` manual page.

add a note User Contributed Notes
getmxrr
tomhutter at web dot de
20-Oct-2006 12:50
`Leonardt's code fails with multiple mx records with the same wight. You can easily change this by switching keys and values in the mxs array:
for($i=0;$i<count($mx_records);$i++){
$mxs[$mx_records[$i]] = $mx_weight[$i];
}
arsort ($mxs );
reset ($mxs);
while (list ($mx_host, $mx_weight) = each ($mxs) ) {
cheers
Tom`
php dot net at oitc dot com
14-Oct-2006 05:28
`This function has some strange side effects when dealing with aliases...
My function:
if (getmxrr($fqdn, $mx_records, $mx_weight)) {
// copy mx records and weight into array $mxs
// ignore multiple mx's at the same weight
for ($i = 0; $i < count($mx_records); $i++) {
$mxs[$mx_weight[$i]] = $mx_records[$i];
}
// sort array mxs to get servers with highest priority
ksort ($mxs, SORT_NUMERIC);
reset ($mxs);
} else {
// No MX so use A
$mxs[0]= $fqdn;
}
fails because a $fqdn containing an alias returns a true yet on return both $mx_records and $mx_weight contain nothing!
The solution until this gets fixed is to replace if (getmxrr($fqdn, $mx_records, $mx_weight)) with
// Handle aliases etc.
if ($result = getmxrr($fqdn, $mx_records, $mx_weight)) {
if(!isset($mx_records) || (count($mx_records) == 0)) $result = false;
}
// Process MXs
if ($result) {
Hope this helps others.... Tom`
glen dot finch at 4siteinternet dot com
09-Oct-2006 08:47
`Lennart Poot's example code (07-Apr-2006 08:23) will not work correctly. When looping through the MX hosts and weights to put them in 1 array he has:
$mxs[$mx_weight[$i]]=$mx_records[$i];
This will not work -> $mxs[$mx_weight[$i]]
For example testing an email at "hotmail.com" should return 4 MX hosts all weighted 5.
doing a quick print_r($mxs) with a hotmail address after the "for loop" will show 1 record as follows:
Array ( [5] => mx1.hotmail.com )
Not the 4 MX hosts as expected.`
MagicalTux at ooKoo dot org
24-Sep-2006 07:59
`If you want to use getmxrr on windows, be careful as choward AT fast DOT net DOT NO SPAM PLZ's function has a security flaw.
It passes its argument to an external command without escaping it. If you don't validate the input, someone may manage to run nasty things on your system.
Here's a fixed version (just added escapeshellarg())
<?php
function getmxrr($hostname, &$mxhosts)
{
$mxhosts = array();
exec('%SYSTEMDIRECTORY%\\nslookup.exe -q=mx '.escapeshellarg($hostname), $result_arr);
foreach($result_arr as $line)
{
if (preg_match("/.*mail exchanger = (.*)/", $line, $matches))
$mxhosts[] = $matches[1];
}
return( count($mxhosts) > 0 );
}//--End of workaround
//test..
getmxrr('yahoo.com', $mxhosts);
print_r($mxhosts);
?>
This way you'll avoid a lot of nasty things ;)`
Lennart Poot(www.twing.nl)
07-Apr-2006 12:23
`This script validates an e-mail adress using getmxrr and fsockopen
1. it validates the syntax of the address.
2. get MX records by hostname
3. connect mail server and verify mailbox(using smtp command RCTP TO:<email>)
When the function "validate_email([email])" fails connecting the mail server with the highest priority in the MX record it will continue with the second mail server and so on..
The function "validate_email([email])" returns 0 when it failes one the 3 steps above, it will return 1 otherwise
Grtz Lennart Poot
<?
function validate_email($email){
$mailparts=explode("@",$email);
$hostname = $mailparts[1];
// validate email address syntax
$exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";
$b_valid_syntax=eregi($exp, $email);
// get mx addresses by getmxrr
$b_mx_avail=getmxrr( $hostname, $mx_records, $mx_weight );
$b_server_found=0;
if($b_valid_syntax && $b_mx_avail){
// copy mx records and weight into array $mxs
$mxs=array();
for($i=0;$i<count($mx_records);$i++){
$mxs[$mx_weight[$i]]=$mx_records[$i];
}
// sort array mxs to get servers with highest prio
ksort ($mxs, SORT_NUMERIC );
reset ($mxs);
while (list ($mx_weight, $mx_host) = each ($mxs) ) {
if($b_server_found == 0){
//try connection on port 25
$fp = @fsockopen($mx_host,25, $errno, $errstr, 2);
if($fp){
$ms_resp="";
// say HELO to mailserver
$ms_resp.=send_command($fp, "HELO microsoft.com");
// initialize sending mail
$ms_resp.=send_command($fp, "MAIL FROM:<support@microsoft.com>");
// try receipent address, will return 250 when ok..
$rcpt_text=send_command($fp, "RCPT TO:<".$email.">");
$ms_resp.=$rcpt_text;
if(substr( $rcpt_text, 0, 3) == "250")
$b_server_found=1;
// quit mail server connection
$ms_resp.=send_command($fp, "QUIT");
fclose($fp);
}
}
}
}
return $b_server_found;
}
function send_command($fp, $out){
fwrite($fp, $out . "\r\n");
return get_data($fp);
}
function get_data($fp){
$s="";
stream_set_timeout($fp, 2);
for($i=0;$i<2;$i++)
$s.=fgets($fp, 1024);
return $s;
}
// support windows platforms
if (!function_exists ('getmxrr') ) {
function getmxrr($hostname, &$mxhosts, &$mxweight) {
if (!is_array ($mxhosts) ) {
$mxhosts = array ();
}
if (!empty ($hostname) ) {
$output = "";
@exec ("nslookup.exe -type=MX $hostname.", $output);
$imx=-1;
foreach ($output as $line) {
$imx++;
$parts = "";
if (preg_match ("/^$hostname\tMX preference = ([0-9]+), mail exchanger = (.*)$/", $line, $parts) ) {
$mxweight[$imx] = $parts[1];
$mxhosts[$imx] = $parts[2];
}
}
return ($imx!=-1);
}
return false;
}
}
?>`
jeff at pzenix dot com
08-Mar-2006 09:58
`I should point out that the below example won't work with some domains (.co.uk, .org.uk, .net.uk for example) because it assumes (possibly incorrectly) that the format is [ DOMAIN ].[ EXT ].`
off at NOSPAM dot abwesend dot de
11-Feb-2006 07:18
`Concerning the message by 'rolf at rowi dot net' (do a check on a address containing a subdomain) we could use:
$email = 'abc@etpc01.trier.fh-rpl.de';
$strDot = '.';
$strAfterAt = substr(strstr($email, '@'), 1);
$chunks = explode($strDot, $strAfterAt);
$cntChunks = count($chunks) - 1;
$strDomain = $chunks[($cntChunks-1)] . $strDot . $chunks[$cntChunks];
if (!getmxrr( $strDomain, $mxhosts )) {
echo 'Mailserver not found';
}
// $strDomain is set to 'fh-rpl.de';`
31-Aug-2005 08:16
`nice function for validating email-adresses! Take care on "register globals" paramter.
http://www.zend.com/zend/spotlight/ev12apr.php`
richard dot quadling at bandvulc dot co dot uk
25-May-2005 02:04
`Windows alternative for getmxrr without the need for PEAR.
define('DEFAULT_GATEWAY', 'nnn.nnn.nnn.nnn');
function raqgetmxrr($sHostName, &$aMXHosts, &$aWeights = NULL)
{
/*
This function is a replacement for the missing Windows function getmxrr.
The parameters are the same as those for the normal getmxrr function.
The steps this function takes are :
1 - Use NSLOOKUP.EXE to get the MX records for the supplied Host.
2 - Use regular expressions to extract the mail servers and the preference.
3 - Sort the results by preference.
4 - Set the return arrays.
5 - Return true or false.
*/
$sNSLookup = shell_exec("nslookup -q=mx {$sHostName} DEFAULT_GATEWAY 2>nul");
preg_match_all("'^.*MX preference = (\d{1,10}), mail exchanger = (.*)$'simU", $sNSLookup, $aMXMatches);
if (count($aMXMatches[2]) > 0)
{
array_multisort($aMXMatches[1], $aMXMatches[2]);
$aMXHosts = $aMXMatches[2];
if (!is_null($aWeights))
{
$aWeights = $aMXMatches[1];
}
return True;
}
else
{
return False;
}
}
You will need to know your default gateway (either it's IP address or its name).
To do this, run the program IPCONFIG /ALL at a cmd prompt and look for the Default Gateway.
Then replace the 'nnn.nnn.nnn.nnn' with the address.
Richard.`
josh/endquote/com
10-Feb-2005 12:56
`See this article for a validation tutorial that uses this function and more:
http://www.devshed.com/c/a/PHP/Email-Address-Verification-with-PHP/`
rune dot heggtveit at devzone dot progative dot com
23-Jan-2005 01:02
`An other way to do mx-lookup on a windows platform.
Rewrote this from an other class i wrote for DNS lookup - so it might be a bit messy - but hope you get the idea.
Big thanks to the rfc community.
<?php
class mxlookup
{
var $dns_socket = NULL;
var $QNAME = "";
var $dns_packet= NULL;
var $ANCOUNT = 0;
var $cIx = 0;
var $dns_repl_domain;
var $arrMX = array();
function mxlookup($domain, $dns="192.168.2.1")
{
$this->QNAME($domain);
$this->pack_dns_packet();
$dns_socket = fsockopen("udp://$dns", 53);
fwrite($dns_socket,$this->dns_packet,strlen($this->dns_packet));
$this->dns_reply = fread($dns_socket,1);
$bytes = stream_get_meta_data($dns_socket);
$this->dns_reply .= fread($dns_socket,$bytes['unread_bytes']);
fclose($dns_socket);
$this->cIx=6;
$this->ANCOUNT = $this->gord(2);
$this->cIx+=4;
$this->parse_data($this->dns_repl_domain);
$this->cIx+=7;
for($ic=1;$ic<=$this->ANCOUNT;$ic++)
{
$QTYPE = ord($this->gdi($this->cIx));
if($QTYPE!==15){print("[MX Record not returned]"); die();}
$this->cIx+=9;
$mxPref = ord($this->gdi($this->cIx));
$this->parse_data($curmx);
$this->arrMX[] = array("MX_Pref" => $mxPref, "MX" => $curmx);
$this->cIx+=3;
}
}
function parse_data(&$retval)
{
$arName = array();
$byte = ord($this->gdi($this->cIx));
while($byte!==0)
{
if($byte==192) //compressed
{
$tmpIx = $this->cIx;
$this->cIx = ord($this->gdi($cIx));
$tmpName = $retval;
$this->parse_data($tmpName);
$retval=$retval.".".$tmpName;
$this->cIx = $tmpIx+1;
return;
}
$retval="";
$bCount = $byte;
for($b=0;$b<$bCount;$b++)
{
$retval .= $this->gdi($this->cIx);
}
$arName[]=$retval;
$byte = ord($this->gdi($this->cIx));
}
$retval=join(".",$arName);
}
function gdi(&$cIx,$bytes=1)
{
$this->cIx++;
return(substr($this->dns_reply, $this->cIx-1, $bytes));
}
function QNAME($domain)
{
$dot_pos = 0; $temp = "";
while($dot_pos=strpos($domain,"."))
{
$temp = substr($domain,0,$dot_pos);
$domain = substr($domain,$dot_pos+1);
$this->QNAME .= chr(strlen($temp)).$temp;
}
$this->QNAME .= chr(strlen($domain)).$domain.chr(0);
}
function gord($ln=1)
{
$reply="";
for($i=0;$i<$ln;$i++){
$reply.=ord(substr($this->dns_reply,$this->cIx,1));
$this->cIx++;
}
return $reply;
}
function pack_dns_packet()
{
$this->dns_packet = chr(0).chr(1).
chr(1).chr(0).
chr(0).chr(1).
chr(0).chr(0).
chr(0).chr(0).
chr(0).chr(0).
$this->QNAME.
chr(0).chr(15).
chr(0).chr(1);
}
}
?>
<?php
/* Exampe of use: */
$mx = new mxlookup("php.net");
print $mx->ANCOUNT." MX Records\n";
print "Records returned for ".$mx->dns_repl_domain.":\n<pre>";
print_r($mx->arrMX);
?>
Return:
02 MX Records Records returned for php.net:
Array
(
[0] => Array
(
[MX_Pref] => 15
[MX] => smtp.osuosl.org
)
[1] => Array
(
[MX_Pref] => 5
[MX] => osu1.php.net
)
)`
rolf at rowi dot net
21-Jan-2005 06:36
`Be aware that not just user@example.com ist a valid address, also user@subnet.example.com is valid (but maybe less common). Just got into trouble with this check...
Rolf`
siclawrence at gmail dot com
04-Jan-2005 06:43
`This code replicates online tools that let you check if an email address is valid. First it checks if the email format is correct, then looks up and prints the mx records. All nicely formatted with fancy words that in the end prints whether the email address valid or invalid.
<?php
$email = "email@domain.com";
print("Checking: $email<br>");
if (eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)+$", $email)) {
print("Format Test: PASSED<br>");
print("Online host verification Test...<br><br>");
print("MX Records for: $email<br>");
list($alias, $domain) = split("@", $email);
if (checkdnsrr($domain, "MX")) {
getmxrr($domain, $mxhosts);
foreach($mxhosts as $mxKey => $mxValue){
print("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mxValue<br>");
}
print("Online host verification Test: PASSED<br><br>");
print("Email Status: VALID");
} else {
print("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No records found.<br>");
print("Online host verification Test: FAILED<br><br>");
print("Email Status: INVALID");
}
} else {
print("Format Test: FAILED<br><br>");
print("Invalid email address provided.<br><br>");
print("Email Status: INVALID");
}
?>`
zorlac_man at hotmail dot com
14-May-2004 12:15
`For some reason this and the other DNS lookup functions seem to be really slow on my Linux box. I've checked several things and have no explanation.
As a work-around, I gave in and just used a system call to dig:
<?php
CheckMX("fakedomain.org");
CheckMX("hotmail.com");
function CheckMX($domain) {
exec("dig +short MX " . escapeshellarg($domain),$ips);
if($ips[0] == "") {
print "MX record found for $domain not found!\n";
return FALSE;
}
print "MX Record for $domain found\n";
return TRUE;
}
?>
Output:
MX record found for fakedomain.org not found!
MX Record for hotmail.com found
As someone else pointed out, it is prudent to check to see if the TLD has an IP address if the MX record is not found.`
ng4rrjanbiah at rediffmail dot com
26-Feb-2004 03:11
`Here is a better workaround for Windows platform. Tested on Windows XP. Highly impressed by "geoffbrisbine A T y a h o o DOT c o m"'s idea of nslookup usage.
<?php
function getmxrr($hostname, &$mxhosts)
{
$mxhosts = array();
exec('nslookup -type=mx '.$hostname, $result_arr);
foreach($result_arr as $line)
{
if (preg_match("/.*mail exchanger = (.*)/", $line, $matches))
$mxhosts[] = $matches[1];
}
return( count($mxhosts) > 0 );
}//--End of workaround
//test..
echo getmxrr('yahoo.com', $mxhosts);
print_r($mxhosts);
?>
HTH,
R. Rajesh Jeba Anbiah`
geoffbrisbine A T y a h o o DOT c o m
24-Sep-2002 09:39
`I was pretty disappointed that the Win32 build of PHP doesn't incorporate getmxrr so, since I'm a naive newbie, I decided to hack together my own (and I stress hack). This has been tested on Win 2000 and Win XP. There's no reason this shouldn't work on Win NT but it will not work on Win 9x (you need the nslookup command). It will finish with the array $mx that will be a multidimensional array with the MX preference, host name and ip address. You can do a print_r ( $mx ) to see what it looks like.
-----------------------------------------------
<?php
$command = "nslookup -type=mx yahoo.com";
exec ( $command, $result );
$i = 0;
while ( list ( $key, $value ) = each ( $result ) ) {
if ( strstr ( $value, "mail exchanger" ) ) { $nslookup[$i] = $value; $i++; }
}
while ( list ( $key, $value ) = each ( $nslookup ) ) {
$temp = explode ( " ", $value );
$mx[$key][0] = $temp[3];
$mx[$key][1] = $temp[7];
$mx[$key][2] = gethostbyname ( $temp[7] );
}
array_multisort ( $mx );
?>`
paul at start dot co dot uk
16-Jan-2001 12:48
`Prevent your dns server from 'creating' a valid host name by appending the local domain to incomplete emails by appending to the domain a trailing . both in the pattern match and mx checks:
if (eregi("^[0-9a-z_]([-_.]?[0-9a-z])*@[0-9a-z][-.0-9a-z]*\\.[a-z]{2,3}[.]?$", $string, $check)) {
$host = substr(strstr($check[0], '@'), 1).".";
if ( getmxrr($host, $validate_email_temp) )
return TRUE;
// THIS WILL CATCH DNSs THAT ARE NOT MX.
if(checkdnsrr($host,"ANY"))
return TRUE;
}
return FALSE;`
add a note
getprotobyname gethostbynamel

Last updated: Fri, 26 Jan 2007
show source | credits | stats | sitemap | contact | advertising | mirror sites
Copyright © 2001-2007 The PHP Group
All rights reserved.
This mirror generously provided by: Yahoo! Inc.
Last updated: Sat Mar 10 10:36:09 2007 PST