Category: "LAMP"

Commandline PHP emailer

A nice commandline PHP emailer (can be adapted for sites), derived primarily from code at http://php.net.

Worthy of note:

  • Use of $HOSTNAME to get the name of the host. This is good for commandline when the $_SERVER variables aren’t available.
  • Separate text and HTML source files, normally, text would be derived from HTML with strip_tags.

<?php

if ($argc < 4)
die('Usage: <destination email address> <text file> <html file>'."\n");

$sHost=trim(shell_exec('echo $HOSTNAME'));
$fromname='no-reply';
$fromaddress='no-reply@'.$sHost;

$sTo=$argv[1];
$sTextFile=$argv[2];
$sHTMLFile=$argv[3];

$boundary='=_'.time();

$plain=file_get_contents($sTextFile);

$html=file_get_contents($sHTMLFile);

/* Courtesy of: http://www.php.net/manual/en/ref.mail.php#77405 - Modified slightly */

$eol="\r\n";
$mime_boundary=md5(time());

# Common Headers
$headers .= "From: ".$fromname."<".$fromaddress.">".$eol;
$headers .= "Reply-To: ".$fromname."<".$fromaddress.">".$eol;
$headers .= "Return-Path: ".$fromname."<".$fromaddress.">".$eol; // these two to set reply address
$headers .= "Message-ID: <".time()."-".$fromaddress.">".$eol;
$headers .= "X-Mailer: PHP v".phpversion().$eol; // These two to help avoid spam-filters

# Boundry for marking the split & Multitype Headers
$headers .= 'MIME-Version: 1.0'.$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"".$mime_boundary."\"".$eol.$eol;

# Open the first part of the mail
$msg = "--".$mime_boundary.$eol;

$htmlalt_mime_boundary = $mime_boundary."_htmlalt"; //we must define a different MIME boundary for this section
# Setup for text OR html -
$msg .= "Content-Type: multipart/alternative; boundary=\"".$htmlalt_mime_boundary."\"".$eol.$eol;

# Text Version
$msg .= "--".$htmlalt_mime_boundary.$eol;
$msg .= "Content-Type: text/plain; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
# $msg .= strip_tags(str_replace("<br>", "\n", substr($body, (strpos($body, "<body>")+6)))).$eol.$eol;
$msg .=$plain.$eol.$eol;

# HTML Version
$msg .= "--".$htmlalt_mime_boundary.$eol;
$msg .= "Content-Type: text/html; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$msg .= $html.$eol.$eol;

//close the html/plain text alternate portion
$msg .= "--".$htmlalt_mime_boundary."--".$eol.$eol;
# Finished
$msg .= "--".$mime_boundary."--".$eol.$eol; // finish with two eol's for better security. see Injection.

# SEND THE EMAIL
$mail_sent = mail($sTo, "Test From $sHost", $msg, $headers);

?>

Risks of HTML emails: http://www.mailchimp.com/resources/top10_html_email_mistakes.phtml

Recommending testing prior to production release
Receipt of emails on all major email clients
http://fingerprintapp.com/email-client-stats

Cleaning up after a hack

grep -rl MultiViews *  | sed  "s/\(.*\)/chown user:group \1/" > chown_multi
grep -rl bacjdzzazbzceh * | sed  "s/\(.*\)/chown user:group \1/" > chown_bacj
grep -rl MultiViews *  | sed  "s/\(.*\)/rm -f \1/" > rm_multi
grep -rl bacjdzzazbzceh * | sed  "s/\(.*\)/rm -f \1/" > rm_bacj

If you don't have root privileges on a server and need to clean up after a hack, your hosting company may be willing to change the ownership of the files so you can delete them.

You can also try to use

<?php system('./rm_multi'); ?>.

OOP Web

In virtually every web application - performance should take precedence over everything.

PHP (and many other languages) are interpretive. The code is read over and over.

  • Organize the files such that the most commonly used code is first.
  • Keep files small.
  • Use a good architecture.
  • Don’t read data or access information that won’t be used. If it won’t go to the client, on every request, don’t read it.
  • Validate on the client side first, and don’t send the data to the server if it isn’t valid.
  • Perform quick validation and escaping to protect the server on the server side.
  • Cache files on the client whenever possible.
  • Cache information on the server, use session variables for anything that will be used on every request. Consider storing ACL data in a session variable, but be aware of security risks.
  • Be aware of PHP best practices, and the impacts of double-quoted strings.

preg_replace trim vs. trim

Regular expressions incur a significant amount of overhead. If there is a suitable PHP function, it should always be used before coding a regular expression.

<?php

$sWord = '   TestString    ';

/* Time preg_replace trim double quotes */
$fStartPreg=microtime(true);
$sPreg=preg_replace("/^\s+|\s+$/", "", $sWord);
$fEndPreg=microtime(true);

/* Time preg_replace trim single quotes */
$fStartPregSng=microtime(true);
$sPreg=preg_replace('/^\s+|\s+$/', '', $sWord);
$fEndPregSng=microtime(true);

/* Time trim */
$fStartTrim=microtime(true);
$sTrim=trim($sWord);
$fEndTrim=microtime(true);

/* Calculate elapsed times */
$fPregElapsed=$fEndPreg-$fStartPreg;
$fPregElapsedSng=$fEndPregSng-$fStartPregSng;
$fTrimElapsed=$fEndTrim-$fStartTrim;

/* Display output */
echo '<html>';
echo '<pre>';
echo htmlentities(file_get_contents('timetest.php'));
echo "\n\n";
echo '$sWord: -'.$sWord."-\n";
echo '$sPreg: -'.$sPreg."-\n";
echo '$sTrim: -'.$sTrim."-\n";
printf("preg_replace:\t%f<br />",$fPregElapsed);
printf("preg_replace:\t%f (single quotes)<br />",$fPregElapsedSng);
printf("trim:\t\t%f<br />",$fTrimElapsed);
printf("difference:\t%f<br />",$fPregElapsed-$fTrimElapsed);
echo '</pre>';
echo '</html>';

?>

$sWord: - TestString -
$sPreg: -TestString-
$sTrim: -TestString-
preg_replace: 0.000114
preg_replace: 0.000012 (single quotes)
trim: 0.000008
difference: 0.000106

This page also demonstrates the impact of single quotes vs. double quotes.

Comments - Etiquette

Comments are added to code to assist the reader in understanding the code. The following guidelines should be observed:

  • Comments should not be written to editorialize or entertain. Sarcasm should not be in comments. Questions can be placed in comments, where necessary, to ensure issues are identified and resolved.
  • Proper grammar and spelling are required. It reduces the opportunties for misunderstanding.
  • Comments, especially in an interpretive environment such as PHP, should be brief. Utilities that strip comments for distribution can eliminate this requirement.
  • Careful coding, with meaningful function and variable names may reduce the need for comments. Overly complex statements should be avoided.
  • Comments should be considered a visible part of the deliverable product and should be of appropriate quality. If it is a professional product, comments should be professional.
  • Comments must be updated to remain current as the code changes.