View Single Post
  #8  
Old 12-11-2006, 09:11 AM
 
kyngchaos kyngchaos is offline
 

Newbie
  
Join Date: Aug 2006
Posts: 2
 

Default Re: SMTP mail function

Here's my version for XCart 4.1.3. I also switched to the PEAR mail functions, since my Geeklog site already uses it.

The key difference I found over the 4.0.x version is that 4.1 added a field to the config options database, so the SQL insert needed updating.

1. For PEAR Mail:

If you have access to your PHP installation, this is the easiest. In a shell type (path to your PHP bin dir must be in your PATH):

sudo pear install --alldeps Mail

This will install Mail and dependencies (just a few) in PHP's lib dir and be instantly available to all PHP programs.

If you prefer to install Mail somewhere else (ie you are using a hosting service and can't change PHP), you can install it in the XCart dir as in the XCart 4.0 example. Either download Mail, SMTP, Socket, SASL and manually install them (no details), or you might be able to set php_dir with the config-set option to pear. There are also ways to install local copies of PEAR for use on hosting services. See the PEAR documentation. If someone can fill in some of these methods, please do so.

2. XCart config options.

The new SQL insert should be: (note, I also added a SMTP Port option, and explicitly ordered the options):

insert into xcart_config values ('use_smtp', 'Use SMTP server', '', 'Email', '1', 'checkbox', '', ''), ('smtp_server', 'SMTP server', '', 'Email', '2', 'text', '', ''), ('smtp_port', 'SMTP port', '', 'Email', '3', 'numeric', '25', ''), ('smtp_user', 'SMTP AUTH username', '', 'Email', '4', 'text', '', ''), ('smtp_password', 'SMTP AUTH password', '', 'Email', '5', 'text', '', '');

The SMTP Auth option might also be useful to some, and can be added if needed.

3. Mail functions.

As mentioned, both mail functions are now in a single file: func.mail.php.

In func_send_mail(), replace the whole block:

list($message_header, $mail_message) = func_parse_mail($msgs);

$mail_from = $from;
if ($config["Email"]["use_base64_headers"] == "Y")
$mail_subject = func_mail_quote($mail_subject,$charset);

$headers = "From: ".$mail_from.$lend."X-Mailer: PHP/".phpversion().$lend."MIME-Version: 1.0".$lend.$message_header;
if (trim($mail_from) != "")
$headers .= "Reply-to: ".$mail_from.$lend;

if (preg_match('/([^ @,;<>]+@[^ @,;<>]+)/S', $from, $m)) {
return @mail($to,$mail_subject,$mail_message,$headers, "-f".$m[1]);
} else {
return @mail($to,$mail_subject,$mail_message,$headers);
}

with:

// customize
$mail_from = $from;
if ($config["Email"]["use_base64_headers"] == "Y")
$mail_subject = func_mail_quote($mail_subject,$charset);

if ($config['Email']['use_smtp'] == 'Y') {
if (empty($config['Email']['smtp_server'])) return;

include_once( 'Mail.php' );
include_once( 'Mail/RFC822.php' );

$mail_settings = array(
'host' => $config['Email']['smtp_server'],
'port' => $config['Email']['smtp_port'],
'username' => $config['Email']['smtp_user'],
'password' => $config['Email']['smtp_password']
);
$mailobj =& Mail::factory( "smtp", $mail_settings );
if (!is_object($mailobj) || !get_class($mailobj) == 'Mail_smtp') return;

list($message_header, $mail_message) = func_parse_mail($msgs, 0, true);

$message_header['To'] = $to;
$message_header['Subject'] = $mail_subject;
$message_header['From'] = $mail_from;
$message_header['X-Mailer'] = "PHP/".phpversion();

$senderr = $mailobj->send( $to, $message_header, $mail_message );
} else {

list($message_header, $mail_message) = func_parse_mail($msgs);
$headers = "From: ".$mail_from.$lend."X-Mailer: PHP/".phpversion().$lend."MIME-Version: 1.0".$lend.$message_header;
if (trim($mail_from) != "")
$headers .= "Reply-to: ".$mail_from.$lend;

if (preg_match('/([^ @,;<>]+@[^ @,;<>]+)/S', $from, $m)) {
return @mail($to,$mail_subject,$mail_message,$headers, "-f".$m[1]);
} else {
return @mail($to,$mail_subject,$mail_message,$headers);
}
}
// end customize

Replace the whole func_parse_mail() function with (PEAR Mail uses arrays for headers):

// customize
function func_parse_mail($msgs, $level = 0, $inarray = false) {

if (empty($msgs))
return false;

$lend = (X_DEF_OS_WINDOWS?"\r\n":"\n");
$head = "";
$heada = array();
$msg = "";

# Subarray
if (is_array($msgs['content'])) {
# Subarray is full
if(count($msgs['content']) > 1) {
$boundary = substr(uniqid(time()+rand()."_"), 0, 16);
$msgs['header']['Content-Type'] .= ";$lend\t boundary=\"$boundary\"";
foreach($msgs['header'] as $k => $v) {
if ($inarray) {
$heada[$k] = $v;
} else {
$head .= $k.": ".$v.$lend;
}
}

if($level > 0)
$msg = $head.$lend;

for($x = 0; $x < count($msgs['content']); $x++) {
// only top level can be returned as array
$res = func_parse_mail($msgs['content'][$x], $level+1);
$msg .= "--".$boundary.$lend.$res[1].$lend;
}

$msg .= "--".$boundary."--".$lend;
} else {
# Subarray have only one element
list($msgs['header'], $msgs['content']) = func_parse_mail($msgs['content'][0], $level, (($level>0)?false:$inarray));
}
}

# Current array - atom
if (!is_array($msgs['content'])) {
if (is_array($msgs['header']))
foreach ($msgs['header'] as $k => $v) {
if ($inarray) {
$heada[$k] = $v;
} else {
$head .= $k.": ".$v.$lend;
}
}

if ($level > 0)
$msg = $head.$lend;

$msg .= $msgs['content'].$lend;
}

# Header substitute
if (empty($head)) {
if (is_array($msgs['header'])) {
foreach ($msgs['header'] as $k => $v) {
if ($inarray) {
$heada[$k] = $v;
} else {
$head .= $k.": ".$v.$lend;
}
}
} else {
$head = $msgs['header'];
}
}

if ($inarray) {
return array($heada, $msg);
} else {
return array($head, $msg);
}
}
// end customize

And in func_send_simple_mail() replace:

$headers_str = "";
foreach ($headers as $hfield=>$hval)
$headers_str .= $hfield.": ".$hval.$lend;

if (preg_match('/([^ @,;<>]+@[^ @,;<>]+)/S', $from, $m))
@mail($to,$m_subject,$body,$headers_str, "-f".$m[1]);
else
@mail($to,$m_subject,$body,$headers_str);

with:

// customize
if ($config['Email']['use_smtp'] == 'Y') {
if (empty($config['Email']['smtp_server'])) return;

include_once( 'Mail.php' );
include_once( 'Mail/RFC822.php' );

$mail_settings = array(
'host' => $config['Email']['smtp_server'],
'port' => $config['Email']['smtp_port'],
'username' => $config['Email']['smtp_user'],
'password' => $config['Email']['smtp_password']
);
$mailobj =& Mail::factory( "smtp", $mail_settings );
if (!is_object($mailobj) || !get_class($mailobj) == 'Mail_smtp') return;

$headers['To'] = $to;
$headers['Subject'] = $m_subject;
list( $usec, $sec ) = explode( ' ', microtime());
$m = substr( $usec, 2, 5 );
$headers['Message-Id'] = '<' . date( 'YmdHis' ) . '.' . $m
. '@' . $config['Email']['smtp_server'] . '>';

return $mailobj->send( $to, $headers, $body );

} else {
$headers_str = "";
foreach ($headers as $hfield=>$hval)
$headers_str .= $hfield.": ".$hval.$lend;

if (preg_match('/([^ @,;<>]+@[^ @,;<>]+)/S', $from, $m))
@mail($to,$m_subject,$body,$headers_str, "-f".$m[1]);
else
@mail($to,$m_subject,$body,$headers_str);
}
// end customize


If you install PEAR Mail outside the PHP lib dir, you will have add that location to the PHP Include Path:

ini_set("include_path","/path/to/custom/install/dir" . ini_get("include_path"));

before including them (I think that'll work). Don't just include the full path to Mail.php, since it also includes its dependencies from the include_path.
__________________
X-Cart Gold 4.1.10
Reply With Quote