ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


PHP Networking

by W.J. Gilmore
04/05/2001

I thought I'd take some time to acquaint you with yet another facet of my favorite language: the network-related functions. In this article I touch upon several cool applications, including how to use PHP to send e-mail, verify e-mail addresses, call operating system functions from within a script, and finally conclude the article with an explanation of how to query a WHOIS database for domain information.

The mail() function

Perhaps the most commonly used network-oriented function of the PHP repertoire is the mail() function. Quite simply, the mail() function is used to send e-mail to some destination. Take a moment to review its syntax:

bool mail(str to, str subject, str message [, str addl_headers])

The first input parameter, to, specifies the e-mail destination to which the e-mail is to be directed. The parameters subject and message specify the subject header and message body, respectively. Finally, the optional input parameter addl_headers specifies any optional information that is to appear within the message header. Although this final parameter is not required, I think that you'll find it particularly useful. Before I delve into a few examples, I'll take a moment to introduce the perfunctory configuration procedures, which simply involve the possible modification of one or more directives found within the php.ini file.

Using mail() on non-Windows platforms

By default, PHP's mail function uses the mail transfer agent sendmail to execute the delivery of e-mail sent via the mail() function. Therefore the php.ini file calls for the directive sendmail_path to be supplied with the path where sendmail can be found. Therefore, if sendmail can be found in the directory /usr/bin, you could set the directive as follows:

sendmail_path = "/usr/bin/sendmail -t -i"

You'll also want to ensure that the user running PHP (probably "nobody") is capable of executing sendmail.

Using mail() on Windows platforms

Since the Windows platform does not offer sendmail, which is the default mail transfer agent for the mail() function, an SMTP (Simple Mail Transfer Protocol, the protocol used for exchanging e-mails over the Internet) address is required. Furthermore, it's possible to specify the From: address directly within the php.ini file. The two directives responsible for Windows configuration are shown here:

SMTP = localhost                   ; for win32 only
sendmail_from = me@localhost.com   ; for win32 only

Once you have the configuration procedures out of the way, it's time to begin playing with the function. In the section "Using mail()," I'll present a few examples that will introduce you to the various nuances of this cool function.

Sendmail switches

Incidentally, it's also possible to supply options to sendmail. In fact, by default, sendmail is called as sendmail -t -i. The -i switch tells sendmail to ignore any lines consisting of just a single dot, which otherwise would cause sendmail to quit reading in the message. The -t switch will tell sendmail to search the message for To:, Cc:, and Bcc: lines, deleting the Bcc: line before sending the message. For a complete listing of sendmail options, check out the respective man page on your server.

Using mail()

As you have seen from the mail() syntax, it's a rather straightforward function. However, there are a few tricks that may not be initially apparent. Let's begin with a simple example:

Listing 1-1: Sending e-mail with mail()

<?
$email = "wjgilmore@hotmail.com";
$subject = "Check out O'Reillynet.com!";
$message = <<<Message
Dear Reader,
O'Reillynet.com's PHP section is really cool, offering insightful material from that< PHP Phanatic Urb LeJeune, among others. <a href="mailto:ccoleman@oreilly.com">Email us</a> should you have any suggestions or comments!";

Thanks!
The O'Reilly PHP crew
Message;

mail($email, $subject, $message);

?>

As you may have surmised, this short script will send an e-mail to wjgilmore@hotmail.com having the subject line of "Check out O'Reillynet.com!" and a message body specified by $message. Simple enough, right? However, those of you with particularly keen insight may be wondering who exactly the message will be attributed to, since it is not specified in the mail() function. In fact, it will be addressed as from the user the webserver is running as. For example, let's assume that O'Reillynet.com's server is running as user "Matilda." Thus the From: header would state: Matilda@oreillynet.com.

Chances are, you are going to want to customize this From: attribute, in addition to others such as Reply-To. This is where the addl_headers parameter comes into play. For example, assume that I would like the same message to be addressed from "The O'Reilly PHP Crew", and also use the Reply-To address of O'Reillynet's PHP editor, "ccoleman@oreilly.com." Therefore I would modify the call to the above mail() function as shown here:

<?
$headers = "From: The O'Reilly PHP Crew\nReply-To: ccoleman@oreilly.com";

mail($email, $subject, $message, $headers);
?>

There are two points worth noting regarding the addl_headers parameter. The first is that each header must be separated by a newline character, as is shown in the above example. The second point to make is that you are certainly not limited to using just From and Reply-To; you are free to use any and all available message headers. In summary, using the addl_headers parameter will result in a more organized and personalized e-mail.

A final note about mail()

It is important to keep in mind that the PHP mail() function is to be used for typical e-mail usage, and not for sending bulk mail. For those of you interested in sending bulk e-mail, I would suggest taking some time to review sendmail's switches carefully, and also check out several of the available bulk e-mail management packages like Majordomo or Listserv. Also check out www.faqs.org for a comprehensive comparison summary of the most popular e-mail management packages.

Verifying e-mail addresses

Although accumulating an e-mail-based newsletter subscriber base is a great way to keep in contact with your site community, it is also important to always keep in perspective one of the age-old adages of security: Never trust the user. This particularly applies to any situation in which you're forcing users to input e-mail addresses at some point within your web site. To illustrate, a common requirement for downloading software is the mandatory input of an e-mail address. Well, if you're anything like me, you probably enter something like "blah@blah.com." Of course, this is not my e-mail address, and it's likely that it's not even a valid one. While this is convenient for me since I typically don't want to be spammed by annoying organizations, it does not bode well for the organization that is storing thousands of potentially invalid e-mail addresses. Regardless of why you're storing e-mails, you may find it interesting to learn that PHP offers a rather trivial method for checking that e-mail addresses actually exist. Listing 1-2 illustrates just such a script.

Listing 1-2: Validating an e-mail's syntax and domain existence

<?

$email = "wjgilmore@hotmail.com";

function validate_email($email) {

// verify that $email meets requirements specified
// by regular expression. Store various parts in $pieces array.
if (eregi("^[a-zA-Z0-9._-]+
@
([a-zA-Z0-9._-]+)
\.
([a-zA-Z0-9_-]){2,3}$",
$email, $pieces)) :

// strstr() returns all of first parameter
// found after second parameter.
// substr() returns all of the string found
// between the first and second parameters.
// getmxrr() verifies that domain MX record exists.

if (getmxrr(substr(strstr($pieces[0], '@'), 1),
$mx_hosts) ) :
return TRUE;
endif;

endif;

return FALSE;

} // end validate_email()

// validate the email and output message accordingly.

if (validate_email($email)) :

print "email is valid!";

else :

print "bad email! baaaaad email!";

endif;

?>

Of course, instead of outputting a message at the end of the script, chances are you will want to perform some function such as adding the e-mail to a database table if it's valid, otherwise informing the user that the e-mail is invalid and reprompting for input.

The only PHP function used in this example that is directly related to networking per se is the function getmxrr(). This function searches for the mail exchanger record that specifies a domain's mail route. All MX records that are found are placed into the second input parameter: in the case of Listing 1-2, the variable $mx_hosts.

Keep in mind that this "foolproof" verification system is unlikely to deter those users who insist on not providing their real e-mail address. While the upside is that you are likely to store only "correct" e-mail addresses, this will not stop users from entering addresses that are not really theirs.

PHP's network functions

Of course, working with e-mail is just a small part of PHP's network-related functionality. PHP also offers several rather useful functions for retrieving information regarding servers and domains, a few of which I'll introduce here.

Let's assume for example that you wanted to write a script that translates the IP addresses found within Apache's server log into corresponding host names. Although I won't delve into the entire script, you may find it interesting to know that PHP offers a function that can readily perform these IP-to-host name translations. The function name is gethostbyaddr(). I'll illustrate its usage in Listing 1-3.

Listing 1-3: Translating an IP to its corresponding host name.

<?
$ip = "208.201.239.36";

$host = gethostbyaddr($ip);

print "The host name for $ip is $host.";
?>

The above example would yield the following output:

The host name for 208.201.239.36 is www.oreillynet.com.

Incidentally, you can use Apache's REMOTE_ADDR variable and the gethostbyaddr() function to obtain the current client's host name, as is shown in Listing 1-4:

Listing 1-4: Obtaining the client's host name

<?
$host = gethostbyaddr($REMOTE_ADDR);

print "Your host name is $host ($REMOTE_ADDR).";
?>

Listing 1-4 would output:

Your host name is www.oreillynet.com (208.201.239.36).

As is the case with many PHP functions, there is a procedure that performs the opposite translation, that is, host name to IP. This is accomplished with the function gethostbyname(). I'll illustrate its usage in Listing 1-5:

Listing 1-5: Obtaining a host name's corresponding IP address

<?
$host = www.oreillynet.com;

$ip = gethostbyname($host);

print "The IP address for the host name $host is $ip.";
?>

This would return the following output:

The IP address for the host name www.oreillynet.com is 208.201.239.36.

Other functions?

Incidentally, if PHP doesn't offer the particular network function that you require, you can probably call it via one of PHP's system execution functions. You can use these execution functions to call various commands located on the server operating system itself. For example, Listing 1-6 illustrates the use of PHP's exec() function to call the ping command, which sends a request for a server response. The exec() function will then store all output into the second input parameter, allowing for subsequent storage, display, or analysis of this data.

Listing 1-6: Using exec() to display ping output

<?
// ping some server five times and store output in array $output
exec("ping -c 5 www.oreillynet.com", $output);

// format each line of output
while (list(,$val) = each($output)) :
print "<pre>$val</pre>";
endwhile;
?>

Executing Listing 1-6 will result in output similar to the following:

Pinging www.oreillynet.com with 32 bytes of data:
Reply from www.oreillynet.com: bytes=32 time<10ms TTL=128
Reply from www.oreillynet.com: bytes=32 time=1ms TTL=128
Reply from www.oreillynet.com: bytes=32 time<10ms TTL=128
Reply from www.oreillynet.com: bytes=32 time<10ms TTL=128
Reply from www.oreillynet.com: bytes=32 time<10ms TTL=128
Ping statistics for www.oreillynet.com:
Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum =  1ms, Average =  0ms

The French PHP resource site www.phpinfo.net offers for download a very slick user logging application written in PHP. This is something you should definitely check out.

Note that I used the HTML "pre" tags to ensure that the output is displayed in some readable format. If these tags were omitted, the array contents would run together in a rather confusing jumble.

Of course, you're not limited to calling just ping with PHP's command functions; you can call any function available on the server.

Verifying domain availability

In today's continuing craze of gobbling up domain names, it becomes ever more necessary for ISPs to offer users the capability to easily verify whether or not a particular domain has already been taken. While on the surface this may seem like a complicated feature to implement, it's actually rather trivial. In this section, I'll demonstrate just how easy it is to incorporate this feature into your web site. First however, allow me to take a moment to explain the underlying mechanics of domain name storage and retrieval.

Although many think of the Internet as this chaotic mess of servers, all that we do today in terms of sending e-mail, surfing the Web, or using a search engine would be impossible if it weren't for organization starting on the highest levels. Operational centers known as NICs (Network Information Centers) are responsible for maintaining databases containing information regarding various networks and the domains and other data pertinent to these networks. Chances are you are familiar with NICs such as Network Solutions and Register.com. Of course, these NICs do not handle all domain extensions. You may need to modify Listing 1-7 (shown below) to be in accordance with the domain extensions that you'd like to search.

The databases that NICs administrate are typically known as WHOIS databases. Using PHP, it's easy to create a web interface that can interact with just such a database, querying it and subsequently displaying the data to the browser. Let's consider just such an interface, making use of the Internic WHOIS database to perform the query. First off, take a moment to try the demo, and then review the code in Listing 1-7.

Listing 1-7: A WHOIS interface (whois.php)

<?
// Has the HTML form been viewed yet?
if (! $seenform) :

$form = <<<Form
<form action="whois.php">
<input type="hidden" name="seenform" value="y" />
Domain name: (i.e. oreillynet.com)<br />
<input type="text" name="domain" value="" size="55" maxsize="65" /><br />
<input type="submit" value="Look it up!" />
</form>
Form;

echo $form;

// The form has been viewed; Process information.
else :

$fh = fsockopen("whois.internic.net", 43)
or die("Can't open WHOIS!");

if ($fh) :

fputs($fh, $domain);

while (! feof($fh)) :
echo fgets($fh, 1048);
endwhile;

fclose($fh);

endif;

endif;
?>

I'll assume that you are familiar with many of the functions used in Listing 1-7, save for perhaps fsockopen(). This function attempts to open a socket connection with some Internet domain. In the above example, I use fsockopen() to open a connection on hostname "whois.internic.net" on port 43.

I'd also like to note that Listing 1-7 is for demonstration purposes only. Some NICs restrict usage of their WHOIS database. Therefore, if you're interested in integrating this type of functionality into your site, please check with the NIC before doing so.

Conclusion

This article touched upon networking as it relates to the PHP scripting language. Quite a few topics were touched upon, including PHP's mail() function, bulk-e-mail software, e-mail validation, IP translation, PHP's system functions, and finally, verifying domain availablity via PHP. Hopefully I've provided you with some insight as to how to begin exploiting PHP's vast set of networking capabilities for your own purposes.

W.J. Gilmore has been developing PHP applications since 1997, and is frequently published on the subject within some of the Web's most popular development sites. He is the author of 'A Programmer's Introduction to PHP 4.0' (January 2001, Apress), and is the Assistant Editorial Director of Web and Open Source Technologies at Apress.


Return to the PHP DevCenter.

Copyright © 2009 O'Reilly Media, Inc.