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
2007-06-09 11:11:20 +00:00
* @ copyright ( c ) 2005 phpBB Group
2011-12-31 13:32:52 +00:00
* @ license http :// opensource . org / licenses / gpl - 2.0 . php GNU General Public License v2
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
{
2013-07-24 13:38:12 -05:00
var $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 ;
2009-07-22 09:07:24 +00:00
2013-09-10 14:01:09 +02:00
/** @var \phpbb\template\template */
2013-07-01 21:18:09 -05:00
protected $template ;
2009-03-11 16:23:12 +00:00
var $eol = " \n " ;
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 = '' ;
2009-03-11 16:23:12 +00:00
// Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac)
$this -> eol = ( ! defined ( 'PHP_EOL' )) ? (( $eol = strtolower ( substr ( PHP_OS , 0 , 3 ))) == 'win' ) ? " \r \n " : (( $eol == 'mac' ) ? " \r " : " \n " ) : PHP_EOL ;
2009-04-08 16:40:39 +00:00
$this -> eol = ( ! $this -> eol ) ? " \n " : $this -> eol ;
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 ();
2013-07-24 13:38:12 -05:00
$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
}
2013-06-12 13:29:57 -05:00
2013-04-24 10:38:57 -05:00
/**
* Set addresses for to / im as available
2013-06-12 13:29:57 -05:00
*
2013-04-24 10:38:57 -05:00
* @ param array $user User row
*/
function set_addresses ( $user )
{
2013-04-24 20:28:35 -05:00
if ( isset ( $user [ 'user_email' ]) && $user [ 'user_email' ])
2013-04-24 10:38:57 -05:00
{
2013-04-24 20:28:35 -05:00
$this -> to ( $user [ 'user_email' ], ( isset ( $user [ 'username' ]) ? $user [ 'username' ] : '' ));
2013-04-24 10:38:57 -05:00
}
2013-04-24 20:28:35 -05:00
if ( isset ( $user [ 'user_jabber' ]) && $user [ 'user_jabber' ])
2013-04-24 10:38:57 -05:00
{
2013-04-24 20:28:35 -05:00
$this -> im ( $user [ 'user_jabber' ], ( isset ( $user [ 'username' ]) ? $user [ 'username' ] : '' ));
2013-04-24 10:38:57 -05:00
}
}
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 ;
2009-03-17 15:50:19 +00:00
if ( ! trim ( $address ))
{
return ;
}
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 = '' )
{
2009-03-17 15:50:19 +00:00
if ( ! trim ( $address ))
{
return ;
}
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 = '' )
{
2009-03-17 15:50:19 +00:00
if ( ! trim ( $address ))
{
return ;
}
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 = '' )
{
2008-11-22 19:55:00 +00:00
// IM-Addresses could be empty
2009-03-17 15:50:19 +00:00
if ( ! trim ( $address ))
2008-11-22 19:55:00 +00:00
{
return ;
}
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
}
2011-11-20 04:15:44 -05:00
/**
* Adds X - AntiAbuse headers
2011-11-20 16:35:31 +01:00
*
* @ param array $config Configuration array
* @ param user $user A user object
*
* @ return null
2011-11-20 04:15:44 -05:00
*/
2011-11-20 16:35:31 +01:00
function anti_abuse_headers ( $config , $user )
2011-11-20 04:15:44 -05:00
{
2011-11-20 04:17:42 -05:00
$this -> headers ( 'X-AntiAbuse: Board servername - ' . mail_encode ( $config [ 'server_name' ]));
2011-11-20 04:15:44 -05:00
$this -> headers ( 'X-AntiAbuse: User_id - ' . $user -> data [ 'user_id' ]);
2011-11-20 04:17:42 -05:00
$this -> headers ( 'X-AntiAbuse: Username - ' . mail_encode ( $user -> data [ 'username' ]));
2011-11-20 04:15:44 -05:00
$this -> headers ( 'X-AntiAbuse: User IP - ' . $user -> ip );
}
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
*/
2009-08-11 16:24:18 +00:00
function template ( $template_file , $template_lang = '' , $template_path = '' )
2003-10-11 23:51:29 +00:00
{
2011-08-30 01:32:11 -04:00
global $config , $phpbb_root_path , $phpEx , $user , $phpbb_extension_manager ;
2003-10-11 23:51:29 +00:00
2013-07-01 21:18:09 -05:00
$this -> setup_template ();
2003-10-11 23:51:29 +00:00
if ( ! trim ( $template_file ))
{
2009-07-22 09:07:24 +00:00
trigger_error ( 'No template file for emailing set.' , E_USER_ERROR );
2003-10-11 23:51:29 +00:00
}
Do not store email templates in database. [Bug #54505]
To explain what this is about, first a short phpBB code history lesson: ;-)
r9823 originally introduced the usage of our template class for emails. The
messenger class uses set_custom_template() to initialise the template object
which neither disables storedb nor inheritance. These two values are set in
$user->theme rather than inside a particular template instance (quite a design
failure if I may add). Thus the html page that is displayed to the user also
determines these settings for the email templates. This obviously causes
problems because both emails and other custom templates can quite simply not
be stored in the database because the db table only stores the filename, not
the path and requires a template id.
r9839 then generally disabled storedb and template inheritance for custom
templates to fix Bug #40515. This works for custom templates, but not for
emails where lots of template objects are created. In such a situation the
last call to set(_custom)_template() would now determine the values of storedb
and inheritance in _tpl_load. So any page sending emails would neither load
its template from the database nor use template inheritance. The same revision
also introduced orig_tpl_* variables in set_template() which on their own are
very much pointless, but could allow resetting the storedb and inheritance
values if they were used to reset $user->theme just before template execution
in _tpl_load.
In r10150 these orig_tpl_* variables are correctly used to access information
about the template of the page being displayed - contrary to the last template
used - from within the bbcode, fixing Bug #51285. However r10150 also introduces
a pointless $template_mode parameter for set_custom_template(). $template_mode
is really just a boolean flag (value you can be 'template' or an arbitrary other
value) that if it set circumvents the unsetting of storedb and template
inheritance. The very code that had been added to prevent issues with emails and
custom templates. Fixing the problem introduced by r8839 but at the same time
reintroducing the much greater problem from the original implementation of email
templates.
And now an explanation of what I did:
Based on this I have now changed the set_custom_template method to always
disable storedb. It can now properly use inheritance, you simply tell it the
path where the parent template can be found, by default the path is false which
will turn inheritance off. To make this work the template class now always
overwrites $user->theme storedb and inheritance variabbles with orig_tpl_* just
before rendering a template in _tpl_load. This way they are guaranteed to always
contain the value they had at the time set_template/set_custom_template were
called. This fixes [Bug #54505].
In summary, using global state is simply a horrible idea in object oriented
programming. Always Pass values, that an object depends on, as parameters - never
through magic global variables. Following this principle will safe you from a lot
of headaches.
Please test this patch as much as possible to make sure templates still work
properly for you, focus on multiple languages, missing language files, and
custom templates in systems that make use of the template class outside of
phpBB itself.
git-svn-id: file:///svn/phpbb/branches/phpBB-3_0_0@10460 89ea8834-ac86-4346-8a33-228a782c2dd0
2010-01-26 16:52:46 +00:00
if ( ! trim ( $template_lang ))
2003-10-11 23:51:29 +00:00
{
2010-01-26 03:43:02 +00:00
// fall back to board default language if the user's language is
// missing $template_file. If this does not exist either,
2013-07-01 21:18:09 -05:00
// $this->template->set_filenames will do a trigger_error
2010-01-26 03:43:02 +00:00
$template_lang = basename ( $config [ 'default_lang' ]);
2003-10-11 23:51:29 +00:00
}
2013-07-01 21:18:09 -05:00
if ( $template_path )
2003-10-11 23:51:29 +00:00
{
2013-07-01 21:18:09 -05:00
$template_paths = array (
$template_path ,
);
}
2013-07-01 21:32:10 -05:00
else
2013-07-01 21:18:09 -05:00
{
$template_path = ( ! empty ( $user -> lang_path )) ? $user -> lang_path : $phpbb_root_path . 'language/' ;
$template_path .= $template_lang . '/email' ;
2003-10-11 23:51:29 +00:00
2013-07-01 21:18:09 -05:00
$template_paths = array (
$template_path ,
);
Do not store email templates in database. [Bug #54505]
To explain what this is about, first a short phpBB code history lesson: ;-)
r9823 originally introduced the usage of our template class for emails. The
messenger class uses set_custom_template() to initialise the template object
which neither disables storedb nor inheritance. These two values are set in
$user->theme rather than inside a particular template instance (quite a design
failure if I may add). Thus the html page that is displayed to the user also
determines these settings for the email templates. This obviously causes
problems because both emails and other custom templates can quite simply not
be stored in the database because the db table only stores the filename, not
the path and requires a template id.
r9839 then generally disabled storedb and template inheritance for custom
templates to fix Bug #40515. This works for custom templates, but not for
emails where lots of template objects are created. In such a situation the
last call to set(_custom)_template() would now determine the values of storedb
and inheritance in _tpl_load. So any page sending emails would neither load
its template from the database nor use template inheritance. The same revision
also introduced orig_tpl_* variables in set_template() which on their own are
very much pointless, but could allow resetting the storedb and inheritance
values if they were used to reset $user->theme just before template execution
in _tpl_load.
In r10150 these orig_tpl_* variables are correctly used to access information
about the template of the page being displayed - contrary to the last template
used - from within the bbcode, fixing Bug #51285. However r10150 also introduces
a pointless $template_mode parameter for set_custom_template(). $template_mode
is really just a boolean flag (value you can be 'template' or an arbitrary other
value) that if it set circumvents the unsetting of storedb and template
inheritance. The very code that had been added to prevent issues with emails and
custom templates. Fixing the problem introduced by r8839 but at the same time
reintroducing the much greater problem from the original implementation of email
templates.
And now an explanation of what I did:
Based on this I have now changed the set_custom_template method to always
disable storedb. It can now properly use inheritance, you simply tell it the
path where the parent template can be found, by default the path is false which
will turn inheritance off. To make this work the template class now always
overwrites $user->theme storedb and inheritance variabbles with orig_tpl_* just
before rendering a template in _tpl_load. This way they are guaranteed to always
contain the value they had at the time set_template/set_custom_template were
called. This fixes [Bug #54505].
In summary, using global state is simply a horrible idea in object oriented
programming. Always Pass values, that an object depends on, as parameters - never
through magic global variables. Following this principle will safe you from a lot
of headaches.
Please test this patch as much as possible to make sure templates still work
properly for you, focus on multiple languages, missing language files, and
custom templates in systems that make use of the template class outside of
phpBB itself.
git-svn-id: file:///svn/phpbb/branches/phpBB-3_0_0@10460 89ea8834-ac86-4346-8a33-228a782c2dd0
2010-01-26 16:52:46 +00:00
2013-07-01 21:18:09 -05:00
// we can only specify default language fallback when the path is not a custom one for which we
// do not know the default language alternative
if ( $template_lang !== basename ( $config [ 'default_lang' ]))
2009-08-11 16:24:18 +00:00
{
2013-07-01 21:18:09 -05:00
$fallback_template_path = ( ! empty ( $user -> lang_path )) ? $user -> lang_path : $phpbb_root_path . 'language/' ;
$fallback_template_path .= basename ( $config [ 'default_lang' ]) . '/email' ;
$template_paths [] = $fallback_template_path ;
2009-08-11 16:24:18 +00:00
}
2013-07-01 21:18:09 -05:00
}
2003-10-11 23:51:29 +00:00
2013-07-01 21:18:09 -05:00
$this -> set_template_paths ( $template_lang . '_email' , $template_paths );
2003-10-11 23:51:29 +00:00
2013-07-01 21:18:09 -05:00
$this -> template -> set_filenames ( array (
'body' => $template_file . '.txt' ,
));
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 )
{
2013-07-01 21:18:09 -05:00
$this -> setup_template ();
2009-07-22 09:07:24 +00:00
2013-07-01 21:18:09 -05:00
$this -> template -> assign_vars ( $vars );
2009-07-22 09:07:24 +00:00
}
function assign_block_vars ( $blockname , $vars )
{
2013-07-01 21:18:09 -05:00
$this -> setup_template ();
2009-07-22 09:07:24 +00:00
2013-07-01 21:18:09 -05:00
$this -> template -> assign_block_vars ( $blockname , $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
2013-07-24 13:38:12 -05:00
$this -> assign_vars ( array (
'U_BOARD' => generate_board_url (),
'EMAIL_SIG' => str_replace ( '<br />' , " \n " , " -- \n " . htmlspecialchars_decode ( $config [ 'board_email_sig' ])),
'SITENAME' => htmlspecialchars_decode ( $config [ 'sitename' ]),
));
2003-10-11 23:51:29 +00:00
2009-07-22 09:07:24 +00:00
// Parse message through template
2013-07-01 21:18:09 -05:00
$this -> msg = trim ( $this -> template -> assign_display ( 'body' ));
2003-10-11 23:51:29 +00:00
2009-08-25 09:04:38 +00:00
// Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding
$this -> msg = str_replace ( " \r \n " , " \n " , $this -> msg );
2003-10-11 23:51:29 +00:00
// 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 )
{
2011-07-13 19:20:16 +02:00
global $user , $phpEx , $phpbb_root_path , $config , $request ;
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
2011-08-18 23:38:39 +02:00
$calling_page = htmlspecialchars_decode ( $request -> server ( 'PHP_SELF' ));
2006-12-06 17:35:04 +00:00
$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
2013-02-24 19:07:24 +01:00
/**
* Generates a valid message id to be used in emails
*
* @ return string message id
*/
function generate_message_id ()
{
global $config ;
$domain = 'phpbb.generated' ;
if ( $config [ 'server_name' ])
{
$domain = $config [ 'server_name' ];
}
else if ( ! empty ( $_SERVER [ 'SERVER_NAME' ]))
{
$domain = $_SERVER [ 'SERVER_NAME' ];
}
return md5 ( unique_id ( time ())) . '@' . $domain ;
}
2006-11-11 12:24:10 +00:00
/**
* Return email header
*/
function build_header ( $to , $cc , $bcc )
{
global $config ;
2009-03-11 16:23:12 +00:00
// We could use keys here, but we won't do this for 3.0.x to retain backwards compatibility
2006-11-11 12:24:10 +00:00
$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' ;
2013-02-24 19:07:24 +01:00
$headers [] = 'Message-ID: <' . $this -> generate_message_id () . '>' ;
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' ));
2009-08-18 09:59:24 +00:00
$headers [] = 'X-Mailer: phpBB3' ;
2006-11-11 12:24:10 +00:00
$headers [] = 'X-MimeOLE: phpBB3' ;
$headers [] = 'X-phpBB-Origin: phpbb://' . str_replace ( array ( 'http://' , 'https://' ), array ( '' , '' ), generate_board_url ());
if ( sizeof ( $this -> extra_headers ))
{
2009-03-11 16:23:12 +00:00
$headers = array_merge ( $headers , $this -> extra_headers );
2006-11-11 12:24:10 +00:00
}
2009-03-11 16:23:12 +00:00
return $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 ;
}
2009-03-17 15:50:19 +00:00
// Addresses to send to?
if ( empty ( $this -> addresses ) || ( empty ( $this -> addresses [ 'to' ]) && empty ( $this -> addresses [ 'cc' ]) && empty ( $this -> addresses [ 'bcc' ])))
{
// Send was successful. ;)
return true ;
}
2003-10-11 23:51:29 +00:00
$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 ;
}
2014-04-23 17:45:09 +02:00
$board_contact = (( $config [ 'board_contact_name' ] !== '' ) ? '"' . mail_encode ( $config [ 'board_contact_name' ]) . '" ' : '' ) . '<' . $config [ 'board_contact' ] . '>' ;
2014-04-17 21:59:23 +02:00
2006-11-11 12:24:10 +00:00
if ( empty ( $this -> replyto ))
{
2014-04-17 21:59:23 +02:00
$this -> replyto = $board_contact ;
2006-11-11 12:24:10 +00:00
}
if ( empty ( $this -> from ))
{
2014-04-17 21:59:23 +02:00
$this -> from = $board_contact ;
2006-11-11 12:24:10 +00:00
}
2009-06-03 16:29:26 +00:00
$encode_eol = ( $config [ 'smtp_delivery' ]) ? " \r \n " : $this -> eol ;
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 )
{
2009-08-18 01:43:51 +00:00
$$type .= (( $$type != '' ) ? ', ' : '' ) . (( $which_ary [ 'name' ] != '' ) ? mail_encode ( $which_ary [ 'name' ], $encode_eol ) . ' <' . $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
{
2009-08-18 09:59:24 +00:00
$result = phpbb_mail ( $mail_to , $this -> subject , $this -> msg , $headers , $this -> eol , $err_msg );
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 ;
}
2008-11-22 19:55:00 +00:00
if ( empty ( $this -> addresses [ 'im' ]))
{
2009-03-17 15:50:19 +00:00
// Send was successful. ;)
return true ;
2008-11-22 19:55:00 +00:00
}
2003-10-11 23:51:29 +00:00
$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 );
2011-12-19 14:24:39 +01:00
$this -> jabber = new jabber ( $config [ 'jab_host' ], $config [ 'jab_port' ], $config [ 'jab_username' ], htmlspecialchars_decode ( $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 ;
}
2013-07-01 21:18:09 -05:00
/**
* Setup template engine
*/
protected function setup_template ()
{
2013-09-26 15:34:44 +02:00
global $config , $phpbb_path_helper , $user , $phpbb_extension_manager ;
2013-07-01 21:18:09 -05:00
2013-09-10 14:01:09 +02:00
if ( $this -> template instanceof \phpbb\template\template )
2013-07-01 21:18:09 -05:00
{
return ;
}
2013-09-26 15:34:44 +02:00
$this -> template = new \phpbb\template\twig\twig ( $phpbb_path_helper , $config , $user , new \phpbb\template\context (), $phpbb_extension_manager );
2013-07-01 21:18:09 -05:00
}
/**
* Set template paths to load
*/
protected function set_template_paths ( $path_name , $paths )
{
$this -> setup_template ();
2013-07-24 13:25:20 -05:00
$this -> template -> set_custom_style ( $path_name , $paths );
2013-07-01 21:18:09 -05:00
}
2003-10-11 23:51:29 +00:00
}
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 = '' ;
2009-04-08 18:08:54 +00:00
var $eol = " \n " ;
2003-10-11 23:51:29 +00:00
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 " ;
2009-04-08 18:08:54 +00:00
// Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac)
$this -> eol = ( ! defined ( 'PHP_EOL' )) ? (( $eol = strtolower ( substr ( PHP_OS , 0 , 3 ))) == 'win' ) ? " \r \n " : (( $eol == 'mac' ) ? " \r " : " \n " ) : PHP_EOL ;
$this -> eol = ( ! $this -> eol ) ? " \n " : $this -> eol ;
2003-10-11 23:51:29 +00:00
}
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
2013-09-10 14:01:09 +02:00
$lock = new \phpbb\lock\flock ( $this -> cache_file );
2012-12-04 02:00:27 -05:00
$lock -> acquire ();
2003-10-11 23:51:29 +00:00
2012-12-05 00:57:24 -05:00
// avoid races, check file existence once
$have_cache_file = file_exists ( $this -> cache_file );
if ( ! $have_cache_file || $config [ 'last_queue_run' ] > time () - $config [ 'queue_interval' ])
2003-10-11 23:51:29 +00:00
{
2012-12-05 00:57:24 -05:00
if ( ! $have_cache_file )
2012-12-05 00:41:47 -05:00
{
set_config ( 'last_queue_run' , time (), true );
}
2012-12-04 02:00:27 -05:00
$lock -> release ();
2003-10-11 23:51:29 +00:00
return ;
}
2012-12-05 00:41:47 -05:00
set_config ( 'last_queue_run' , time (), true );
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
2010-07-22 10:44:31 -05:00
/*
* This code is commented out because it causes problems on some web hosts .
* The core problem is rather restrictive email sending limits .
* This code is nly useful if you have no such restrictions from the
* web host and the package size setting is wrong .
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' ]);
}
2010-07-22 10:44:31 -05:00
*/
2007-08-13 12:14:07 +00:00
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 );
2011-12-19 14:24:39 +01:00
$this -> jabber = new jabber ( $config [ 'jab_host' ], $config [ 'jab_port' ], $config [ 'jab_username' ], htmlspecialchars_decode ( $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
{
2014-03-09 22:03:38 +01:00
$messenger = new messenger ();
$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
{
2014-03-09 22:03:38 +01:00
$messenger = new messenger ();
$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 :
2012-12-04 02:00:27 -05:00
$lock -> release ();
2003-10-11 23:51:29 +00:00
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
{
2009-08-18 09:59:24 +00:00
$result = phpbb_mail ( $to , $subject , $msg , $headers , $this -> eol , $err_msg );
2007-01-04 16:07:38 +00:00
}
2003-10-11 23:51:29 +00:00
if ( ! $result )
{
2014-03-09 22:03:38 +01:00
$messenger = new messenger ();
$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
{
2014-03-09 22:03:38 +01:00
$messenger = new messenger ();
$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
{
2008-10-06 05:50:16 +00:00
if ( $fp = @ fopen ( $this -> cache_file , 'wb' ))
2003-10-11 23:51:29 +00:00
{
2009-03-11 12:53:54 +00:00
fwrite ( $fp , " <?php \n if (!defined('IN_PHPBB')) exit; \n \$ this->queue_data = unserialize( " . var_export ( serialize ( $this -> queue_data ), true ) . " ); \n \n ?> " );
2003-10-11 23:51:29 +00:00
fclose ( $fp );
2007-06-30 15:04:49 +00:00
2008-12-19 20:36:18 +00:00
phpbb_chmod ( $this -> cache_file , CHMOD_READ | CHMOD_WRITE );
2003-10-11 23:51:29 +00:00
}
}
2012-12-04 02:00:27 -05:00
$lock -> release ();
2003-10-11 23:51:29 +00:00
}
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
2013-09-10 14:01:09 +02:00
$lock = new \phpbb\lock\flock ( $this -> cache_file );
2012-12-04 02:00:27 -05:00
$lock -> acquire ();
2010-04-20 06:53:52 -04: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
{
2009-03-11 12:53:54 +00:00
fwrite ( $fp , " <?php \n if (!defined('IN_PHPBB')) exit; \n \$ this->queue_data = unserialize( " . var_export ( serialize ( $this -> data ), true ) . " ); \n \n ?> " );
2003-10-11 23:51:29 +00:00
fclose ( $fp );
2007-06-30 15:04:49 +00:00
2008-12-19 20:36:18 +00:00
phpbb_chmod ( $this -> cache_file , CHMOD_READ | CHMOD_WRITE );
2003-10-11 23:51:29 +00:00
}
2010-04-20 06:53:52 -04:00
2012-12-04 02:00:27 -05:00
$lock -> release ();
2003-10-11 23:51:29 +00:00
}
}
2005-04-09 12:26:45 +00:00
/**
* Replacement or substitute for PHP ' s mail command
*/
2009-03-11 16:23:12 +00:00
function smtpmail ( $addresses , $subject , $message , & $err_msg , $headers = false )
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 );
2009-03-11 16:23:12 +00:00
if ( $headers !== false )
2003-10-11 23:51:29 +00:00
{
2009-03-11 16:23:12 +00:00
if ( ! is_array ( $headers ))
2003-10-11 23:51:29 +00:00
{
2009-03-11 16:23:12 +00:00
// Make sure there are no bare linefeeds in the headers
$headers = preg_replace ( '#(?<!\r)\n#si' , " \n " , $headers );
$headers = explode ( " \n " , $headers );
2003-10-11 23:51:29 +00:00
}
// 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
2009-03-11 16:23:12 +00:00
$headers_used = array ();
2006-12-31 16:56:15 +00:00
2009-03-11 16:23:12 +00:00
foreach ( $headers as $header )
2003-10-11 23:51:29 +00:00
{
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
{
2009-03-11 16:23:12 +00:00
continue ;
2003-10-11 23:51:29 +00:00
}
2009-03-11 16:23:12 +00:00
$headers_used [] = trim ( $header );
2003-10-11 23:51:29 +00:00
}
2009-03-11 16:23:12 +00:00
$headers = chop ( implode ( " \r \n " , $headers_used ));
2003-10-11 23:51:29 +00:00
}
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.
2013-09-10 14:01:09 +02:00
if ( ! class_exists ( '\phpbb\error_collector' ))
2011-08-26 01:53:52 +02:00
{
global $phpbb_root_path , $phpEx ;
include ( $phpbb_root_path . 'includes/error_collector.' . $phpEx );
}
2013-09-10 14:01:09 +02:00
$collector = new \phpbb\error_collector ;
2011-08-26 01:53:52 +02:00
$collector -> install ();
2007-07-19 20:38:38 +00:00
$smtp -> socket = fsockopen ( $config [ 'smtp_host' ], $config [ 'smtp_port' ], $errno , $errstr , 20 );
2011-08-26 01:53:52 +02:00
$collector -> uninstall ();
$error_contents = $collector -> format_errors ();
2007-07-19 20:38:38 +00:00
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
2011-12-19 14:24:39 +01:00
if ( $err_msg = $smtp -> log_into_server ( $config [ 'smtp_host' ], $config [ 'smtp_username' ], htmlspecialchars_decode ( $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....
2009-03-11 16:23:12 +00:00
if ( $headers !== false )
{
$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 ;
2011-08-22 23:50:02 +02:00
protected $socket_tls = false ;
2004-01-31 15:49:12 +00:00
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 = '' ;
2009-09-22 15:09:09 +00:00
// Here we try to determine the *real* hostname (reverse DNS entry preferrably)
$local_host = $user -> host ;
if ( function_exists ( 'php_uname' ))
{
$local_host = php_uname ( 'n' );
// Able to resolve name to IP
if (( $addr = @ gethostbyname ( $local_host )) !== $local_host )
{
// Able to resolve IP back to name
if (( $name = @ gethostbyaddr ( $addr )) !== $addr )
{
$local_host = $name ;
}
}
}
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
}
2011-08-22 23:33:34 +02:00
$hello_result = $this -> hello ( $local_host );
if ( ! is_null ( $hello_result ))
2004-01-31 15:49:12 +00:00
{
2011-08-22 23:33:34 +02:00
return $hello_result ;
2004-01-31 19:07:14 +00:00
}
2004-01-31 15:49:12 +00:00
2011-08-22 23:50:02 +02:00
// SMTP STARTTLS (RFC 3207)
if ( ! $this -> socket_tls )
{
$this -> socket_tls = $this -> starttls ();
if ( $this -> socket_tls )
{
// Switched to TLS
// RFC 3207: "The client MUST discard any knowledge obtained from the server, [...]"
// So say hello again
$hello_result = $this -> hello ( $local_host );
if ( ! is_null ( $hello_result ))
{
return $hello_result ;
}
}
}
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 );
}
2011-08-22 23:33:34 +02:00
/**
* SMTP EHLO / HELO
*
* @ return mixed Null if the authentication process is supposed to continue
* False if already authenticated
* Error message ( string ) otherwise
*/
protected function hello ( $hostname )
{
// Try EHLO first
$this -> server_send ( " EHLO $hostname " );
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 ;
}
// If EHLO fails, we try HELO
$this -> server_send ( " HELO $hostname " );
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 );
}
}
2011-08-22 23:50:02 +02:00
/**
* SMTP STARTTLS ( RFC 3207 )
*
* @ return bool Returns true if TLS was started
* Otherwise false
*/
protected function starttls ()
{
if ( ! function_exists ( 'stream_socket_enable_crypto' ))
{
return false ;
}
if ( ! isset ( $this -> commands [ 'STARTTLS' ]))
{
return false ;
}
$this -> server_send ( 'STARTTLS' );
if ( $err_msg = $this -> server_parse ( '220' , __LINE__ ))
{
return false ;
}
$result = false ;
$stream_meta = stream_get_meta_data ( $this -> socket );
2013-10-28 22:27:25 +01:00
if ( socket_set_blocking ( $this -> socket , 1 ))
2011-08-22 23:50:02 +02:00
{
$result = stream_socket_enable_crypto ( $this -> socket , true , STREAM_CRYPTO_METHOD_TLS_CLIENT );
socket_set_blocking ( $this -> socket , ( int ) $stream_meta [ 'blocked' ]);
}
return $result ;
}
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 .
2009-06-03 16:29:26 +00:00
*
* @ param string $eol End of line we are using ( optional to be backwards compatible )
2005-04-09 12:26:45 +00:00
*/
2009-06-03 16:29:26 +00:00
function mail_encode ( $str , $eol = " \r \n " )
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 = " ?= " ;
2009-06-03 16:29:26 +00:00
$delimiter = " $eol " ;
2003-10-12 11:59:23 +00:00
2009-04-16 15:39:29 +00:00
// Maximum length is 75. $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $delimiter . $end)!!!
$split_length = 60 ;
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 ))
{
2009-04-10 07:54:52 +00:00
return $start . implode ( $end . $delimiter . $start , str_split ( $encoded_str , $split_length )) . $end ;
2006-11-23 12:44:12 +00:00
}
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
}
2009-04-10 07:54:52 +00:00
$str .= $start . base64_encode ( $text ) . $end . $delimiter ;
2006-11-23 11:53:52 +00:00
}
2003-10-12 11:59:23 +00:00
2009-04-10 07:54:52 +00:00
return substr ( $str , 0 , - strlen ( $delimiter ));
2003-10-12 11:59:23 +00:00
}
2009-08-18 09:59:24 +00:00
/**
* Wrapper for sending out emails with the PHP ' s mail function
*/
function phpbb_mail ( $to , $subject , $msg , $headers , $eol , & $err_msg )
{
2011-08-26 01:53:52 +02:00
global $config , $phpbb_root_path , $phpEx ;
2009-08-18 09:59:24 +00:00
// We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used...
// Reference: http://bugs.php.net/bug.php?id=15841
$headers = implode ( $eol , $headers );
2013-09-10 14:01:09 +02:00
if ( ! class_exists ( '\phpbb\error_collector' ))
2011-08-26 01:53:52 +02:00
{
include ( $phpbb_root_path . 'includes/error_collector.' . $phpEx );
}
2013-09-10 14:01:09 +02:00
$collector = new \phpbb\error_collector ;
2011-08-26 01:53:52 +02:00
$collector -> install ();
2009-08-18 09:59:24 +00:00
// On some PHP Versions mail() *may* fail if there are newlines within the subject.
// Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8.
2009-08-18 13:24:45 +00:00
// Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used)
$result = $config [ 'email_function_name' ]( $to , mail_encode ( $subject , '' ), wordwrap ( utf8_wordwrap ( $msg ), 997 , " \n " , true ), $headers );
2011-08-26 01:53:52 +02:00
$collector -> uninstall ();
$err_msg = $collector -> format_errors ();
2009-08-18 09:59:24 +00:00
return $result ;
}