2003-10-11 23:51:29 +00:00
< ? php
2007-06-09 11:11:20 +00:00
/**
2005-04-09 12:26:45 +00:00
*
* @ package phpBB3
* @ version $Id $
2007-06-09 11:11:20 +00:00
* @ copyright ( c ) 2005 phpBB Group
* @ license http :// opensource . org / licenses / gpl - license . php GNU Public License
2005-04-09 12:26:45 +00:00
*
*/
2007-10-05 14:30:11 +00:00
/**
* @ ignore
*/
if ( ! defined ( 'IN_PHPBB' ))
{
exit ;
}
2005-04-09 12:26:45 +00:00
/**
* Messenger
2006-06-13 21:06:29 +00:00
* @ package phpBB3
2005-04-09 12:26:45 +00:00
*/
2003-10-11 23:51:29 +00:00
class messenger
{
2006-09-17 22:02:28 +00:00
var $vars , $msg , $extra_headers , $replyto , $from , $subject ;
2004-11-06 14:22:04 +00:00
var $addresses = array ();
2003-10-11 23:51:29 +00:00
2004-02-01 21:45:40 +00:00
var $mail_priority = MAIL_NORMAL_PRIORITY ;
var $use_queue = true ;
2004-11-06 14:22:04 +00:00
var $tpl_msg = array ();
2003-10-11 23:51:29 +00:00
2006-06-06 20:53:46 +00:00
/**
* Constructor
*/
2004-02-01 21:45:40 +00:00
function messenger ( $use_queue = true )
2003-10-12 15:29:18 +00:00
{
2007-07-19 20:38:38 +00:00
global $config ;
$this -> use_queue = ( ! $config [ 'email_package_size' ]) ? false : $use_queue ;
2004-11-06 14:22:04 +00:00
$this -> subject = '' ;
2003-10-12 15:29:18 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Resets all the data ( address , template file , etc etc ) to default
*/
2003-10-11 23:51:29 +00:00
function reset ()
{
2006-11-11 12:24:10 +00:00
$this -> addresses = $this -> extra_headers = array ();
$this -> vars = $this -> msg = $this -> replyto = $this -> from = '' ;
2004-02-01 21:45:40 +00:00
$this -> mail_priority = MAIL_NORMAL_PRIORITY ;
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Sets an email address to send to
*/
2003-10-11 23:51:29 +00:00
function to ( $address , $realname = '' )
{
2006-12-24 13:11:54 +00:00
global $config ;
2004-10-19 19:26:58 +00:00
$pos = isset ( $this -> addresses [ 'to' ]) ? sizeof ( $this -> addresses [ 'to' ]) : 0 ;
2006-12-24 13:11:54 +00:00
2003-10-11 23:51:29 +00:00
$this -> addresses [ 'to' ][ $pos ][ 'email' ] = trim ( $address );
2006-12-24 13:11:54 +00:00
// If empty sendmail_path on windows, PHP changes the to line
2007-07-03 15:36:18 +00:00
if ( ! $config [ 'smtp_delivery' ] && DIRECTORY_SEPARATOR == '\\' )
2006-12-24 13:11:54 +00:00
{
$this -> addresses [ 'to' ][ $pos ][ 'name' ] = '' ;
}
else
{
$this -> addresses [ 'to' ][ $pos ][ 'name' ] = trim ( $realname );
}
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Sets an cc address to send to
*/
2003-10-11 23:51:29 +00:00
function cc ( $address , $realname = '' )
{
2004-10-19 19:26:58 +00:00
$pos = isset ( $this -> addresses [ 'cc' ]) ? sizeof ( $this -> addresses [ 'cc' ]) : 0 ;
2003-10-11 23:51:29 +00:00
$this -> addresses [ 'cc' ][ $pos ][ 'email' ] = trim ( $address );
2004-02-07 11:00:27 +00:00
$this -> addresses [ 'cc' ][ $pos ][ 'name' ] = trim ( $realname );
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Sets an bcc address to send to
*/
2003-10-11 23:51:29 +00:00
function bcc ( $address , $realname = '' )
{
2004-10-19 19:26:58 +00:00
$pos = isset ( $this -> addresses [ 'bcc' ]) ? sizeof ( $this -> addresses [ 'bcc' ]) : 0 ;
2003-10-11 23:51:29 +00:00
$this -> addresses [ 'bcc' ][ $pos ][ 'email' ] = trim ( $address );
2004-10-19 19:26:58 +00:00
$this -> addresses [ 'bcc' ][ $pos ][ 'name' ] = trim ( $realname );
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Sets a im contact to send to
*/
2003-10-12 15:29:18 +00:00
function im ( $address , $realname = '' )
{
2004-10-19 19:26:58 +00:00
$pos = isset ( $this -> addresses [ 'im' ]) ? sizeof ( $this -> addresses [ 'im' ]) : 0 ;
2003-10-12 15:29:18 +00:00
$this -> addresses [ 'im' ][ $pos ][ 'uid' ] = trim ( $address );
$this -> addresses [ 'im' ][ $pos ][ 'name' ] = trim ( $realname );
}
2006-06-06 20:53:46 +00:00
/**
* Set the reply to address
*/
2003-10-11 23:51:29 +00:00
function replyto ( $address )
{
$this -> replyto = trim ( $address );
}
2006-06-06 20:53:46 +00:00
/**
* Set the from address
*/
2003-10-11 23:51:29 +00:00
function from ( $address )
{
$this -> from = trim ( $address );
}
2006-06-06 20:53:46 +00:00
/**
* set up subject for mail
*/
2003-10-11 23:51:29 +00:00
function subject ( $subject = '' )
{
$this -> subject = trim ( $subject );
}
2006-06-06 20:53:46 +00:00
/**
* set up extra mail headers
*/
2003-10-11 23:51:29 +00:00
function headers ( $headers )
{
2006-11-11 12:24:10 +00:00
$this -> extra_headers [] = trim ( $headers );
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Set the email priority
*/
2004-02-01 21:45:40 +00:00
function set_mail_priority ( $priority = MAIL_NORMAL_PRIORITY )
{
$this -> mail_priority = $priority ;
}
2006-06-06 20:53:46 +00:00
/**
* Set email template to use
*/
2003-10-11 23:51:29 +00:00
function template ( $template_file , $template_lang = '' )
{
global $config , $phpbb_root_path ;
if ( ! trim ( $template_file ))
{
trigger_error ( 'No template file set' , E_USER_ERROR );
}
if ( ! trim ( $template_lang ))
{
2006-06-06 20:53:46 +00:00
$template_lang = basename ( $config [ 'default_lang' ]);
2003-10-11 23:51:29 +00:00
}
2004-02-07 11:00:27 +00:00
if ( empty ( $this -> tpl_msg [ $template_lang . $template_file ]))
2003-10-11 23:51:29 +00:00
{
$tpl_file = " { $phpbb_root_path } language/ $template_lang /email/ $template_file .txt " ;
if ( ! file_exists ( $tpl_file ))
{
2007-11-17 20:04:49 +00:00
trigger_error ( " Could not find email template file [ $tpl_file ] " , E_USER_ERROR );
2003-10-11 23:51:29 +00:00
}
2007-03-25 16:05:22 +00:00
if (( $data = @ file_get_contents ( $tpl_file )) === false )
2003-10-11 23:51:29 +00:00
{
2006-04-30 12:57:37 +00:00
trigger_error ( " Failed opening template file [ $tpl_file ] " , E_USER_ERROR );
2003-10-11 23:51:29 +00:00
}
2007-03-25 15:58:48 +00:00
$this -> tpl_msg [ $template_lang . $template_file ] = $data ;
2003-10-11 23:51:29 +00:00
}
2004-02-07 11:00:27 +00:00
$this -> msg = $this -> tpl_msg [ $template_lang . $template_file ];
2003-10-11 23:51:29 +00:00
return true ;
}
2006-06-06 20:53:46 +00:00
/**
* assign variables to email template
*/
2003-10-11 23:51:29 +00:00
function assign_vars ( $vars )
{
2006-04-15 14:48:36 +00:00
$this -> vars = ( empty ( $this -> vars )) ? $vars : $this -> vars + $vars ;
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Send the mail out to the recipients set previously in var $this -> addresses
*/
2004-09-04 19:32:23 +00:00
function send ( $method = NOTIFY_EMAIL , $break = false )
2003-10-11 23:51:29 +00:00
{
global $config , $user ;
2006-11-03 17:50:39 +00:00
// We add some standard variables we always use, no need to specify them always
$this -> vars [ 'U_BOARD' ] = ( ! isset ( $this -> vars [ 'U_BOARD' ])) ? generate_board_url () : $this -> vars [ 'U_BOARD' ];
2006-11-03 21:05:25 +00:00
$this -> vars [ 'EMAIL_SIG' ] = ( ! isset ( $this -> vars [ 'EMAIL_SIG' ])) ? str_replace ( '<br />' , " \n " , " -- \n " . htmlspecialchars_decode ( $config [ 'board_email_sig' ])) : $this -> vars [ 'EMAIL_SIG' ];
$this -> vars [ 'SITENAME' ] = ( ! isset ( $this -> vars [ 'SITENAME' ])) ? htmlspecialchars_decode ( $config [ 'sitename' ]) : $this -> vars [ 'SITENAME' ];
2006-11-03 17:50:39 +00:00
2003-10-11 23:51:29 +00:00
// Escape all quotes, else the eval will fail.
$this -> msg = str_replace ( " ' " , " \ ' " , $this -> msg );
2006-11-03 17:50:39 +00:00
$this -> msg = preg_replace ( '#\{([a-z0-9\-_]*?)\}#is' , " ' . ((isset( \$ this->vars[' \\ 1'])) ? \$ this->vars[' \\ 1'] : '') . ' " , $this -> msg );
2003-10-11 23:51:29 +00:00
eval ( " \$ this->msg = ' $this->msg '; " );
// We now try and pull a subject from the email body ... if it exists,
// do this here because the subject may contain a variable
$drop_header = '' ;
$match = array ();
if ( preg_match ( '#^(Subject:(.*?))$#m' , $this -> msg , $match ))
{
2007-02-09 14:31:17 +00:00
$this -> subject = ( trim ( $match [ 2 ]) != '' ) ? trim ( $match [ 2 ]) : (( $this -> subject != '' ) ? $this -> subject : $user -> lang [ 'NO_EMAIL_SUBJECT' ]);
2003-10-11 23:51:29 +00:00
$drop_header .= '[\r\n]*?' . preg_quote ( $match [ 1 ], '#' );
}
else
{
2007-02-09 14:31:17 +00:00
$this -> subject = (( $this -> subject != '' ) ? $this -> subject : $user -> lang [ 'NO_EMAIL_SUBJECT' ]);
2003-10-11 23:51:29 +00:00
}
if ( $drop_header )
{
$this -> msg = trim ( preg_replace ( '#' . $drop_header . '#s' , '' , $this -> msg ));
}
2004-09-04 19:32:23 +00:00
if ( $break )
{
2006-05-26 15:04:27 +00:00
return true ;
2004-09-04 19:32:23 +00:00
}
2003-10-11 23:51:29 +00:00
switch ( $method )
{
case NOTIFY_EMAIL :
2004-05-26 20:32:51 +00:00
$result = $this -> msg_email ();
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
case NOTIFY_IM :
2004-02-07 11:00:27 +00:00
$result = $this -> msg_jabber ();
2006-04-15 14:48:36 +00:00
break ;
2006-06-06 20:53:46 +00:00
2003-10-11 23:51:29 +00:00
case NOTIFY_BOTH :
2004-05-26 20:32:51 +00:00
$result = $this -> msg_email ();
2003-10-11 23:51:29 +00:00
$this -> msg_jabber ();
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
}
$this -> reset ();
2004-02-07 11:00:27 +00:00
return $result ;
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Add error message to log
*/
2003-10-11 23:51:29 +00:00
function error ( $type , $msg )
{
2006-12-06 17:35:04 +00:00
global $user , $phpEx , $phpbb_root_path , $config ;
2003-10-13 17:41:27 +00:00
// Session doesn't exist, create it
2006-06-13 18:50:21 +00:00
if ( ! isset ( $user -> session_id ) || $user -> session_id === '' )
{
$user -> session_begin ();
}
2003-10-11 23:51:29 +00:00
2006-12-06 17:35:04 +00:00
$calling_page = ( ! empty ( $_SERVER [ 'PHP_SELF' ])) ? $_SERVER [ 'PHP_SELF' ] : $_ENV [ 'PHP_SELF' ];
$message = '' ;
switch ( $type )
{
case 'EMAIL' :
$message = '<strong>EMAIL/' . (( $config [ 'smtp_delivery' ]) ? 'SMTP' : 'PHP/' . $config [ 'email_function_name' ] . '()' ) . '</strong>' ;
break ;
default :
$message = " <strong> $type </strong> " ;
break ;
}
2007-09-02 17:24:56 +00:00
$message .= '<br /><em>' . htmlspecialchars ( $calling_page ) . '</em><br /><br />' . $msg . '<br />' ;
2006-12-06 17:35:04 +00:00
add_log ( 'critical' , 'LOG_ERROR_' . $type , $message );
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Save to queue
*/
2005-04-09 12:26:45 +00:00
function save_queue ()
{
2005-08-18 12:44:24 +00:00
global $config ;
if ( $config [ 'email_package_size' ] && $this -> use_queue && ! empty ( $this -> queue ))
2005-04-09 12:26:45 +00:00
{
$this -> queue -> save ();
2007-07-19 20:38:38 +00:00
return ;
2005-04-09 12:26:45 +00:00
}
}
2003-10-11 23:51:29 +00:00
2006-11-11 12:24:10 +00:00
/**
* Return email header
*/
function build_header ( $to , $cc , $bcc )
{
global $config ;
$headers = array ();
$headers [] = 'From: ' . $this -> from ;
if ( $cc )
{
$headers [] = 'Cc: ' . $cc ;
}
if ( $bcc )
{
$headers [] = 'Bcc: ' . $bcc ;
}
$headers [] = 'Reply-To: ' . $this -> replyto ;
$headers [] = 'Return-Path: <' . $config [ 'board_email' ] . '>' ;
$headers [] = 'Sender: <' . $config [ 'board_email' ] . '>' ;
$headers [] = 'MIME-Version: 1.0' ;
$headers [] = 'Message-ID: <' . md5 ( unique_id ( time ())) . '@' . $config [ 'server_name' ] . '>' ;
2007-11-10 16:19:24 +00:00
$headers [] = 'Date: ' . date ( 'r' , time ());
2006-11-11 12:24:10 +00:00
$headers [] = 'Content-Type: text/plain; charset=UTF-8' ; // format=flowed
$headers [] = 'Content-Transfer-Encoding: 8bit' ; // 7bit
$headers [] = 'X-Priority: ' . $this -> mail_priority ;
$headers [] = 'X-MSMail-Priority: ' . (( $this -> mail_priority == MAIL_LOW_PRIORITY ) ? 'Low' : (( $this -> mail_priority == MAIL_NORMAL_PRIORITY ) ? 'Normal' : 'High' ));
$headers [] = 'X-Mailer: PhpBB3' ;
$headers [] = 'X-MimeOLE: phpBB3' ;
$headers [] = 'X-phpBB-Origin: phpbb://' . str_replace ( array ( 'http://' , 'https://' ), array ( '' , '' ), generate_board_url ());
2006-11-12 18:44:42 +00:00
// We use \n here instead of \r\n because our smtp mailer is adjusting it to \r\n automatically, whereby the php mail function only works
// if using \n.
2006-11-11 12:24:10 +00:00
if ( sizeof ( $this -> extra_headers ))
{
2006-11-12 18:44:42 +00:00
$headers [] = implode ( " \n " , $this -> extra_headers );
2006-11-11 12:24:10 +00:00
}
2006-11-12 18:44:42 +00:00
return implode ( " \n " , $headers );
2006-11-11 12:24:10 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Send out emails
*/
2004-05-26 20:32:51 +00:00
function msg_email ()
2003-10-11 23:51:29 +00:00
{
global $config , $user ;
if ( empty ( $config [ 'email_enable' ]))
{
return false ;
}
$use_queue = false ;
2004-02-01 21:45:40 +00:00
if ( $config [ 'email_package_size' ] && $this -> use_queue )
2003-10-11 23:51:29 +00:00
{
if ( empty ( $this -> queue ))
{
$this -> queue = new queue ();
2004-02-01 21:45:40 +00:00
$this -> queue -> init ( 'email' , $config [ 'email_package_size' ]);
2003-10-11 23:51:29 +00:00
}
$use_queue = true ;
}
2006-11-11 12:24:10 +00:00
if ( empty ( $this -> replyto ))
{
2006-12-31 16:56:15 +00:00
$this -> replyto = '<' . $config [ 'board_contact' ] . '>' ;
2006-11-11 12:24:10 +00:00
}
if ( empty ( $this -> from ))
{
2007-01-01 12:56:14 +00:00
$this -> from = '<' . $config [ 'board_contact' ] . '>' ;
2006-11-11 12:24:10 +00:00
}
2003-10-11 23:51:29 +00:00
// Build to, cc and bcc strings
2006-11-11 12:24:10 +00:00
$to = $cc = $bcc = '' ;
2003-10-11 23:51:29 +00:00
foreach ( $this -> addresses as $type => $address_ary )
{
2004-11-06 14:22:04 +00:00
if ( $type == 'im' )
{
continue ;
}
2003-10-11 23:51:29 +00:00
foreach ( $address_ary as $which_ary )
{
2007-01-26 16:09:51 +00:00
$$type .= (( $$type != '' ) ? ', ' : '' ) . (( $which_ary [ 'name' ] != '' ) ? '"' . mail_encode ( $which_ary [ 'name' ]) . '" <' . $which_ary [ 'email' ] . '>' : $which_ary [ 'email' ]);
2003-10-11 23:51:29 +00:00
}
}
// Build header
2006-11-11 12:24:10 +00:00
$headers = $this -> build_header ( $to , $cc , $bcc );
2003-10-11 23:51:29 +00:00
2006-09-17 22:02:28 +00:00
// Send message ...
2003-10-11 23:51:29 +00:00
if ( ! $use_queue )
{
2007-09-14 14:06:23 +00:00
$mail_to = ( $to == '' ) ? 'undisclosed-recipients:;' : $to ;
2003-10-11 23:51:29 +00:00
$err_msg = '' ;
2004-02-02 13:06:18 +00:00
2006-07-20 17:55:36 +00:00
if ( $config [ 'smtp_delivery' ])
{
2007-08-16 11:28:58 +00:00
$result = smtpmail ( $this -> addresses , mail_encode ( $this -> subject ), wordwrap ( utf8_wordwrap ( $this -> msg ), 997 , " \n " , true ), $err_msg , $headers );
2006-07-20 17:55:36 +00:00
}
else
{
2007-01-04 16:07:38 +00:00
ob_start ();
2007-08-16 11:28:58 +00:00
$result = $config [ 'email_function_name' ]( $mail_to , mail_encode ( $this -> subject ), wordwrap ( utf8_wordwrap ( $this -> msg ), 997 , " \n " , true ), $headers );
2007-01-04 16:07:38 +00:00
$err_msg = ob_get_clean ();
2006-07-20 17:55:36 +00:00
}
2003-10-11 23:51:29 +00:00
if ( ! $result )
{
2006-12-06 17:35:04 +00:00
$this -> error ( 'EMAIL' , $err_msg );
2004-02-01 21:45:40 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
}
else
{
$this -> queue -> put ( 'email' , array (
'to' => $to ,
'addresses' => $this -> addresses ,
'subject' => $this -> subject ,
'msg' => $this -> msg ,
'headers' => $headers )
);
}
2004-02-07 11:00:27 +00:00
2003-10-11 23:51:29 +00:00
return true ;
}
2006-06-06 20:53:46 +00:00
/**
* Send jabber message out
*/
2003-10-11 23:51:29 +00:00
function msg_jabber ()
{
global $config , $db , $user , $phpbb_root_path , $phpEx ;
if ( empty ( $config [ 'jab_enable' ]) || empty ( $config [ 'jab_host' ]) || empty ( $config [ 'jab_username' ]) || empty ( $config [ 'jab_password' ]))
{
return false ;
}
$use_queue = false ;
2004-02-01 21:45:40 +00:00
if ( $config [ 'jab_package_size' ] && $this -> use_queue )
2003-10-11 23:51:29 +00:00
{
if ( empty ( $this -> queue ))
{
$this -> queue = new queue ();
2004-02-01 21:45:40 +00:00
$this -> queue -> init ( 'jabber' , $config [ 'jab_package_size' ]);
2003-10-11 23:51:29 +00:00
}
$use_queue = true ;
}
$addresses = array ();
2003-10-12 15:29:18 +00:00
foreach ( $this -> addresses [ 'im' ] as $type => $uid_ary )
2003-10-11 23:51:29 +00:00
{
2003-10-12 15:29:18 +00:00
$addresses [] = $uid_ary [ 'uid' ];
2003-10-11 23:51:29 +00:00
}
$addresses = array_unique ( $addresses );
if ( ! $use_queue )
{
2006-12-16 12:57:01 +00:00
include_once ( $phpbb_root_path . 'includes/functions_jabber.' . $phpEx );
2007-05-26 18:20:07 +00:00
$this -> jabber = new jabber ( $config [ 'jab_host' ], $config [ 'jab_port' ], $config [ 'jab_username' ], $config [ 'jab_password' ], $config [ 'jab_use_ssl' ]);
2003-10-11 23:51:29 +00:00
2005-04-10 11:21:01 +00:00
if ( ! $this -> jabber -> connect ())
2003-10-11 23:51:29 +00:00
{
2007-09-02 17:24:56 +00:00
$this -> error ( 'JABBER' , $user -> lang [ 'ERR_JAB_CONNECT' ] . '<br />' . $this -> jabber -> get_log ());
2004-05-26 20:32:51 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
2007-05-26 16:38:33 +00:00
if ( ! $this -> jabber -> login ())
2003-10-11 23:51:29 +00:00
{
2007-09-02 17:24:56 +00:00
$this -> error ( 'JABBER' , $user -> lang [ 'ERR_JAB_AUTH' ] . '<br />' . $this -> jabber -> get_log ());
2004-05-26 20:32:51 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
foreach ( $addresses as $address )
{
2007-05-26 16:38:33 +00:00
$this -> jabber -> send_message ( $address , $this -> msg , $this -> subject );
2003-10-11 23:51:29 +00:00
}
2005-04-10 11:21:01 +00:00
$this -> jabber -> disconnect ();
2003-10-11 23:51:29 +00:00
}
else
{
$this -> queue -> put ( 'jabber' , array (
'addresses' => $addresses ,
2006-06-06 20:53:46 +00:00
'subject' => $this -> subject ,
'msg' => $this -> msg )
2003-10-11 23:51:29 +00:00
);
}
unset ( $addresses );
return true ;
}
}
2005-04-09 12:26:45 +00:00
/**
2006-06-06 20:53:46 +00:00
* handling email and jabber queue
2006-06-13 21:06:29 +00:00
* @ package phpBB3
2005-04-09 12:26:45 +00:00
*/
2003-10-11 23:51:29 +00:00
class queue
{
var $data = array ();
var $queue_data = array ();
var $package_size = 0 ;
var $cache_file = '' ;
2006-06-06 20:53:46 +00:00
/**
* constructor
*/
2003-10-11 23:51:29 +00:00
function queue ()
{
global $phpEx , $phpbb_root_path ;
$this -> data = array ();
$this -> cache_file = " { $phpbb_root_path } cache/queue. $phpEx " ;
}
2006-06-06 20:53:46 +00:00
/**
* Init a queue object
*/
2003-10-11 23:51:29 +00:00
function init ( $object , $package_size )
{
$this -> data [ $object ] = array ();
$this -> data [ $object ][ 'package_size' ] = $package_size ;
$this -> data [ $object ][ 'data' ] = array ();
}
2006-06-06 20:53:46 +00:00
/**
* Put object in queue
*/
2003-10-11 23:51:29 +00:00
function put ( $object , $scope )
{
$this -> data [ $object ][ 'data' ][] = $scope ;
}
2006-06-06 20:53:46 +00:00
/**
* Process queue
* Using lock file
*/
2003-10-11 23:51:29 +00:00
function process ()
{
2007-09-02 17:24:56 +00:00
global $db , $config , $phpEx , $phpbb_root_path , $user ;
2003-10-11 23:51:29 +00:00
2005-04-10 11:21:01 +00:00
set_config ( 'last_queue_run' , time (), true );
2003-10-11 23:51:29 +00:00
2004-05-31 18:00:10 +00:00
// Delete stale lock file
if ( file_exists ( $this -> cache_file . '.lock' ) && ! file_exists ( $this -> cache_file ))
{
@ unlink ( $this -> cache_file . '.lock' );
return ;
}
2003-10-12 20:38:37 +00:00
if ( ! file_exists ( $this -> cache_file ) || ( file_exists ( $this -> cache_file . '.lock' ) && filemtime ( $this -> cache_file ) > time () - $config [ 'queue_interval' ]))
2003-10-11 23:51:29 +00:00
{
return ;
}
$fp = @ fopen ( $this -> cache_file . '.lock' , 'wb' );
fclose ( $fp );
2008-08-16 19:06:18 +00:00
phpbb_chmod ( $this -> cache_file . '.lock' , 'write-all' );
2003-10-11 23:51:29 +00:00
include ( $this -> cache_file );
foreach ( $this -> queue_data as $object => $data_ary )
{
2005-10-02 18:17:06 +00:00
@ set_time_limit ( 0 );
if ( ! isset ( $data_ary [ 'package_size' ]))
{
$data_ary [ 'package_size' ] = 0 ;
}
2003-10-11 23:51:29 +00:00
2003-10-14 13:24:07 +00:00
$package_size = $data_ary [ 'package_size' ];
2006-10-11 13:48:30 +00:00
$num_items = ( ! $package_size || sizeof ( $data_ary [ 'data' ]) < $package_size ) ? sizeof ( $data_ary [ 'data' ]) : $package_size ;
2003-10-11 23:51:29 +00:00
2007-08-13 12:14:07 +00:00
// If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs...
if ( sizeof ( $data_ary [ 'data' ]) > $package_size * 2.5 )
{
$num_items = sizeof ( $data_ary [ 'data' ]);
}
2003-10-11 23:51:29 +00:00
switch ( $object )
{
case 'email' :
// Delete the email queued objects if mailing is disabled
if ( ! $config [ 'email_enable' ])
{
unset ( $this -> queue_data [ 'email' ]);
2003-10-14 13:30:43 +00:00
continue 2 ;
2003-10-11 23:51:29 +00:00
}
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
case 'jabber' :
if ( ! $config [ 'jab_enable' ])
{
unset ( $this -> queue_data [ 'jabber' ]);
2003-10-14 13:30:43 +00:00
continue 2 ;
2003-10-11 23:51:29 +00:00
}
2007-11-17 20:04:49 +00:00
include_once ( $phpbb_root_path . 'includes/functions_jabber.' . $phpEx );
2007-05-26 18:20:07 +00:00
$this -> jabber = new jabber ( $config [ 'jab_host' ], $config [ 'jab_port' ], $config [ 'jab_username' ], $config [ 'jab_password' ], $config [ 'jab_use_ssl' ]);
2003-10-11 23:51:29 +00:00
2005-04-10 11:21:01 +00:00
if ( ! $this -> jabber -> connect ())
2003-10-11 23:51:29 +00:00
{
2007-09-02 17:24:56 +00:00
messenger :: error ( 'JABBER' , $user -> lang [ 'ERR_JAB_CONNECT' ]);
2003-10-14 13:30:43 +00:00
continue 2 ;
2003-10-11 23:51:29 +00:00
}
2007-05-26 16:38:33 +00:00
if ( ! $this -> jabber -> login ())
2003-10-11 23:51:29 +00:00
{
2007-09-02 17:24:56 +00:00
messenger :: error ( 'JABBER' , $user -> lang [ 'ERR_JAB_AUTH' ]);
2003-10-14 13:30:43 +00:00
continue 2 ;
2003-10-11 23:51:29 +00:00
}
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
default :
return ;
}
for ( $i = 0 ; $i < $num_items ; $i ++ )
{
2006-03-21 19:23:34 +00:00
// Make variables available...
2003-10-11 23:51:29 +00:00
extract ( array_shift ( $this -> queue_data [ $object ][ 'data' ]));
switch ( $object )
{
case 'email' :
$err_msg = '' ;
2007-09-14 14:06:23 +00:00
$to = ( ! $to ) ? 'undisclosed-recipients:;' : $to ;
2003-11-23 22:25:46 +00:00
2007-01-04 16:07:38 +00:00
if ( $config [ 'smtp_delivery' ])
{
2007-08-16 11:28:58 +00:00
$result = smtpmail ( $addresses , mail_encode ( $subject ), wordwrap ( utf8_wordwrap ( $msg ), 997 , " \n " , true ), $err_msg , $headers );
2007-01-04 16:07:38 +00:00
}
else
{
ob_start ();
2007-08-16 11:28:58 +00:00
$result = $config [ 'email_function_name' ]( $to , mail_encode ( $subject ), wordwrap ( utf8_wordwrap ( $msg ), 997 , " \n " , true ), $headers );
2007-01-04 16:07:38 +00:00
$err_msg = ob_get_clean ();
}
2003-10-11 23:51:29 +00:00
if ( ! $result )
{
@ unlink ( $this -> cache_file . '.lock' );
2006-12-06 17:35:04 +00:00
messenger :: error ( 'EMAIL' , $err_msg );
2006-10-03 18:35:59 +00:00
continue 2 ;
2003-10-11 23:51:29 +00:00
}
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
case 'jabber' :
foreach ( $addresses as $address )
{
2007-05-26 16:38:33 +00:00
if ( $this -> jabber -> send_message ( $address , $msg , $subject ) === false )
2006-10-03 18:35:59 +00:00
{
2006-12-16 12:57:01 +00:00
messenger :: error ( 'JABBER' , $this -> jabber -> get_log ());
2006-10-03 18:35:59 +00:00
continue 3 ;
}
2003-10-11 23:51:29 +00:00
}
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
}
}
// No more data for this object? Unset it
2005-04-10 18:07:12 +00:00
if ( ! sizeof ( $this -> queue_data [ $object ][ 'data' ]))
2003-10-11 23:51:29 +00:00
{
unset ( $this -> queue_data [ $object ]);
}
// Post-object processing
switch ( $object )
{
case 'jabber' :
// Hang about a couple of secs to ensure the messages are
// handled, then disconnect
2005-04-10 11:21:01 +00:00
$this -> jabber -> disconnect ();
2006-04-15 14:48:36 +00:00
break ;
2003-10-11 23:51:29 +00:00
}
}
2008-08-16 19:06:18 +00:00
2003-10-11 23:51:29 +00:00
if ( ! sizeof ( $this -> queue_data ))
{
2003-10-11 23:59:41 +00:00
@ unlink ( $this -> cache_file );
2003-10-11 23:51:29 +00:00
}
else
{
if ( $fp = @ fopen ( $this -> cache_file , 'w' ))
{
@ flock ( $fp , LOCK_EX );
2007-01-05 09:30:46 +00:00
fwrite ( $fp , " <?php \n \$ this->queue_data = " . var_export ( $this -> queue_data , true ) . " ; \n ?> " );
2003-10-11 23:51:29 +00:00
@ flock ( $fp , LOCK_UN );
fclose ( $fp );
2007-06-30 15:04:49 +00:00
2008-08-16 19:06:18 +00:00
phpbb_chmod ( $this -> cache_file , 'rwrite' );
2003-10-11 23:51:29 +00:00
}
}
@ unlink ( $this -> cache_file . '.lock' );
}
2006-06-06 20:53:46 +00:00
/**
* Save queue
*/
2003-10-11 23:51:29 +00:00
function save ()
{
2004-02-01 21:45:40 +00:00
if ( ! sizeof ( $this -> data ))
{
return ;
}
2008-08-16 19:06:18 +00:00
2003-10-11 23:51:29 +00:00
if ( file_exists ( $this -> cache_file ))
{
include ( $this -> cache_file );
2008-08-16 19:06:18 +00:00
2003-10-11 23:51:29 +00:00
foreach ( $this -> queue_data as $object => $data_ary )
{
2005-04-10 18:07:12 +00:00
if ( isset ( $this -> data [ $object ]) && sizeof ( $this -> data [ $object ]))
2003-10-11 23:51:29 +00:00
{
$this -> data [ $object ][ 'data' ] = array_merge ( $data_ary [ 'data' ], $this -> data [ $object ][ 'data' ]);
}
2005-04-10 18:07:12 +00:00
else
{
$this -> data [ $object ][ 'data' ] = $data_ary [ 'data' ];
}
2003-10-11 23:51:29 +00:00
}
}
2006-05-27 16:24:21 +00:00
if ( $fp = @ fopen ( $this -> cache_file , 'w' ))
2003-10-11 23:51:29 +00:00
{
@ flock ( $fp , LOCK_EX );
2007-01-05 09:30:46 +00:00
fwrite ( $fp , " <?php \n \$ this->queue_data = " . var_export ( $this -> data , true ) . " ; \n ?> " );
2003-10-11 23:51:29 +00:00
@ flock ( $fp , LOCK_UN );
fclose ( $fp );
2007-06-30 15:04:49 +00:00
2008-08-16 19:06:18 +00:00
phpbb_chmod ( $this -> cache_file , 'rwrite' );
2003-10-11 23:51:29 +00:00
}
}
}
2005-04-09 12:26:45 +00:00
/**
* Replacement or substitute for PHP ' s mail command
*/
2006-09-17 22:02:28 +00:00
function smtpmail ( $addresses , $subject , $message , & $err_msg , $headers = '' )
2003-10-11 23:51:29 +00:00
{
2004-02-07 11:00:27 +00:00
global $config , $user ;
2003-10-11 23:51:29 +00:00
// Fix any bare linefeeds in the message to make it RFC821 Compliant.
$message = preg_replace ( " #(?<! \r ) \n #si " , " \r \n " , $message );
if ( $headers != '' )
{
if ( is_array ( $headers ))
{
2006-11-12 18:44:42 +00:00
$headers = ( sizeof ( $headers ) > 1 ) ? join ( " \n " , $headers ) : $headers [ 0 ];
2003-10-11 23:51:29 +00:00
}
$headers = chop ( $headers );
// Make sure there are no bare linefeeds in the headers
$headers = preg_replace ( '#(?<!\r)\n#si' , " \r \n " , $headers );
// Ok this is rather confusing all things considered,
// but we have to grab bcc and cc headers and treat them differently
// Something we really didn't take into consideration originally
$header_array = explode ( " \r \n " , $headers );
$headers = '' ;
2006-12-31 16:56:15 +00:00
2003-10-11 23:51:29 +00:00
foreach ( $header_array as $header )
{
2006-12-31 16:56:15 +00:00
if ( strpos ( strtolower ( $header ), 'cc:' ) === 0 || strpos ( strtolower ( $header ), 'bcc:' ) === 0 )
2003-10-11 23:51:29 +00:00
{
$header = '' ;
}
$headers .= ( $header != '' ) ? $header . " \r \n " : '' ;
}
$headers = chop ( $headers );
}
if ( trim ( $subject ) == '' )
{
2006-06-06 20:53:46 +00:00
$err_msg = ( isset ( $user -> lang [ 'NO_EMAIL_SUBJECT' ])) ? $user -> lang [ 'NO_EMAIL_SUBJECT' ] : 'No email subject specified' ;
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
if ( trim ( $message ) == '' )
{
2006-06-06 20:53:46 +00:00
$err_msg = ( isset ( $user -> lang [ 'NO_EMAIL_MESSAGE' ])) ? $user -> lang [ 'NO_EMAIL_MESSAGE' ] : 'Email message was blank' ;
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
$mail_rcpt = $mail_to = $mail_cc = array ();
// Build correct addresses for RCPT TO command and the client side display (TO, CC)
2006-09-04 20:35:46 +00:00
if ( isset ( $addresses [ 'to' ]) && sizeof ( $addresses [ 'to' ]))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
foreach ( $addresses [ 'to' ] as $which_ary )
{
2006-09-17 22:02:28 +00:00
$mail_to [] = ( $which_ary [ 'name' ] != '' ) ? mail_encode ( trim ( $which_ary [ 'name' ])) . ' <' . trim ( $which_ary [ 'email' ]) . '>' : '<' . trim ( $which_ary [ 'email' ]) . '>' ;
2006-09-04 20:35:46 +00:00
$mail_rcpt [ 'to' ][] = '<' . trim ( $which_ary [ 'email' ]) . '>' ;
}
2003-10-11 23:51:29 +00:00
}
2004-09-05 09:54:48 +00:00
if ( isset ( $addresses [ 'bcc' ]) && sizeof ( $addresses [ 'bcc' ]))
2003-10-11 23:51:29 +00:00
{
2004-09-05 09:54:48 +00:00
foreach ( $addresses [ 'bcc' ] as $which_ary )
{
$mail_rcpt [ 'bcc' ][] = '<' . trim ( $which_ary [ 'email' ]) . '>' ;
}
2003-10-11 23:51:29 +00:00
}
2004-09-05 09:54:48 +00:00
if ( isset ( $addresses [ 'cc' ]) && sizeof ( $addresses [ 'cc' ]))
2003-10-11 23:51:29 +00:00
{
2004-09-05 09:54:48 +00:00
foreach ( $addresses [ 'cc' ] as $which_ary )
{
2006-09-17 22:02:28 +00:00
$mail_cc [] = ( $which_ary [ 'name' ] != '' ) ? mail_encode ( trim ( $which_ary [ 'name' ])) . ' <' . trim ( $which_ary [ 'email' ]) . '>' : '<' . trim ( $which_ary [ 'email' ]) . '>' ;
2004-09-05 09:54:48 +00:00
$mail_rcpt [ 'cc' ][] = '<' . trim ( $which_ary [ 'email' ]) . '>' ;
}
2003-10-11 23:51:29 +00:00
}
2006-09-04 20:35:46 +00:00
$smtp = new smtp_class ();
2004-01-31 15:49:12 +00:00
2006-06-22 15:14:03 +00:00
$errno = 0 ;
$errstr = '' ;
2006-09-04 20:35:46 +00:00
$smtp -> add_backtrace ( 'Connecting to ' . $config [ 'smtp_host' ] . ':' . $config [ 'smtp_port' ]);
2006-06-06 20:53:46 +00:00
// Ok we have error checked as much as we can to this point let's get on it already.
2007-07-19 20:38:38 +00:00
ob_start ();
$smtp -> socket = fsockopen ( $config [ 'smtp_host' ], $config [ 'smtp_port' ], $errno , $errstr , 20 );
$error_contents = ob_get_clean ();
if ( ! $smtp -> socket )
2003-10-11 23:51:29 +00:00
{
2007-01-06 19:37:09 +00:00
if ( $errstr )
{
$errstr = utf8_convert_message ( $errstr );
}
2006-06-06 20:53:46 +00:00
$err_msg = ( isset ( $user -> lang [ 'NO_CONNECT_TO_SMTP_HOST' ])) ? sprintf ( $user -> lang [ 'NO_CONNECT_TO_SMTP_HOST' ], $errno , $errstr ) : " Could not connect to smtp host : $errno : $errstr " ;
2007-07-19 20:38:38 +00:00
$err_msg .= ( $error_contents ) ? '<br /><br />' . htmlspecialchars ( $error_contents ) : '' ;
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
// Wait for reply
2004-01-31 15:49:12 +00:00
if ( $err_msg = $smtp -> server_parse ( '220' , __LINE__ ))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
2004-01-31 15:49:12 +00:00
// Let me in. This function handles the complete authentication process
if ( $err_msg = $smtp -> log_into_server ( $config [ 'smtp_host' ], $config [ 'smtp_username' ], $config [ 'smtp_password' ], $config [ 'smtp_auth_method' ]))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
// From this point onward most server response codes should be 250
// Specify who the mail is from....
2007-02-18 13:42:08 +00:00
$smtp -> server_send ( 'MAIL FROM:<' . $config [ 'board_email' ] . '>' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $smtp -> server_parse ( '250' , __LINE__ ))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
// Specify each user to send to and build to header.
$to_header = implode ( ', ' , $mail_to );
$cc_header = implode ( ', ' , $mail_cc );
// Now tell the MTA to send the Message to the following people... [TO, BCC, CC]
2004-01-31 19:07:14 +00:00
$rcpt = false ;
2003-10-11 23:51:29 +00:00
foreach ( $mail_rcpt as $type => $mail_to_addresses )
{
foreach ( $mail_to_addresses as $mail_to_address )
{
// Add an additional bit of error checking to the To field.
if ( preg_match ( '#[^ ]+\@[^ ]+#' , $mail_to_address ))
{
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( " RCPT TO: $mail_to_address " );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $smtp -> server_parse ( '250' , __LINE__ ))
2003-10-11 23:51:29 +00:00
{
2004-01-31 19:07:14 +00:00
// We continue... if users are not resolved we do not care
if ( $smtp -> numeric_response_code != 550 )
{
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 19:07:14 +00:00
return false ;
}
}
else
{
$rcpt = true ;
2003-10-11 23:51:29 +00:00
}
}
}
}
2004-01-31 19:07:14 +00:00
// We try to send messages even if a few people do not seem to have valid email addresses, but if no one has, we have to exit here.
if ( ! $rcpt )
{
2005-10-02 18:17:06 +00:00
$user -> session_begin ();
2006-06-06 20:53:46 +00:00
$err_msg .= '<br /><br />' ;
$err_msg .= ( isset ( $user -> lang [ 'INVALID_EMAIL_LOG' ])) ? sprintf ( $user -> lang [ 'INVALID_EMAIL_LOG' ], htmlspecialchars ( $mail_to_address )) : '<strong>' . htmlspecialchars ( $mail_to_address ) . '</strong> possibly an invalid email address?' ;
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 19:07:14 +00:00
return false ;
}
2003-10-11 23:51:29 +00:00
// Ok now we tell the server we are ready to start sending data
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( 'DATA' );
2003-10-11 23:51:29 +00:00
// This is the last response code we look for until the end of the message.
2004-01-31 15:49:12 +00:00
if ( $err_msg = $smtp -> server_parse ( '354' , __LINE__ ))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
// Send the Subject Line...
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( " Subject: $subject " );
2003-10-11 23:51:29 +00:00
// Now the To Header.
2007-09-14 14:06:23 +00:00
$to_header = ( $to_header == '' ) ? 'undisclosed-recipients:;' : $to_header ;
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( " To: $to_header " );
2003-10-11 23:51:29 +00:00
// Now the CC Header.
if ( $cc_header != '' )
{
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( " CC: $cc_header " );
2003-10-11 23:51:29 +00:00
}
// Now any custom headers....
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( " $headers\r\n " );
2003-10-11 23:51:29 +00:00
// Ok now we are ready for the message...
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( $message );
2003-10-11 23:51:29 +00:00
// Ok the all the ingredients are mixed in let's cook this puppy...
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( '.' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $smtp -> server_parse ( '250' , __LINE__ ))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2004-01-31 15:49:12 +00:00
return false ;
2003-10-11 23:51:29 +00:00
}
// Now tell the server we are done and close the socket...
2004-02-01 21:45:40 +00:00
$smtp -> server_send ( 'QUIT' );
2006-09-04 20:35:46 +00:00
$smtp -> close_session ( $err_msg );
2003-10-11 23:51:29 +00:00
2004-01-31 15:49:12 +00:00
return true ;
2003-10-11 23:51:29 +00:00
}
2005-04-09 12:26:45 +00:00
/**
* SMTP Class
* Auth Mechanisms originally taken from the AUTH Modules found within the PHP Extension and Application Repository ( PEAR )
* See docs / AUTHORS for more details
2006-06-13 21:06:29 +00:00
* @ package phpBB3
2005-04-09 12:26:45 +00:00
*/
2004-01-31 15:49:12 +00:00
class smtp_class
2003-10-11 23:51:29 +00:00
{
2004-01-31 15:49:12 +00:00
var $server_response = '' ;
var $socket = 0 ;
var $responses = array ();
var $commands = array ();
var $numeric_response_code = 0 ;
2006-09-04 20:35:46 +00:00
var $backtrace = false ;
var $backtrace_log = array ();
function smtp_class ()
{
2007-05-18 14:33:18 +00:00
// Always create a backtrace for admins to identify SMTP problems
$this -> backtrace = true ;
$this -> backtrace_log = array ();
2006-09-04 20:35:46 +00:00
}
/**
* Add backtrace message for debugging
*/
function add_backtrace ( $message )
{
if ( $this -> backtrace )
{
2007-05-18 14:33:18 +00:00
$this -> backtrace_log [] = utf8_htmlspecialchars ( $message );
2006-09-04 20:35:46 +00:00
}
}
2006-06-06 20:53:46 +00:00
/**
* Send command to smtp server
*/
2006-09-04 20:35:46 +00:00
function server_send ( $command , $private_info = false )
2004-01-31 15:49:12 +00:00
{
2004-02-01 21:45:40 +00:00
fputs ( $this -> socket , $command . " \r \n " );
2004-05-26 20:32:51 +00:00
2007-01-21 18:33:45 +00:00
( ! $private_info ) ? $this -> add_backtrace ( " # $command " ) : $this -> add_backtrace ( '# Omitting sensitive information' );
2006-09-04 20:35:46 +00:00
2004-05-26 20:32:51 +00:00
// We could put additional code here
2004-01-31 15:49:12 +00:00
}
2006-09-04 20:35:46 +00:00
2006-06-06 20:53:46 +00:00
/**
* We use the line to give the support people an indication at which command the error occurred
*/
2004-01-31 15:49:12 +00:00
function server_parse ( $response , $line )
{
2006-06-06 20:53:46 +00:00
global $user ;
2004-01-31 15:49:12 +00:00
$this -> server_response = '' ;
$this -> responses = array ();
$this -> numeric_response_code = 0 ;
while ( substr ( $this -> server_response , 3 , 1 ) != ' ' )
{
if ( ! ( $this -> server_response = fgets ( $this -> socket , 256 )))
{
2006-06-06 20:53:46 +00:00
return ( isset ( $user -> lang [ 'NO_EMAIL_RESPONSE_CODE' ])) ? $user -> lang [ 'NO_EMAIL_RESPONSE_CODE' ] : 'Could not get mail server response codes' ;
2004-01-31 15:49:12 +00:00
}
$this -> responses [] = substr ( rtrim ( $this -> server_response ), 4 );
$this -> numeric_response_code = ( int ) substr ( $this -> server_response , 0 , 3 );
2006-09-04 20:35:46 +00:00
$this -> add_backtrace ( " LINE: $line <- { $this -> server_response } " );
2004-01-31 15:49:12 +00:00
}
if ( ! ( substr ( $this -> server_response , 0 , 3 ) == $response ))
{
$this -> numeric_response_code = ( int ) substr ( $this -> server_response , 0 , 3 );
2006-06-06 20:53:46 +00:00
return ( isset ( $user -> lang [ 'EMAIL_SMTP_ERROR_RESPONSE' ])) ? sprintf ( $user -> lang [ 'EMAIL_SMTP_ERROR_RESPONSE' ], $line , $this -> server_response ) : " Ran into problems sending Mail at <strong>Line $line </strong>. Response: $this->server_response " ;
2004-01-31 15:49:12 +00:00
}
return 0 ;
}
2006-06-06 20:53:46 +00:00
/**
* Close session
*/
2006-09-04 20:35:46 +00:00
function close_session ( & $err_msg )
2004-02-01 21:45:40 +00:00
{
fclose ( $this -> socket );
2006-09-04 20:35:46 +00:00
if ( $this -> backtrace )
{
2006-12-06 17:35:04 +00:00
$message = '<h1>Backtrace</h1><p>' . implode ( '<br />' , $this -> backtrace_log ) . '</p>' ;
2006-09-04 20:35:46 +00:00
$err_msg .= $message ;
}
2004-02-01 21:45:40 +00:00
}
2008-08-16 19:06:18 +00:00
2006-06-06 20:53:46 +00:00
/**
* Log into server and get possible auth codes if neccessary
*/
2004-01-31 15:49:12 +00:00
function log_into_server ( $hostname , $username , $password , $default_auth_method )
{
2006-04-29 13:14:33 +00:00
global $user ;
2004-01-31 15:49:12 +00:00
$err_msg = '' ;
2008-03-18 14:32:49 +00:00
$local_host = ( function_exists ( 'php_uname' )) ? php_uname ( 'n' ) : $user -> host ;
2004-01-31 15:49:12 +00:00
// If we are authenticating through pop-before-smtp, we
// have to login ones before we get authenticated
2007-10-05 14:30:11 +00:00
// NOTE: on some configurations the time between an update of the auth database takes so
2006-09-04 20:35:46 +00:00
// long that the first email send does not work. This is not a biggie on a live board (only
// the install mail will most likely fail) - but on a dynamic ip connection this might produce
// severe problems and is not fixable!
2004-01-31 15:49:12 +00:00
if ( $default_auth_method == 'POP-BEFORE-SMTP' && $username && $password )
{
2006-09-04 20:35:46 +00:00
global $config ;
$errno = 0 ;
$errstr = '' ;
$this -> server_send ( " QUIT " );
fclose ( $this -> socket );
2004-01-31 15:49:12 +00:00
$result = $this -> pop_before_smtp ( $hostname , $username , $password );
$username = $password = $default_auth_method = '' ;
2006-09-04 20:35:46 +00:00
// We need to close the previous session, else the server is not
// able to get our ip for matching...
if ( ! $this -> socket = @ fsockopen ( $config [ 'smtp_host' ], $config [ 'smtp_port' ], $errno , $errstr , 10 ))
{
2007-01-06 19:37:09 +00:00
if ( $errstr )
{
$errstr = utf8_convert_message ( $errstr );
}
2006-09-04 20:35:46 +00:00
$err_msg = ( isset ( $user -> lang [ 'NO_CONNECT_TO_SMTP_HOST' ])) ? sprintf ( $user -> lang [ 'NO_CONNECT_TO_SMTP_HOST' ], $errno , $errstr ) : " Could not connect to smtp host : $errno : $errstr " ;
return $err_msg ;
}
// Wait for reply
if ( $err_msg = $this -> server_parse ( '220' , __LINE__ ))
{
$this -> close_session ( $err_msg );
return $err_msg ;
}
2004-01-31 15:49:12 +00:00
}
// Try EHLO first
2006-06-11 18:13:52 +00:00
$this -> server_send ( " EHLO { $local_host } " );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '250' , __LINE__ ))
{
// a 503 response code means that we're already authenticated
if ( $this -> numeric_response_code == 503 )
{
return false ;
}
2008-08-16 19:06:18 +00:00
// If EHLO fails, we try HELO
2006-06-11 18:13:52 +00:00
$this -> server_send ( " HELO { $local_host } " );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '250' , __LINE__ ))
{
return ( $this -> numeric_response_code == 503 ) ? false : $err_msg ;
}
}
foreach ( $this -> responses as $response )
{
$response = explode ( ' ' , $response );
$response_code = $response [ 0 ];
unset ( $response [ 0 ]);
$this -> commands [ $response_code ] = implode ( ' ' , $response );
2004-01-31 19:07:14 +00:00
}
2004-01-31 15:49:12 +00:00
// If we are not authenticated yet, something might be wrong if no username and passwd passed
if ( ! $username || ! $password )
{
return false ;
}
2008-08-16 19:06:18 +00:00
2004-01-31 15:49:12 +00:00
if ( ! isset ( $this -> commands [ 'AUTH' ]))
{
2006-06-06 20:53:46 +00:00
return ( isset ( $user -> lang [ 'SMTP_NO_AUTH_SUPPORT' ])) ? $user -> lang [ 'SMTP_NO_AUTH_SUPPORT' ] : 'SMTP server does not support authentication' ;
2004-01-31 15:49:12 +00:00
}
// Get best authentication method
2004-01-31 19:07:14 +00:00
$available_methods = explode ( ' ' , $this -> commands [ 'AUTH' ]);
2004-01-31 15:49:12 +00:00
// Define the auth ordering if the default auth method was not found
2006-04-30 12:19:11 +00:00
$auth_methods = array ( 'PLAIN' , 'LOGIN' , 'CRAM-MD5' , 'DIGEST-MD5' );
2004-01-31 15:49:12 +00:00
$method = '' ;
if ( in_array ( $default_auth_method , $available_methods ))
{
$method = $default_auth_method ;
}
else
{
foreach ( $auth_methods as $_method )
{
if ( in_array ( $_method , $available_methods ))
{
$method = $_method ;
break ;
}
}
2004-01-31 19:07:14 +00:00
}
2004-01-31 15:49:12 +00:00
if ( ! $method )
{
2006-06-06 20:53:46 +00:00
return ( isset ( $user -> lang [ 'NO_SUPPORTED_AUTH_METHODS' ])) ? $user -> lang [ 'NO_SUPPORTED_AUTH_METHODS' ] : 'No supported authentication methods' ;
2004-01-31 15:49:12 +00:00
}
$method = strtolower ( str_replace ( '-' , '_' , $method ));
return $this -> $method ( $username , $password );
}
2006-06-06 20:53:46 +00:00
/**
* Pop before smtp authentication
*/
2004-01-31 15:49:12 +00:00
function pop_before_smtp ( $hostname , $username , $password )
2003-10-11 23:51:29 +00:00
{
2006-06-06 20:53:46 +00:00
global $user ;
2006-09-04 20:35:46 +00:00
if ( ! $this -> socket = @ fsockopen ( $hostname , 110 , $errno , $errstr , 10 ))
2004-01-31 15:49:12 +00:00
{
2007-01-06 19:37:09 +00:00
if ( $errstr )
{
$errstr = utf8_convert_message ( $errstr );
}
2006-06-06 20:53:46 +00:00
return ( isset ( $user -> lang [ 'NO_CONNECT_TO_SMTP_HOST' ])) ? sprintf ( $user -> lang [ 'NO_CONNECT_TO_SMTP_HOST' ], $errno , $errstr ) : " Could not connect to smtp host : $errno : $errstr " ;
2004-01-31 15:49:12 +00:00
}
2006-06-06 20:53:46 +00:00
2006-09-04 20:35:46 +00:00
$this -> server_send ( " USER $username " , true );
if ( $err_msg = $this -> server_parse ( '+OK' , __LINE__ ))
2003-10-11 23:51:29 +00:00
{
2006-09-04 20:35:46 +00:00
return $err_msg ;
2003-10-11 23:51:29 +00:00
}
2006-09-04 20:35:46 +00:00
$this -> server_send ( " PASS $password " , true );
if ( $err_msg = $this -> server_parse ( '+OK' , __LINE__ ))
2004-01-31 15:49:12 +00:00
{
2006-09-04 20:35:46 +00:00
return $err_msg ;
2004-01-31 15:49:12 +00:00
}
2004-02-01 21:45:40 +00:00
$this -> server_send ( 'QUIT' );
2004-01-31 15:49:12 +00:00
fclose ( $this -> socket );
return false ;
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* Plain authentication method
*/
2004-01-31 15:49:12 +00:00
function plain ( $username , $password )
{
2004-02-01 21:45:40 +00:00
$this -> server_send ( 'AUTH PLAIN' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '334' , __LINE__ ))
{
return ( $this -> numeric_response_code == 503 ) ? false : $err_msg ;
}
2003-10-11 23:51:29 +00:00
2004-01-31 15:49:12 +00:00
$base64_method_plain = base64_encode ( " \0 " . $username . " \0 " . $password );
2006-09-04 20:35:46 +00:00
$this -> server_send ( $base64_method_plain , true );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '235' , __LINE__ ))
{
return $err_msg ;
}
return false ;
}
2006-06-06 20:53:46 +00:00
/**
* Login authentication method
*/
2004-01-31 15:49:12 +00:00
function login ( $username , $password )
{
2004-02-01 21:45:40 +00:00
$this -> server_send ( 'AUTH LOGIN' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '334' , __LINE__ ))
{
return ( $this -> numeric_response_code == 503 ) ? false : $err_msg ;
}
2006-09-04 20:35:46 +00:00
$this -> server_send ( base64_encode ( $username ), true );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '334' , __LINE__ ))
{
return $err_msg ;
}
2006-09-04 20:35:46 +00:00
$this -> server_send ( base64_encode ( $password ), true );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '235' , __LINE__ ))
{
return $err_msg ;
}
return false ;
}
2006-06-06 20:53:46 +00:00
/**
* cram_md5 authentication method
*/
2004-01-31 15:49:12 +00:00
function cram_md5 ( $username , $password )
2003-10-11 23:51:29 +00:00
{
2004-02-01 21:45:40 +00:00
$this -> server_send ( 'AUTH CRAM-MD5' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '334' , __LINE__ ))
{
return ( $this -> numeric_response_code == 503 ) ? false : $err_msg ;
}
$md5_challenge = base64_decode ( $this -> responses [ 0 ]);
$password = ( strlen ( $password ) > 64 ) ? pack ( 'H32' , md5 ( $password )) : (( strlen ( $password ) < 64 ) ? str_pad ( $password , 64 , chr ( 0 )) : $password );
$md5_digest = md5 (( substr ( $password , 0 , 64 ) ^ str_repeat ( chr ( 0x5C ), 64 )) . ( pack ( 'H32' , md5 (( substr ( $password , 0 , 64 ) ^ str_repeat ( chr ( 0x36 ), 64 )) . $md5_challenge ))));
$base64_method_cram_md5 = base64_encode ( $username . ' ' . $md5_digest );
2006-09-04 20:35:46 +00:00
$this -> server_send ( $base64_method_cram_md5 , true );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '235' , __LINE__ ))
{
return $err_msg ;
}
return false ;
2003-10-11 23:51:29 +00:00
}
2006-06-06 20:53:46 +00:00
/**
* digest_md5 authentication method
* A real pain in the ***
*/
2004-01-31 15:49:12 +00:00
function digest_md5 ( $username , $password )
{
2006-06-06 20:53:46 +00:00
global $config , $user ;
2004-01-31 15:49:12 +00:00
2004-02-01 21:45:40 +00:00
$this -> server_send ( 'AUTH DIGEST-MD5' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '334' , __LINE__ ))
{
return ( $this -> numeric_response_code == 503 ) ? false : $err_msg ;
}
$md5_challenge = base64_decode ( $this -> responses [ 0 ]);
2008-08-16 19:06:18 +00:00
2004-02-21 12:47:35 +00:00
// Parse the md5 challenge - from AUTH_SASL (PEAR)
2004-01-31 15:49:12 +00:00
$tokens = array ();
while ( preg_match ( '/^([a-z-]+)=("[^"]+(?<!\\\)"|[^,]+)/i' , $md5_challenge , $matches ))
{
// Ignore these as per rfc2831
if ( $matches [ 1 ] == 'opaque' || $matches [ 1 ] == 'domain' )
{
$md5_challenge = substr ( $md5_challenge , strlen ( $matches [ 0 ]) + 1 );
continue ;
}
// Allowed multiple "realm" and "auth-param"
if ( ! empty ( $tokens [ $matches [ 1 ]]) && ( $matches [ 1 ] == 'realm' || $matches [ 1 ] == 'auth-param' ))
{
if ( is_array ( $tokens [ $matches [ 1 ]]))
{
$tokens [ $matches [ 1 ]][] = preg_replace ( '/^"(.*)"$/' , '\\1' , $matches [ 2 ]);
}
else
{
2004-01-31 19:07:14 +00:00
$tokens [ $matches [ 1 ]] = array ( $tokens [ $matches [ 1 ]], preg_replace ( '/^"(.*)"$/' , '\\1' , $matches [ 2 ]));
}
2007-10-05 14:30:11 +00:00
}
2004-01-31 15:49:12 +00:00
else if ( ! empty ( $tokens [ $matches [ 1 ]])) // Any other multiple instance = failure
{
$tokens = array ();
break ;
}
else
{
$tokens [ $matches [ 1 ]] = preg_replace ( '/^"(.*)"$/' , '\\1' , $matches [ 2 ]);
}
// Remove the just parsed directive from the challenge
$md5_challenge = substr ( $md5_challenge , strlen ( $matches [ 0 ]) + 1 );
}
// Realm
if ( empty ( $tokens [ 'realm' ]))
{
2008-03-18 14:32:49 +00:00
$tokens [ 'realm' ] = ( function_exists ( 'php_uname' )) ? php_uname ( 'n' ) : $user -> host ;
2004-01-31 15:49:12 +00:00
}
2006-04-29 13:14:33 +00:00
2004-01-31 15:49:12 +00:00
// Maxbuf
if ( empty ( $tokens [ 'maxbuf' ]))
{
$tokens [ 'maxbuf' ] = 65536 ;
}
2004-01-31 19:07:14 +00:00
2004-01-31 15:49:12 +00:00
// Required: nonce, algorithm
if ( empty ( $tokens [ 'nonce' ]) || empty ( $tokens [ 'algorithm' ]))
{
2004-01-31 19:07:14 +00:00
$tokens = array ();
}
$md5_challenge = $tokens ;
2004-01-31 15:49:12 +00:00
if ( ! empty ( $md5_challenge ))
{
$str = '' ;
for ( $i = 0 ; $i < 32 ; $i ++ )
{
$str .= chr ( mt_rand ( 0 , 255 ));
2004-01-31 19:07:14 +00:00
}
$cnonce = base64_encode ( $str );
2004-01-31 15:49:12 +00:00
2004-01-31 19:07:14 +00:00
$digest_uri = 'smtp/' . $config [ 'smtp_host' ];
2004-01-31 15:49:12 +00:00
$auth_1 = sprintf ( '%s:%s:%s' , pack ( 'H32' , md5 ( sprintf ( '%s:%s:%s' , $username , $md5_challenge [ 'realm' ], $password ))), $md5_challenge [ 'nonce' ], $cnonce );
$auth_2 = 'AUTHENTICATE:' . $digest_uri ;
$response_value = md5 ( sprintf ( '%s:%s:00000001:%s:auth:%s' , md5 ( $auth_1 ), $md5_challenge [ 'nonce' ], $cnonce , md5 ( $auth_2 )));
$input_string = sprintf ( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc="00000001",qop=auth,digest-uri="%s",response=%s,%d' , $username , $md5_challenge [ 'realm' ], $md5_challenge [ 'nonce' ], $cnonce , $digest_uri , $response_value , $md5_challenge [ 'maxbuf' ]);
2004-01-31 19:07:14 +00:00
}
2004-01-31 15:49:12 +00:00
else
{
2006-06-06 20:53:46 +00:00
return ( isset ( $user -> lang [ 'INVALID_DIGEST_CHALLENGE' ])) ? $user -> lang [ 'INVALID_DIGEST_CHALLENGE' ] : 'Invalid digest challenge' ;
2004-01-31 19:07:14 +00:00
}
2006-06-06 20:53:46 +00:00
2004-01-31 15:49:12 +00:00
$base64_method_digest_md5 = base64_encode ( $input_string );
2006-09-04 20:35:46 +00:00
$this -> server_send ( $base64_method_digest_md5 , true );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '334' , __LINE__ ))
{
return $err_msg ;
}
2004-02-01 21:45:40 +00:00
$this -> server_send ( ' ' );
2004-01-31 15:49:12 +00:00
if ( $err_msg = $this -> server_parse ( '235' , __LINE__ ))
{
return $err_msg ;
}
2006-06-06 20:53:46 +00:00
2004-01-31 15:49:12 +00:00
return false ;
}
2003-10-11 23:51:29 +00:00
}
2005-04-09 12:26:45 +00:00
/**
2006-11-23 11:53:52 +00:00
* Encodes the given string for proper display in UTF - 8.
2006-11-11 12:24:10 +00:00
*
2006-11-11 16:20:11 +00:00
* This version is using base64 encoded data . The downside of this
2006-11-11 12:24:10 +00:00
* is if the mail client does not understand this encoding the user
* is basically doomed with an unreadable subject .
2006-11-23 11:53:52 +00:00
*
2006-11-23 14:54:37 +00:00
* Please note that this version fully supports RFC 2045 section 6.8 .
2005-04-09 12:26:45 +00:00
*/
2006-11-23 14:54:37 +00:00
function mail_encode ( $str )
2003-10-12 11:59:23 +00:00
{
// define start delimimter, end delimiter and spacer
2006-11-23 14:54:37 +00:00
$start = " =?UTF-8?B? " ;
$end = " ?= " ;
$spacer = $end . ' ' . $start ;
$split_length = 64 ;
2003-10-12 11:59:23 +00:00
2006-11-23 11:53:52 +00:00
$encoded_str = base64_encode ( $str );
2006-11-23 14:54:37 +00:00
// If encoded string meets the limits, we just return with the correct data.
if ( strlen ( $encoded_str ) <= $split_length )
2006-11-23 11:53:52 +00:00
{
return $start . $encoded_str . $end ;
}
2006-11-23 14:54:37 +00:00
// If there is only ASCII data, we just return what we want, correctly splitting the lines.
2006-11-23 12:44:12 +00:00
if ( strlen ( $str ) === utf8_strlen ( $str ))
{
return $start . implode ( $spacer , str_split ( $encoded_str , $split_length )) . $end ;
}
2006-11-23 14:54:37 +00:00
// UTF-8 data, compose encoded lines
$array = utf8_str_split ( $str );
$str = '' ;
2003-10-12 11:59:23 +00:00
2006-11-23 14:54:37 +00:00
while ( sizeof ( $array ))
2006-11-23 11:53:52 +00:00
{
2006-11-23 14:54:37 +00:00
$text = '' ;
2003-10-12 11:59:23 +00:00
2006-12-02 16:52:17 +00:00
while ( sizeof ( $array ) && intval (( strlen ( $text . $array [ 0 ]) + 2 ) / 3 ) << 2 <= $split_length )
2006-11-23 11:53:52 +00:00
{
2006-11-23 14:54:37 +00:00
$text .= array_shift ( $array );
2006-11-23 11:53:52 +00:00
}
2006-11-23 14:54:37 +00:00
$str .= $start . base64_encode ( $text ) . $end . ' ' ;
2006-11-23 11:53:52 +00:00
}
2003-10-12 11:59:23 +00:00
2006-11-23 14:54:37 +00:00
return substr ( $str , 0 , - 1 );
2003-10-12 11:59:23 +00:00
}
2003-10-11 23:51:29 +00:00
?>