diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 704c122d59..ba6658f889 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -327,11 +327,11 @@ services: - '@config' - '@language' - '@log' + - '@messenger.method_collection' - '@notification_manager' - '@user_loader' - '%core.root_path%' - '%core.php_ext%' - - '@messenger.method_collection' tags: - { name: console.command } @@ -342,10 +342,10 @@ services: - '@dbal.conn' - '@config' - '@language' + - '@messenger.method_collection' - '@passwords.manager' - '%core.root_path%' - '%core.php_ext%' - - '@messenger.method_collection' tags: - { name: console.command } diff --git a/phpBB/config/default/container/services_messenger.yml b/phpBB/config/default/container/services_messenger.yml index d6625430ef..c2ff6fa679 100644 --- a/phpBB/config/default/container/services_messenger.yml +++ b/phpBB/config/default/container/services_messenger.yml @@ -16,34 +16,34 @@ services: - '@assets.bag' - '@config' - '@dispatcher' + - '@ext.manager' - '@language' - '@log' - - '@request' - - '@user' - '@messenger.queue' - '@path_helper' - - '@ext.manager' + - '@request' - '@template.twig.extensions.collection' - '@template.twig.lexer' + - '@user' + - '%core.root_path%' - '%core.template.cache_path%' - - '%core.php_ext%' messenger.method.email: - class: phpbb\messenger\method\phpbb_email + class: phpbb\messenger\method\email shared: false parent: messenger.method.base calls: - - [reset, []] + - [init, []] - [set_transport, []] tags: - { name: messenger.method } messenger.method.jabber: - class: phpbb\messenger\method\phpbb_jabber + class: phpbb\messenger\method\jabber shared: false parent: messenger.method.base calls: - - [reset, []] + - [init, []] tags: - { name: messenger.method } diff --git a/phpBB/config/default/container/services_ucp.yml b/phpBB/config/default/container/services_ucp.yml index 6321e431db..bbe5d35f2b 100644 --- a/phpBB/config/default/container/services_ucp.yml +++ b/phpBB/config/default/container/services_ucp.yml @@ -19,6 +19,7 @@ services: - '@controller.helper' - '@language' - '@log' + - '@messenger.method.email' - '@passwords.manager' - '@request' - '@template' @@ -26,7 +27,6 @@ services: - '%tables.users%' - '%core.root_path%' - '%core.php_ext%' - - '@messenger.method_collection' phpbb.ucp.controller.webpush: class: phpbb\ucp\controller\webpush diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 3537b67737..b20d0d9753 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -720,17 +720,16 @@ class acp_board { if ($config['email_enable']) { - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('test'); - $email->set_addresses($user->data); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('test'); + $email_method->set_addresses($user->data); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($user->data['username'], ENT_COMPAT), 'MESSAGE' => html_entity_decode($request->variable('send_test_email_text', '', true), ENT_COMPAT), ]); - $email->send(); + $email_method->send(); trigger_error($user->lang('TEST_EMAIL_SENT') . adm_back_link($this->u_action)); } diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 23f7885e53..630b1bcb14 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -217,16 +217,15 @@ class acp_email ); extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); for ($i = 0, $size = count($email_list); $i < $size; $i++) { $used_lang = $email_list[$i][0]['lang']; $used_method = $email_list[$i][0]['method']; - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $used_method || $used_method == NOTIFY_BOTH) { $messenger_method->set_use_queue($use_queue); @@ -260,7 +259,6 @@ class acp_email $messenger_method->save_queue(); } } - $messenger_collection_iterator->next(); } } unset($email_list); diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 13427a8191..9d5d730348 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -114,19 +114,18 @@ class acp_inactive if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !empty($inactive_users)) { - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); foreach ($inactive_users as $row) { - $email->template('admin_welcome_activated', $row['user_lang']); - $email->set_addresses($row); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method->template('admin_welcome_activated', $row['user_lang']); + $email_method->set_addresses($row); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($row['username'], ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } } @@ -199,14 +198,13 @@ class acp_inactive { // Send the messages $usernames = $user_ids = array(); - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); do { - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) { $messenger_method->template('user_remind_inactive', $row['user_lang']); @@ -221,7 +219,6 @@ class acp_inactive $messenger_method->send(); $messenger_method->save_queue(); } - $messenger_collection_iterator->next(); } $usernames[] = $row['username']; diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 707e6b5541..d88d050387 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -398,18 +398,17 @@ class acp_users $db->sql_query($sql); // Start sending email - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template($email_template, $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template($email_template, $user_row['user_lang']); + $email_method->set_addresses($user_row); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey", ]); - $email->send(); + $email_method->send(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE', false, array($user_row['username'])); $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_REACTIVATE_USER', false, array( @@ -454,16 +453,15 @@ class acp_users $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('admin_welcome_activated', $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('admin_welcome_activated', $user_row['user_lang']); + $email_method->set_addresses($user_row); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } } diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php deleted file mode 100644 index 323ab31999..0000000000 --- a/phpBB/includes/functions_messenger.php +++ /dev/null @@ -1,1366 +0,0 @@ - - * @license GNU General Public License, version 2 (GPL-2.0) - * - * For full copyright and license information, please see - * the docs/CREDITS.txt file. - * - */ - -use Symfony\Component\Mailer\Transport; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; -use Symfony\Component\Mime\Header\Headers; - -/** - * @ignore - */ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** - * Messenger class - */ -class messenger -{ - /** @var array */ - private const PRIORITY_MAP = [ - Email::PRIORITY_HIGHEST => 'Highest', - Email::PRIORITY_HIGH => 'High', - Email::PRIORITY_NORMAL => 'Normal', - Email::PRIORITY_LOW => 'Low', - Email::PRIORITY_LOWEST => 'Lowest', - ]; - - /** @var array */ - private const HEADER_CLASS_MAP = [ - 'date' => DateHeader::class, - 'from' => MailboxListHeader::class, - 'sender' => MailboxHeader::class, - 'reply-to' => MailboxListHeader::class, - 'to' => MailboxListHeader::class, - 'cc' => MailboxListHeader::class, - 'bcc' => MailboxListHeader::class, - 'message-id' => IdentificationHeader::class, - 'in-reply-to' => UnstructuredHeader::class, - 'references' => UnstructuredHeader::class, - 'return-path' => PathHeader::class, - ]; - - /** @var array */ - protected $additional_headers = []; - - /** @var array */ - protected $addresses = []; - - /** @var \phpbb\config\config */ - protected $config; - - /** @var \phpbb\event\dispatcher */ - protected $dispatcher; - - /** - * @var string - * - * Symfony Mailer transport DSN - */ - protected $dsn = ''; - - /** @var string */ - protected $from; - - /** @var Symfony\Component\Mime\Header\Headers */ - protected $headers; - - /** @var \phpbb\language\language */ - protected $language; - - /** @var \phpbb\log\log_interface */ - protected $log; - - /** - * @var int - * - * Possible values are: - * Email::PRIORITY_HIGHEST - * Email::PRIORITY_HIGH - * Email::PRIORITY_NORMAL - * Email::PRIORITY_LOW - * Email::PRIORITY_LOWEST - */ - protected $mail_priority = Email::PRIORITY_NORMAL; - - /** @var string */ - protected $msg; - - /** @var string */ - protected $php_ext; - - /** @var queue */ - protected $queue; - - /** @var string */ - protected $replyto; - - /** @var \phpbb\request\request */ - protected $request; - - /** @var string */ - protected $root_path; - - /** @var string */ - protected $subject; - - /** @var \phpbb\template\template */ - protected $template; - - /** @var Symfony\Component\Mailer\Transport */ - protected $transport; - - /** @var bool */ - protected $use_queue = true; - - /** @var phpbb\user */ - protected $user; - - /** - * Messenger class constructor - * - * @param bool $use_queue Flag to switch the use of the messenger file queue - */ - function __construct($use_queue = true) - { - global $phpbb_container; - - $this->phpbb_container = $phpbb_container; - $this->config = $this->phpbb_container->get('config'); - $this->dispatcher = $this->phpbb_container->get('dispatcher'); - $this->language = $this->phpbb_container->get('language'); - $this->log = $this->phpbb_container->get('log'); - $this->request = $this->phpbb_container->get('request'); - $this->user = $this->phpbb_container->get('user'); - $this->email = new Email(); - $this->headers = $this->email->getHeaders(); - $this->use_queue = (!$this->config['email_package_size']) ? false : $use_queue; - $this->subject = ''; - $this->php_ext = $this->phpbb_container->getParameter('core.php_ext'); - $this->root_path = $this->phpbb_container->getParameter('core.root_path'); - $this->set_transport(); - } - - /** - * Resets all the data (address, template file, etc etc) to default - * - * @return void - */ - public function reset() - { - $this->addresses = []; - $this->msg = $this->replyto = $this->from = ''; - $this->mail_priority = Email::PRIORITY_NORMAL; - } - - /** - * Set addresses for to/im as available - * - * @param array $user User row - * @return void - */ - public function set_addresses($user) - { - if (isset($user['user_email']) && $user['user_email']) - { - $this->to($user['user_email'], $user['username'] ?: ''); - } - - if (isset($user['user_jabber']) && $user['user_jabber']) - { - $this->im($user['user_jabber'], $user['username'] ?: ''); - } - } - - /** - * Sets email address to send to - * - * @param string $address Email "To" recipient address - * @param string $realname Email "To" recipient name - * @return void - */ - public function to($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - // If empty sendmail_path on windows, PHP changes the to line - $windows_empty_sendmail_path = !$this->config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\'; - - $to = new Address(trim($address), $windows_empty_sendmail_path ? '' : trim($realname)); - $this->email->getTo() ? $this->email->addTo($to) : $this->email->to($to); - } - - /** - * Sets cc address to send to - * - * @param string $address Email carbon copy recipient address - * @param string $realname Email carbon copy recipient name - * @return void - */ - public function cc($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $cc = new Address(trim($address), trim($realname)); - $this->email->getCc() ? $this->email->addCc($to) : $this->email->cc($to); - } - - /** - * Sets bcc address to send to - * - * @param string $address Email black carbon copy recipient address - * @param string $realname Email black carbon copy recipient name - * @return void - */ - public function bcc($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $bcc = new Address(trim($address), trim($realname)); - $this->email->getBcc() ? $this->email->addBcc($to) : $this->email->bcc($to); - } - - /** - * Sets a im contact to send to - * - * @param string $address Jabber recipient address - * @param string $realname Jabber recipient name - * @return void - */ - public function im($address, $realname = '') - { - // IM-Addresses could be empty - if (!trim($address)) - { - return; - } - - $pos = isset($this->addresses['im']) ? count($this->addresses['im']) : 0; - $this->addresses['im'][$pos]['uid'] = trim($address); - $this->addresses['im'][$pos]['name'] = trim($realname); - } - - /** - * Set the reply to address - * - * @param string $address Email "Reply to" address - * @return void - */ - public function replyto($address) - { - $this->replyto = new Address(trim($address)); - $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); - } - - /** - * Set the from address - * - * @param string $address Email "from" address - * @return void - */ - public function from($address) - { - $this->from = new Address(trim($address)); - $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); - } - - /** - * Set up subject for mail - * - * @param string $subject Email subject - * @return void - */ - public function subject($subject = '') - { - $this->subject = $subject; - $this->email->subject(trim($this->subject)); - } - - /** - * Set up extra mail headers - * - * @param string $header_name Email header name - * @param string $header_value Email header body - * @return void - */ - public function header($header_name, $header_value) - { - $header_name = trim($header_name); - $header_value = trim($header_value); - - // addMailboxListHeader() requires value to be array - if ($this->get_header_method($header_name) == 'addMailboxListHeader') - { - $header_value = [$header_value]; - } - $this->headers->addHeader($header_name, $header_value); - } - - /** - * Adds X-AntiAbuse headers - * - * @param \phpbb\config\config $config Config object - * @param \phpbb\user $user User object - * @return void - */ - public function anti_abuse_headers($config, $user) - { - $this->header('X-AntiAbuse', 'Board servername - ' . $config['server_name']); - $this->header('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); - $this->header('X-AntiAbuse', 'Username - ' . $user->data['username']); - $this->header('X-AntiAbuse', 'User IP - ' . $user->ip); - } - - /** - * Set the email priority - * - * Possible values are: - * Email::PRIORITY_HIGHEST = 1 - * Email::PRIORITY_HIGH = 2 - * Email::PRIORITY_NORMAL = 3 - * Email::PRIORITY_LOW = 4 - * Email::PRIORITY_LOWEST = 5 - * - * @param int $priority Email priority level - * @return void - */ - public function set_mail_priority($priority = Email::PRIORITY_NORMAL) - { - $this->email->priority($priority); - } - - /** - * Set email template to use - * - * @param string $template_file Email template file name - * @param string $template_lang Email template language - * @param string $template_path Email template path - * @param string $template_dir_prefix Email template directory prefix - * - * @return bool - */ - public function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') - { - $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; - - $this->setup_template(); - - if (!trim($template_file)) - { - trigger_error('No template file for emailing set.', E_USER_ERROR); - } - - if (!trim($template_lang)) - { - // fall back to board default language if the user's language is - // missing $template_file. If this does not exist either, - // $this->template->set_filenames will do a trigger_error - $template_lang = basename($this->config['default_lang']); - } - - $ext_template_paths = [ - [ - 'name' => $template_lang . '_email', - 'ext_path' => 'language/' . $template_lang . '/email' . $template_dir_prefix, - ], - ]; - - if ($template_path) - { - $template_paths = [ - $template_path . $template_dir_prefix, - ]; - } - else - { - $template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; - $template_path .= $template_lang . '/email'; - - $template_paths = [ - $template_path . $template_dir_prefix, - ]; - - $board_language = basename($this->config['default_lang']); - - // 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 !== $board_language) - { - $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; - $fallback_template_path .= $board_language . '/email'; - - $template_paths[] = $fallback_template_path . $template_dir_prefix; - - $ext_template_paths[] = [ - 'name' => $board_language . '_email', - 'ext_path' => 'language/' . $board_language . '/email' . $template_dir_prefix, - ]; - } - // If everything fails just fall back to en template - if ($template_lang !== 'en' && $board_language !== 'en') - { - $fallback_template_path = (!empty($this->user->lang_path)) ? $this->user->lang_path : $this->root_path . 'language/'; - $fallback_template_path .= 'en/email'; - - $template_paths[] = $fallback_template_path . $template_dir_prefix; - - $ext_template_paths[] = [ - 'name' => 'en_email', - 'ext_path' => 'language/en/email' . $template_dir_prefix, - ]; - } - } - - $this->set_template_paths($ext_template_paths, $template_paths); - - $this->template->set_filenames([ - 'body' => $template_file . '.txt', - ]); - - return true; - } - - /** - * Assign variables to email template - * - * @param array $vars Array of VAR => VALUE to assign to email template - * @return void - */ - public function assign_vars($vars) - { - $this->setup_template(); - - $this->template->assign_vars($vars); - } - - /** - * Assign block of variables to email template - * - * @param string $blockname Template block name - * @param array $vars Array of VAR => VALUE to assign to email template block - * @return void - */ - public function assign_block_vars($blockname, $vars) - { - $this->setup_template(); - - $this->template->assign_block_vars($blockname, $vars); - } - - /** - * Prepare message before sending out to the recipients - * - * @return void - */ - public function prepare_message() - { - // We add some standard variables we always use, no need to specify them always - $this->assign_vars([ - 'U_BOARD' => generate_board_url(), - 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . html_entity_decode($this->config['board_email_sig'], ENT_COMPAT)), - 'SITENAME' => html_entity_decode($this->config['sitename'], ENT_COMPAT), - ]); - - $email = $this->email; - $subject = $this->email->getSubject(); - $template = $this->template; - /** - * Event to modify the template before parsing - * - * @event core.modify_notification_template - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var \phpbb\template\template template The (readonly) template object - * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. - */ - $vars = ['email', 'subject', 'template']; - extract($this->dispatcher->trigger_event('core.modify_notification_template', compact($vars))); - - // Parse message through template - $message = trim($this->template->assign_display('body')); - - /** - * Event to modify notification message text after parsing - * - * @event core.modify_notification_message - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string message The message text - * @var string subject The message subject - * @since 3.1.11-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: method, break. - */ - $vars = ['email', 'message', 'subject']; - extract($this->dispatcher->trigger_event('core.modify_notification_message', compact($vars))); - - $this->email = $email; - $this->subject = $subject; - $this->msg = $message; - unset($email, $subject, $message, $template); - - // 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); - - // 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 = []; - if (preg_match('#^(Subject):(.*?)$#m', $this->msg, $match)) - { - $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); - $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); - } - else - { - $this->subject = (($this->subject != '') ? $this->subject : $this->user->lang['NO_EMAIL_SUBJECT']); - } - - if (preg_match('#^(List-Unsubscribe):(.*?)$#m', $this->msg, $match)) - { - $drop_header .= '[\r\n]*?' . preg_quote($match[0], '#'); - $this->additional_headers[$match[1]] = trim($match[2]); - } - - if ($drop_header) - { - $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); - } - } - - /** - * Send the mail out to the recipients - * - * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH - * @param bool $break Flag indicating if the function only formats the subject - * and the message without sending it - * @return bool - */ - public function send($method = NOTIFY_EMAIL, $break = false) - { - $this->prepare_message(); - if ($break) - { - return true; - } - - switch ($method) - { - case NOTIFY_EMAIL: - $result = $this->msg_email(); - break; - - case NOTIFY_IM: - $result = $this->msg_jabber(); - break; - - case NOTIFY_BOTH: - $result = $this->msg_email(); - $this->msg_jabber(); - break; - } - - $this->reset(); - return $result; - } - - /** - * Add error message to log - * - * @param string $type Error type: EMAIL / etc - * @param string $msg Error message text - * @return void - */ - public function error($type, $msg) - { - // Session doesn't exist, create it - if (!isset($this->user->session_id) || $this->user->session_id === '') - { - $this->user->session_begin(); - } - - $calling_page = html_entity_decode($this->request->server('REQUEST_URI'), ENT_COMPAT); - - switch ($type) - { - case 'EMAIL': - $message = 'EMAIL/' . (($this->config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()') . ''; - break; - - default: - $message = "$type"; - break; - } - - $message .= '
' . htmlspecialchars($calling_page, ENT_COMPAT) . '

' . $msg . '
'; - $this->log->add('critical', $this->user->data['user_id'], $this->user->ip, 'LOG_ERROR_' . $type, false, [$message]); - } - - /** - * Save message data to the messemger file queue - * @return void - */ - public function save_queue() - { - if ($this->config['email_package_size'] && $this->use_queue && !empty($this->queue)) - { - $this->queue->save(); - return; - } - } - - /** - * Detect proper Header class method to add header - * - * @param string $name Email header name - * @return string - */ - protected function get_header_method(string $name) - { - $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); - $method = 'add'.ucfirst(array_pop($parts)); - if ('addUnstructuredHeader' === $method) - { - $method = 'addTextHeader'; - } - else if ('addIdentificationHeader' === $method) - { - $method = 'addIdHeader'; - } - - return $method; - } - - /** - * Set email headers - * - * @return bool - */ - protected function build_header() - { - $headers = []; - - $board_contact = $this->config['board_contact']; - if (empty($this->email->getReplyTo())) - { - $this->replyto($board_contact); - $headers['Reply-To'] = $this->replyto; - } - - if (empty($this->email->getFrom())) - { - $this->from($board_contact); - $headers['From'] = $this->from; - } - - $headers['Return-Path'] = new Address($this->config['board_email']); - $headers['Sender'] = new Address($this->config['board_email']); - $headers['X-Priority'] = sprintf('%d (%s)', $this->mail_priority, self::PRIORITY_MAP[$this->mail_priority]); - $headers['X-MSMail-Priority'] = self::PRIORITY_MAP[$this->mail_priority]; - $headers['X-Mailer'] = 'phpBB3'; - $headers['X-MimeOLE'] = 'phpBB3'; - $headers['X-phpBB-Origin'] = 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()); - - /** - * Event to modify email header entries - * - * @event core.modify_email_headers - * @var array headers Array containing email header entries - * @since 3.1.11-RC1 - */ - $vars = ['headers']; - extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - - foreach ($headers as $header => $value) - { - $this->header($header, $value); - } - - return true; - } - - /** - * Generates valid DSN for Symfony Mailer transport - * - * @param string $dsn Symfony Mailer transport DSN - * @return void - */ - public function set_dsn($dsn = '') - { - if (!empty($dsn)) - { - $this->dsn = $dsn; - } - else if ($this->config['smtp_delivery']) - { - if (empty($this->config['smtp_host'])) - { - $this->dsn = 'null://null'; - } - else - { - $user = urlencode($this->config['smtp_username']); - $password = urlencode($this->config['smtp_password']); - $smtp_host = urlencode($this->config['smtp_host']); - $smtp_port = $this->config['smtp_port']; - - $this->dsn = "smtp://$user:$password@$smtp_host:$smtp_port"; - } - } - else - { - $this->dsn = 'sendmail://default'; - } - } - - /** - * Get Symfony Mailer transport DSN - * - * @return void - */ - public function get_dsn() - { - return $this->dsn; - } - - /** - * Generates a valid transport to send email - * - * @return void - */ - public function set_transport() - { - if (empty($this->dsn)) - { - $this->set_dsn(); - } - - $this->transport = Transport::fromDsn($this->dsn); - - if ($this->config['smtp_delivery'] && !in_array($this->dsn, ['null://null', 'sendmail://default'])) - { - // Set ssl context options, see http://php.net/manual/en/context.ssl.php - $options['ssl'] = [ - 'verify_peer' => (bool) $this->config['smtp_verify_peer'], - 'verify_peer_name' => (bool) $this->config['smtp_verify_peer_name'], - 'allow_self_signed' => (bool) $this->config['smtp_allow_self_signed'], - ]; - $this->transport->getStream()->setStreamOptions($options); - } - } - - /** - * Get mailer transport object - * - * @return Symfony\Component\Mailer\Transport Symfony Mailer transport object - */ - public function get_transport() - { - return $this->transport; - } - - /** - * Send out emails - * - * @return bool - */ - protected function msg_email() - { - if (empty($this->config['email_enable'])) - { - return false; - } - - // Addresses to send to? - if (empty($this->email->getTo())) - { - // Send was successful. ;) - return true; - } - - $use_queue = false; - if ($this->config['email_package_size'] && $this->use_queue) - { - if (empty($this->queue)) - { - $this->queue = new queue(); - $this->queue->init('email', $this->config['email_package_size']); - } - $use_queue = true; - } - - $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); - $board_contact = $this->config['board_contact']; - - $this->email->subject($this->subject); - $this->email->text($this->msg); - - $break = false; - $subject = $this->subject; - $msg = $this->msg; - $email = $this->email; - /** - * Event to send message via external transport - * - * @event core.notification_message_email - * @var bool break Flag indicating if the function return after hook - * @var string subject The message subject - * @var string msg The message text - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses - */ - $vars = [ - 'break', - 'subject', - 'msg', - 'email', - ]; - extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); - - $this->addresses = $addresses; - $this->subject = $subject; - $this->msg = $msg; - unset($addresses, $subject, $msg); - - if ($break) - { - return true; - } - - if (empty($this->email->getReplyto())) - { - $this->replyto($board_contact); - } - - if (empty($this->email->getFrom())) - { - $this->from($board_contact); - } - - // Build header - foreach ($this->additional_headers as $header_name => $header_value) - { - $this->header($header_name, $header_value); - } - $this->build_header(); - - // Send message ... - if (!$use_queue) - { - $mailer = new Mailer($this->transport); - - $subject = $this->subject; - $msg = $this->msg; - $headers = $this->headers; - $email = $this->email; - /** - * Modify data before sending out emails with PHP's mail function - * - * @event core.phpbb_mail_before - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers - * @since 3.3.6-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters. - */ - $vars = [ - 'email', - 'subject', - 'msg', - 'headers', - ]; - extract($this->dispatcher->trigger_event('core.phpbb_mail_before', compact($vars))); - - $this->subject = $subject; - $this->msg = $msg; - $this->headers = $headers; - $this->email = $email; - - try - { - $mailer->send($this->email); - } - catch (TransportExceptionInterface $e) - { - $this->error('EMAIL', $e->getDebug()); - return false; - } - - /** - * Execute code after sending out emails with PHP's mail function - * - * @event core.phpbb_mail_after - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @var string subject The message subject - * @var string msg The message text - * @var string headers The email headers - * @since 3.3.6-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: to, eol, additional_parameters, $result. - */ - $vars = [ - 'email', - 'subject', - 'msg', - 'headers', - ]; - extract($this->dispatcher->trigger_event('core.phpbb_mail_after', compact($vars))); - } - else - { - $this->queue->put('email', [ - 'email' => $this->email, - ]); - } - - return true; - } - - /** - * Send jabber message out - * - * @return bool - */ - protected function msg_jabber() - { - if (empty($this->config['jab_enable']) || empty($this->config['jab_host']) || empty($this->config['jab_username']) || empty($this->config['jab_password'])) - { - return false; - } - - if (empty($this->addresses['im'])) - { - // Send was successful. ;) - return true; - } - - $use_queue = false; - if ($this->config['jab_package_size'] && $this->use_queue) - { - if (empty($this->queue)) - { - $this->queue = new queue(); - $this->queue->init('jabber', $this->config['jab_package_size']); - } - $use_queue = true; - } - - $addresses = []; - foreach ($this->addresses['im'] as $type => $uid_ary) - { - $addresses[] = $uid_ary['uid']; - } - $addresses = array_unique($addresses); - - if (!$use_queue) - { - include_once($this->root_path . 'includes/functions_jabber.' . $this->php_ext); - $this->jabber = new jabber($this->config['jab_host'], $this->config['jab_port'], $this->config['jab_username'], html_entity_decode($this->config['jab_password'], ENT_COMPAT), $this->config['jab_use_ssl'], $this->config['jab_verify_peer'], $this->config['jab_verify_peer_name'], $this->config['jab_allow_self_signed']); - - if (!$this->jabber->connect()) - { - $this->error('JABBER', $this->user->lang['ERR_JAB_CONNECT'] . '
' . $this->jabber->get_log()); - return false; - } - - if (!$this->jabber->login()) - { - $this->error('JABBER', $this->user->lang['ERR_JAB_AUTH'] . '
' . $this->jabber->get_log()); - return false; - } - - foreach ($addresses as $address) - { - $this->jabber->send_message($address, $this->msg, $this->subject); - } - - $this->jabber->disconnect(); - } - else - { - $this->queue->put('jabber', [ - 'addresses' => $addresses, - 'subject' => $this->subject, - 'msg' => $this->msg - ]); - } - unset($addresses); - return true; - } - - /** - * Setup template engine - * - * @return void - */ - protected function setup_template() - { - if ($this->template instanceof \phpbb\template\template) - { - return; - } - - $template_environment = new \phpbb\template\twig\environment( - $phpbb_container->get('assets.bag'), - $phpbb_container->get('config'), - $phpbb_container->get('filesystem'), - $phpbb_container->get('path_helper'), - $phpbb_container->getParameter('core.template.cache_path'), - $phpbb_container->get('ext.manager'), - new \phpbb\template\twig\loader(), - $this->dispatcher, - [] - ); - $template_environment->setLexer($this->phpbb_container->get('template.twig.lexer')); - - $this->template = new \phpbb\template\twig\twig( - $this->phpbb_container->get('path_helper'), - $this->config, - new \phpbb\template\context(), - $template_environment, - $this->phpbb_container->getParameter('core.template.cache_path'), - $this->user, - $this->phpbb_container->get('template.twig.extensions.collection'), - $this->phpbb_container->get('ext.manager') - ); - } - - /** - * Set template paths to load - * - * @param string $path_name Email template path name - * @param string $paths Email template paths - * @return void - */ - protected function set_template_paths($path_name, $paths) - { - $this->setup_template(); - - $this->template->set_custom_style($path_name, $paths); - } -} - -/** - * Handling messenger file queue - */ -class queue -{ - /** @var array */ - protected $data = []; - - /** @var array */ - protected $queue_data = []; - - /** @var string */ - protected $cache_file = ''; - - /** - * @var \phpbb\filesystem\filesystem_interface - */ - protected $filesystem; - - /** - * Messenger file queue class constructor - */ - function __construct() - { - global $phpbb_container; - - $this->phpbb_container = $phpbb_container; - $this->php_ext = $this->phpbb_container->getParameter('core.php_ext'); - $this->root_path = $this->phpbb_container->getParameter('core.root_path'); - $this->cache_file = $this->phpbb_container->getParameter('core.cache_dir') . "queue.{$this->php_ext}"; - $this->filesystem = $this->phpbb_container->get('filesystem'); - $this->config = $this->phpbb_container->get('config'); - $this->dispatcher = $this->phpbb_container->get('dispatcher'); - } - - /** - * Init a queue object - * - * @param string $object Queue object type: email/jabber/etc - * @param int $package_size Size of the messenger package to send - * @return void - */ - public function init($object, $package_size) - { - $this->data[$object] = []; - $this->data[$object]['package_size'] = $package_size; - $this->data[$object]['data'] = []; - } - - /** - * Put message into the messenger file queue - * - * @param string $object Queue object type: email/jabber/etc - * @param mixed $message_data Message data to send - * @return void - */ - public function put($object, $message_data) - { - $this->data[$object]['data'][] = $message_data; - } - - /** - * Process the messemger file queue (using lock file) - * - * @return void - */ - public function process() - { - $lock = new \phpbb\lock\flock($this->cache_file); - $lock->acquire(); - - // avoid races, check file existence once - $have_cache_file = file_exists($this->cache_file); - if (!$have_cache_file || $this->config['last_queue_run'] > time() - $this->config['queue_interval']) - { - if (!$have_cache_file) - { - $this->config->set('last_queue_run', time(), false); - } - - $lock->release(); - return; - } - - $this->config->set('last_queue_run', time(), false); - - include($this->cache_file); - - foreach ($this->queue_data as $object => $data_ary) - { - @set_time_limit(0); - - if (!isset($data_ary['package_size'])) - { - $data_ary['package_size'] = 0; - } - - $package_size = $data_ary['package_size']; - $num_items = (!$package_size || count($data_ary['data']) < $package_size) ? count($data_ary['data']) : $package_size; - - switch ($object) - { - case 'email': - // Delete the email queued objects if mailing is disabled - if (!$this->config['email_enable']) - { - unset($this->queue_data['email']); - continue 2; - } - break; - - case 'jabber': - if (!$this->config['jab_enable']) - { - unset($this->queue_data['jabber']); - continue 2; - } - - include_once($this->root_path . 'includes/functions_jabber.' . $this->php_ext); - $this->jabber = new jabber($this->config['jab_host'], $this->config['jab_port'], $this->config['jab_username'], html_entity_decode($this->config['jab_password'], ENT_COMPAT), $this->config['jab_use_ssl'], $this->config['jab_verify_peer'], $this->config['jab_verify_peer_name'], $this->config['jab_allow_self_signed']); - - if (!$this->jabber->connect()) - { - $messenger = new messenger(); - $messenger->error('JABBER', $this->user->lang['ERR_JAB_CONNECT']); - continue 2; - } - - if (!$this->jabber->login()) - { - $messenger = new messenger(); - $messenger->error('JABBER', $this->user->lang['ERR_JAB_AUTH']); - continue 2; - } - - break; - - default: - $lock->release(); - return; - } - - for ($i = 0; $i < $num_items; $i++) - { - // Make variables available... - extract(array_shift($this->queue_data[$object]['data'])); - - switch ($object) - { - case 'email': - $break = false; - /** - * Event to send message via external transport - * - * @event core.notification_message_process - * @var bool break Flag indicating if the function return after hook - * @var Symfony\Component\Mime\Email email The Symfony Email object - * @since 3.2.4-RC1 - * @changed 4.0.0-a1 Added vars: email. Removed vars: addresses, subject, msg. - */ - $vars = [ - 'break', - 'email', - ]; - extract($this->dispatcher->trigger_event('core.notification_message_process', compact($vars))); - - if (!$break) - { - $messenger = new messenger(); - $mailer = new Mailer($messenger->get_transport()); - - try - { - $mailer->send($email); - } - catch (TransportExceptionInterface $e) - { - $messenger->error('EMAIL', $e->getDebug()); - continue 2; - } - } - break; - - case 'jabber': - foreach ($addresses as $address) - { - if ($this->jabber->send_message($address, $msg, $subject) === false) - { - $messenger = new messenger(); - $messenger->error('JABBER', $this->jabber->get_log()); - continue 3; - } - } - break; - } - } - - // No more data for this object? Unset it - if (!count($this->queue_data[$object]['data'])) - { - 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 - $this->jabber->disconnect(); - break; - } - } - - if (!count($this->queue_data)) - { - @unlink($this->cache_file); - } - else - { - if ($fp = @fopen($this->cache_file, 'wb')) - { - fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); - fclose($fp); - - if (function_exists('opcache_invalidate')) - { - @opcache_invalidate($this->cache_file); - } - - try - { - $this->filesystem->phpbb_chmod($this->cache_file, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - } - } - - $lock->release(); - } - - /** - * Save message data to the messenger file queue - * - * @return void - */ - public function save() - { - if (!count($this->data)) - { - return; - } - - $lock = new \phpbb\lock\flock($this->cache_file); - $lock->acquire(); - - if (file_exists($this->cache_file)) - { - include($this->cache_file); - - foreach ($this->queue_data as $object => $data_ary) - { - if (isset($this->data[$object]) && count($this->data[$object])) - { - $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']); - } - else - { - $this->data[$object]['data'] = $data_ary['data']; - } - } - } - - if ($fp = @fopen($this->cache_file, 'w')) - { - fwrite($fp, "queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); - fclose($fp); - - if (function_exists('opcache_invalidate')) - { - @opcache_invalidate($this->cache_file); - } - - try - { - $this->filesystem->phpbb_chmod($this->cache_file, \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE); - } - catch (\phpbb\filesystem\exception\filesystem_exception $e) - { - // Do nothing - } - - $this->data = []; - } - - $lock->release(); - } -} diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 2db88c6934..b8867fcdb3 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -131,11 +131,10 @@ class ucp_activate $phpbb_notifications = $phpbb_container->get('notification_manager'); $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $messenger_collection_iterator = $messenger->getIterator(); - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $user_row['user_notify_type'] || $user_row['user_notify_type'] == NOTIFY_BOTH) { $messenger_method->set_use_queue(false); @@ -148,7 +147,6 @@ class ucp_activate $messenger_method->send(); } - $messenger_collection_iterator->next(); } $message = 'ACCOUNT_ACTIVE_ADMIN'; diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index c142a2af73..0b34598e14 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -174,17 +174,16 @@ class ucp_profile $user_actkey = gen_rand_string(mt_rand(6, 10)); - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); + $email_method = $phpbb_container->get('messenger.method.email'); $template_file = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? 'user_activate_inactive' : 'user_activate'; - $email->template($template_file, $user->data['user_lang']); - $email->to($data['email'], $data['username']); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method->template($template_file, $user->data['user_lang']); + $email_method->to($data['email'], $data['username']); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($data['username'], ENT_COMPAT), 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey", ]); - $email->send(); + $email_method->send(); if ($config['require_activation'] == USER_ACTIVATION_ADMIN) { diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 92a54a37cb..6736ea25f0 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -458,13 +458,12 @@ class ucp_register if ($config['email_enable']) { - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template($email_template, $data['lang']); - $email->to($data['email'], $data['username']); - $email->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template($email_template, $data['lang']); + $email_method->to($data['email'], $data['username']); + $email_method->anti_abuse_headers($config, $user); + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($data['new_password'], ENT_COMPAT), @@ -473,7 +472,7 @@ class ucp_register if ($coppa) { - $email->assign_vars([ + $email_method->assign_vars([ 'FAX_INFO' => $config['coppa_fax'], 'MAIL_INFO' => $config['coppa_mail'], 'EMAIL_ADDRESS' => $data['email'], @@ -506,7 +505,7 @@ class ucp_register ); extract($phpbb_dispatcher->trigger_event('core.ucp_register_welcome_email_before', compact($vars))); - $email->send(); + $email_method->send(); } if ($config['require_activation'] == USER_ACTIVATION_ADMIN) diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 122aeeca37..ab108bc15d 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -94,18 +94,17 @@ class ucp_resend $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false; - $messenger = $phpbb_container->get('messenger.method_collection'); - $email = $messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); + $email_method = $phpbb_container->get('messenger.method.email'); + $email_method->set_use_queue(false); if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa) { - $email->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); - $email->set_addresses($user_row); + $email_method->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); + $email_method->set_addresses($user_row); - $email->anti_abuse_headers($config, $user); + $email_method->anti_abuse_headers($config, $user); - $email->assign_vars([ + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", @@ -113,14 +112,14 @@ class ucp_resend if ($coppa) { - $email->assign_vars([ + $email_method->assign_vars([ 'FAX_INFO' => $config['coppa_fax'], 'MAIL_INFO' => $config['coppa_mail'], 'EMAIL_ADDRESS' => $user_row['user_email'], ]); } - $email->send(); + $email_method->send(); } if ($config['require_activation'] == USER_ACTIVATION_ADMIN) @@ -136,9 +135,8 @@ class ucp_resend $messenger_collection_iterator = $messenger->getIterator(); while ($row = $db->sql_fetchrow($result)) { - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); $messenger_method->set_use_queue(false); if ($messenger_method->get_id() == $row['user_notify_type'] || $row['user_notify_type'] == NOTIFY_BOTH) { @@ -156,7 +154,6 @@ class ucp_resend // Save the queue in the messenger method class (has to be called or these messages could be lost) $messenger_method->save_queue(); } - $messenger_collection_iterator->next(); } } $db->sql_freeresult($result); diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index f61fd21502..be4b467a5f 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -436,8 +436,7 @@ switch ($mode) trigger_error('EMPTY_MESSAGE_IM'); } - $messenger = $phpbb_container->get('messenger.method_collection'); - $jabber = $messenger->offsetGet('messenger.method.jabber'); + $jabber = $phpbb_container->get('messenger.method.jabber'); $jabber->set_use_queue(false); $jabber->template('profile_send_im', $row['user_lang']); @@ -901,7 +900,7 @@ switch ($mode) case 'contactadmin': case 'email': - $messenger = $phpbb_container->get('messenger.method_collection'); + $messenger = (\phpbb\di\service_collection) $phpbb_container->get('messenger.method_collection'); $user_id = $request->variable('u', 0); $topic_id = $request->variable('t', 0); diff --git a/phpBB/phpbb/console/command/user/activate.php b/phpBB/phpbb/console/command/user/activate.php index 9157206e0a..23f1b390e3 100644 --- a/phpBB/phpbb/console/command/user/activate.php +++ b/phpBB/phpbb/console/command/user/activate.php @@ -39,6 +39,9 @@ class activate extends command /** @var log_interface */ protected $log; + /** @var service_collection */ + protected $messenger; + /** @var manager */ protected $notifications; @@ -59,9 +62,6 @@ class activate extends command */ protected $php_ext; - /** @var service_collection */ - protected $messenger; - /** * Construct method * @@ -69,22 +69,22 @@ class activate extends command * @param config $config * @param language $language * @param log_interface $log + * @param service_collection $messenger * @param manager $notifications * @param user_loader $user_loader * @param string $phpbb_root_path * @param string $php_ext - * @param service_collection $messenger */ - public function __construct(user $user, config $config, language $language, log_interface $log, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext, service_collection $messenger) + public function __construct(user $user, config $config, language $language, log_interface $log, service_collection $messenger, manager $notifications, user_loader $user_loader, $phpbb_root_path, $php_ext) { $this->config = $config; $this->language = $language; $this->log = $log; + $this->messenger = $messenger; $this->notifications = $notifications; $this->user_loader = $user_loader; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $this->messenger = $messenger; $this->language->add_lang('acp/users'); parent::__construct($user); @@ -200,15 +200,15 @@ class activate extends command if ($input->getOption('send-email')) { - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('admin_welcome_activated', $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $email_method = $this->messenger->offsetGet('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('admin_welcome_activated', $user_row['user_lang']); + $email_method->set_addresses($user_row); + $email_method->anti_abuse_headers($this->config, $this->user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } } } diff --git a/phpBB/phpbb/console/command/user/add.php b/phpBB/phpbb/console/command/user/add.php index 9813608034..1ad3770c76 100644 --- a/phpBB/phpbb/console/command/user/add.php +++ b/phpBB/phpbb/console/command/user/add.php @@ -43,6 +43,9 @@ class add extends command /** @var language */ protected $language; + /** @var service_collection */ + protected $messenger; + /** @var manager */ protected $password_manager; @@ -60,9 +63,6 @@ class add extends command */ protected $php_ext; - /** @var service_collection */ - protected $messenger; - /** * Construct method * @@ -70,20 +70,20 @@ class add extends command * @param driver_interface $db * @param config $config * @param language $language + * @param service_collection $messenger * @param manager $password_manager * @param string $phpbb_root_path * @param string $php_ext - * @param service_collection $messenger */ - public function __construct(user $user, driver_interface $db, config $config, language $language, manager $password_manager, $phpbb_root_path, $php_ext, service_collection $messenger) + public function __construct(user $user, driver_interface $db, config $config, language $language, service_collection $messenger, manager $password_manager, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; $this->language = $language; + $this->messenger = $messenger; $this->password_manager = $password_manager; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; - $this->messenger = $messenger; $this->language->add_lang('ucp'); parent::__construct($user); @@ -313,18 +313,18 @@ class add extends command $user_actkey = $this->get_activation_key($user_id); - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template($email_template, $this->user->lang_name); - $email->to($this->data['email'], $this->data['username']); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $email_method = $this->messenger->offsetGet('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template($email_template, $this->user->lang_name); + $email_method->to($this->data['email'], $this->data['username']); + $email_method->anti_abuse_headers($this->config, $this->user); + $email_method->assign_vars([ 'WELCOME_MSG' => html_entity_decode($this->language->lang('WELCOME_SUBJECT', $this->config['sitename']), ENT_COMPAT), 'USERNAME' => html_entity_decode($this->data['username'], ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->data['new_password'], ENT_COMPAT), 'U_ACTIVATE' => generate_board_url() . "/ucp.{$this->php_ext}?mode=activate&u=$user_id&k=$user_actkey", ]); - $email->send(); + $email_method->send(); } /** diff --git a/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php b/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php index eed17067b7..830307c1e8 100644 --- a/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php +++ b/phpBB/phpbb/db/migration/data/v400/remove_smtp_auth_method.php @@ -35,4 +35,11 @@ class remove_smtp_auth_method extends migration ['config.remove', ['smtp_auth_method']], ]; } + + public function revert_data() + { + return [ + ['config.add', ['smtp_auth_method', 'PLAIN']], + ]; + } } diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php index 8c973311e5..3f2c439bdd 100644 --- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -97,16 +97,16 @@ class notify_user extends \phpbb\install\task_base if ($this->config['email_enable']) { - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('installed', $this->install_config->get('user_language', 'en')); - $email->to($this->config['board_email'], $this->install_config->get('admin_name')); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $email_method = $this->messenger->offsetGet('messenger.method.email'); + $email_method->set_use_queue(false); + $email_method->template('installed', $this->install_config->get('user_language', 'en')); + $email_method->to($this->config['board_email'], $this->install_config->get('admin_name')); + $email_method->anti_abuse_headers($this->config, $this->user); + $email_method->assign_vars([ 'USERNAME' => html_entity_decode($this->install_config->get('admin_name'), ENT_COMPAT), 'PASSWORD' => html_entity_decode($this->install_config->get('admin_passwd'), ENT_COMPAT), ]); - $email->send(); + $email_method->send(); } // Login admin diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 0fed6fb7a5..34295d1a02 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -247,15 +247,14 @@ class message { /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $messenger->getIterator(); - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); $messenger_method->set_use_queue(false); if ($messenger_method->get_id() == $recipient['notify_type'] || $recipient['notify_type'] == NOTIFY_BOTH) { $messenger_method->template($this->template, $recipient['lang']); $messenger_method->set_addresses($recipient); - $messenger_method->replyto($this->sender_address); + $messenger_method->reply_to($this->sender_address); $messenger_method->header('X-AntiAbuse', 'Board servername - ' . $this->server_name); $messenger_method->header('X-AntiAbuse', 'User IP - ' . $this->sender_ip); @@ -284,7 +283,6 @@ class message $messenger_method->send(); } - $messenger_collection_iterator->next(); } } } diff --git a/phpBB/phpbb/messenger/method/base.php b/phpBB/phpbb/messenger/method/base.php index 809d2b2854..1d6e23ad29 100644 --- a/phpBB/phpbb/messenger/method/base.php +++ b/phpBB/phpbb/messenger/method/base.php @@ -61,12 +61,12 @@ abstract class base /** @var path_helper */ protected $path_helper; - /** @var string */ - protected $root_path; - /** @var request */ protected $request; + /** @var string */ + protected $root_path; + /** @var string */ protected $subject = ''; @@ -94,95 +94,98 @@ abstract class base * @param assets_bag $assets_bag * @param config $config * @param dispatcher $dispatcher + * @param manager $ext_manager * @param language $language * @param log_interface $log - * @param request $request - * @param user $user * @param queue $queue * @param path_helper $path_helper - * @param manager $ext_manager + * @param request $request * @param service_collection $twig_extensions_collection * @param lexer $twig_lexer - * @param string $template_cache_path + * @param user $user * @param string $phpbb_root_path + * @param string $template_cache_path */ - function __construct( + public function __construct( assets_bag $assets_bag, config $config, dispatcher $dispatcher, + manager $ext_manager, language $language, log_interface $log, - request $request, - user $user, queue $queue, path_helper $path_helper, - manager $ext_manager, + request $request, service_collection $twig_extensions_collection, lexer $twig_lexer, - $template_cache_path, - $phpbb_root_path + user $user, + $phpbb_root_path, + $template_cache_path ) { $this->assets_bag = $assets_bag; $this->config = $config; $this->dispatcher = $dispatcher; + $this->ext_manager = $ext_manager; $this->language = $language; $this->log = $log; - $this->request = $request; - $this->user = $user; $this->queue = $queue; $this->path_helper = $path_helper; - $this->ext_manager = $ext_manager; + $this->request = $request; $this->twig_extensions_collection = $twig_extensions_collection; $this->twig_lexer = $twig_lexer; - $this->template_cache_path = $template_cache_path; + $this->user = $user; $this->root_path = $phpbb_root_path; + $this->template_cache_path = $template_cache_path; $this->set_use_queue(); } /** * Get messenger method id - * @return mixed + * + * @return int */ - abstract public function get_id(); + abstract public function get_id(): int; /** * Check if the messenger method is enabled + * * @return bool */ - abstract public function is_enabled(); + abstract public function is_enabled(): bool; /** * Sets the use of messenger queue flag * * @return void */ - public function set_use_queue($use_queue = true) + public function set_use_queue(bool $use_queue = true): void { $this->use_queue = $use_queue; } /** - * Resets all the data (address, template file, etc etc) to default + * Initializes all the data (address, template file, etc) or resets to default * * @return void */ - abstract public function reset(); + abstract public function init(): void; /** * Set addresses for to/im as available * - * @param array $user User row + * @param array $user_row User row * @return void */ - abstract public function set_addresses($user); + abstract public function set_addresses(array $user_row): void; /** * Get messenger method fie queue object name + * * @return string */ - abstract public function get_queue_object_name(); + abstract public function get_queue_object_name(): string; /** * Set up subject for mail @@ -190,7 +193,7 @@ abstract class base * @param string $subject Email subject * @return void */ - public function subject($subject = '') + public function subject(string $subject = ''): void { $this->subject = $subject; } @@ -202,9 +205,7 @@ abstract class base * @param user $user User object * @return void */ - public function anti_abuse_headers($config, $user) - { - } + abstract public function anti_abuse_headers(config $config, user $user): void; /** * Set up extra headers @@ -213,9 +214,7 @@ abstract class base * @param string $header_value Email header body * @return void */ - public function header($header_name, $header_value) - { - } + abstract public function header(string $header_name, string $header_value): void; /** * Set the reply to address @@ -223,15 +222,14 @@ abstract class base * @param string $address Email "Reply to" address * @return void */ - public function replyto($address) - { - } + abstract public function reply_to($address): void; /** * Send out messages + * * @return bool */ - abstract protected function send(); + abstract protected function send(): bool; /** * Send messages from the queue @@ -239,7 +237,7 @@ abstract class base * @param array $queue_data Queue data array * @return void */ - abstract public function process_queue(&$queue_data); + abstract public function process_queue(array &$queue_data): void; /** * Set email template to use @@ -251,17 +249,12 @@ abstract class base * * @return bool */ - public function template($template_file, $template_lang = '', $template_path = '', $template_dir_prefix = '') + public function template(string $template_file, string $template_lang = '', string $template_path = '', string $template_dir_prefix = ''): bool { $template_dir_prefix = (!$template_dir_prefix || $template_dir_prefix[0] === '/') ? $template_dir_prefix : '/' . $template_dir_prefix; $this->setup_template(); - if (!trim($template_file)) - { - trigger_error('No template file for emailing set.', E_USER_ERROR); - } - if (!trim($template_lang)) { // fall back to board default language if the user's language is @@ -338,7 +331,7 @@ abstract class base * @param array $vars Array of VAR => VALUE to assign to email template * @return void */ - public function assign_vars($vars) + public function assign_vars(array $vars): void { $this->setup_template(); $this->template->assign_vars($vars); @@ -351,7 +344,7 @@ abstract class base * @param array $vars Array of VAR => VALUE to assign to email template block * @return void */ - public function assign_block_vars($blockname, $vars) + public function assign_block_vars(string $blockname, array $vars): void { $this->setup_template(); @@ -363,7 +356,7 @@ abstract class base * * @return void */ - public function prepare_message() + public function prepare_message(): void { // We add some standard variables we always use, no need to specify them always $this->assign_vars([ @@ -440,7 +433,7 @@ abstract class base * @param string $msg Error message text * @return void */ - public function error($msg) + public function error(string $msg): void { // Session doesn't exist, create it if (!isset($this->user->session_id) || $this->user->session_id === '') @@ -458,7 +451,7 @@ abstract class base * Save message data to the messenger file queue * @return void */ - public function save_queue() + public function save_queue(): void { if ($this->use_queue && !empty($this->queue)) { @@ -469,9 +462,10 @@ abstract class base /** * Setup template engine + * * @return void */ - protected function setup_template() + protected function setup_template(): void { if (isset($this->template) && $this->template instanceof \phpbb\template\template) { @@ -510,7 +504,7 @@ abstract class base * @param string|array $paths Email template paths * @return void */ - protected function set_template_paths($path_name, $paths) + protected function set_template_paths(string|array $path_name, string|array $paths): void { $this->setup_template(); $this->template->set_custom_style($path_name, $paths); diff --git a/phpBB/phpbb/messenger/method/phpbb_email.php b/phpBB/phpbb/messenger/method/email.php similarity index 72% rename from phpBB/phpbb/messenger/method/phpbb_email.php rename to phpBB/phpbb/messenger/method/email.php index 98d7497e70..d3642b263d 100644 --- a/phpBB/phpbb/messenger/method/phpbb_email.php +++ b/phpBB/phpbb/messenger/method/email.php @@ -16,7 +16,7 @@ namespace phpbb\messenger\method; use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Email as symfony_email; use Symfony\Component\Mime\Header\DateHeader; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\Header\IdentificationHeader; @@ -28,7 +28,7 @@ use Symfony\Component\Mime\Header\UnstructuredHeader; /** * Messenger class */ -class phpbb_email extends base +class email extends base { /** @var array */ private const PRIORITY_MAP = [ @@ -39,21 +39,6 @@ class phpbb_email extends base Email::PRIORITY_LOWEST => 'Lowest', ]; - /** @var array */ - private const HEADER_CLASS_MAP = [ - 'date' => DateHeader::class, - 'from' => MailboxListHeader::class, - 'sender' => MailboxHeader::class, - 'reply-to' => MailboxListHeader::class, - 'to' => MailboxListHeader::class, - 'cc' => MailboxListHeader::class, - 'bcc' => MailboxListHeader::class, - 'message-id' => IdentificationHeader::class, - 'in-reply-to' => UnstructuredHeader::class, - 'references' => UnstructuredHeader::class, - 'return-path' => PathHeader::class, - ]; - /** * @var string * @@ -86,7 +71,7 @@ class phpbb_email extends base protected $queue; /** @var Address */ - protected $replyto; + protected $reply_to; /** @var \Symfony\Component\Mailer\Transport\AbstractTransport */ protected $transport; @@ -94,7 +79,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function get_id() + public function get_id(): int { return NOTIFY_EMAIL; } @@ -102,7 +87,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function get_queue_object_name() + public function get_queue_object_name(): string { return 'email'; } @@ -110,7 +95,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function is_enabled() + public function is_enabled(): bool { return (bool) $this->config['email_enable']; } @@ -118,16 +103,16 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function reset() + public function init(): void { - $this->email = new Email(); + $this->email = new symfony_email(); $this->headers = $this->email->getHeaders(); $this->subject = $this->msg = ''; $this->mail_priority = Email::PRIORITY_NORMAL; $this->additional_headers = []; $this->use_queue = true; - unset($this->template, $this->replyto, $this->from); + unset($this->template, $this->reply_to, $this->from); } /** @@ -135,7 +120,7 @@ class phpbb_email extends base * * @return void */ - public function set_use_queue($use_queue = true) + public function set_use_queue(bool $use_queue = true): void { $this->use_queue = !$this->config['email_package_size'] ? false : $use_queue; } @@ -143,11 +128,11 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function set_addresses($user) + public function set_addresses(array $user_row): void { - if (isset($user['user_email']) && $user['user_email']) + if (isset($user_row['user_email']) && $user_row['user_email']) { - $this->to($user['user_email'], $user['username'] ?: ''); + $this->to($user_row['user_email'], $user_row['username'] ?: ''); } } @@ -158,7 +143,7 @@ class phpbb_email extends base * @param string $realname Email "To" recipient name * @return void */ - public function to($address, $realname = '') + public function to(string $address, string $realname = ''): void { if (!$address = trim($address)) { @@ -179,7 +164,7 @@ class phpbb_email extends base * @param string $realname Email carbon copy recipient name * @return void */ - public function cc($address, $realname = '') + public function cc(string $address, string $realname = ''): void { if (!$address = trim($address)) { @@ -197,7 +182,7 @@ class phpbb_email extends base * @param string $realname Email black carbon copy recipient name * @return void */ - public function bcc($address, $realname = '') + public function bcc(string $address, string $realname = ''): void { if (!$address = trim($address)) { @@ -212,23 +197,35 @@ class phpbb_email extends base * Set the reply to address * * @param string $address Email "Reply to" address + * @param string $realname Email "Reply to" recipient name * @return void */ - public function replyto($address) + public function reply_to(string $address, string $realname = ''): void { - $this->replyto = new Address(trim($address)); - $this->email->getReplyTo() ? $this->email->addReplyTo($this->replyto) : $this->email->replyTo($this->replyto); + if (!$address = trim($address)) + { + return; + } + + $this->reply_to = new Address($address, trim($realname)); + $this->email->getReplyTo() ? $this->email->addReplyTo($this->reply_to) : $this->email->replyTo($this->reply_to); } /** * Set the from address * * @param string $address Email "from" address + * @param string $realname Email "from" recipient name * @return void */ - public function from($address) + public function from(string $address, string $realname = ''): void { - $this->from = new Address(trim($address)); + if (!$address = trim($address)) + { + return; + } + + $this->from = new Address($address, trim($realname)); $this->email->getFrom() ? $this->email->addFrom($this->from) : $this->email->from($this->from); } @@ -238,32 +235,12 @@ class phpbb_email extends base * @param string $subject Email subject * @return void */ - public function subject($subject = '') + public function subject(string $subject = ''): void { parent::subject(trim($subject)); $this->email->subject($this->subject); } - /** - * Set up extra mail headers - * - * @param string $header_name Email header name - * @param string $header_value Email header body - * @return void - */ - public function header($header_name, $header_value) - { - $header_name = $header_name; - $header_value = $header_value; - - // addMailboxListHeader() requires value to be array - if ($this->get_header_method($header_name) == 'addMailboxListHeader') - { - $header_value = [$header_value]; - } - $this->headers->addHeader($header_name, $header_value); - } - /** * Adds X-AntiAbuse headers * @@ -271,12 +248,12 @@ class phpbb_email extends base * @param \phpbb\user $user User object * @return void */ - public function anti_abuse_headers($config, $user) + public function anti_abuse_headers(\phpbb\config\config $config, \phpbb\user $user): void { - $this->header('X-AntiAbuse', 'Board servername - ' . $config['server_name']); - $this->header('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); - $this->header('X-AntiAbuse', 'Username - ' . $user->data['username']); - $this->header('X-AntiAbuse', 'User IP - ' . $user->ip); + $this->headers->addHeader('X-AntiAbuse', 'Board servername - ' . $config['server_name']); + $this->headers->addHeader('X-AntiAbuse', 'User_id - ' . $user->data['user_id']); + $this->headers->addHeader('X-AntiAbuse', 'Username - ' . $user->data['username']); + $this->headers->addHeader('X-AntiAbuse', 'User IP - ' . $user->ip); } /** @@ -292,79 +269,63 @@ class phpbb_email extends base * @param int $priority Email priority level * @return void */ - public function set_mail_priority($priority = Email::PRIORITY_NORMAL) + public function set_mail_priority(int $priority = Email::PRIORITY_NORMAL): void { $this->email->priority($priority); } - /** - * Detect proper Header class method to add header - * - * @param string $name Email header name - * @return string - */ - protected function get_header_method(string $name) - { - $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); - $method = 'add'.ucfirst(array_pop($parts)); - if ('addUnstructuredHeader' === $method) - { - $method = 'addTextHeader'; - } - else if ('addIdentificationHeader' === $method) - { - $method = 'addIdHeader'; - } - - return $method; - } - /** * Set email headers * - * @return bool + * @return void */ - protected function build_header() + protected function build_headers(): void { - $headers = []; - $board_contact = $this->config['board_contact']; + $board_contact = trim($this->config['board_contact']); + $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); + if (empty($this->email->getReplyTo())) { - $this->replyto($board_contact); - $headers['Reply-To'] = $this->replyto; + $this->reply_to($board_contact, $contact_name); } if (empty($this->email->getFrom())) { - $this->from($board_contact); - $headers['From'] = $this->from; + $this->from($board_contact, $contact_name); } - $headers['Return-Path'] = new Address($this->config['board_email']); - $headers['Sender'] = new Address($this->config['board_email']); - $headers['X-Priority'] = sprintf('%d (%s)', $this->mail_priority, self::PRIORITY_MAP[$this->mail_priority]); - $headers['X-MSMail-Priority'] = self::PRIORITY_MAP[$this->mail_priority]; - $headers['X-Mailer'] = 'phpBB3'; - $headers['X-MimeOLE'] = 'phpBB3'; - $headers['X-phpBB-Origin'] = 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()); + $this->email->priority($this->mail_priority); + $phpbb_headers = [ + 'Return-Path' => new Address($this->config['board_email']), + 'Sender' => new Address($this->config['board_email']), + 'X-MSMail-Priority' => self::PRIORITY_MAP[$this->mail_priority], + 'X-Mailer' => 'phpBB3', + 'X-MimeOLE' => 'phpBB3', + 'X-phpBB-Origin' => 'phpbb://' . str_replace(['http://', 'https://'], ['', ''], generate_board_url()), + ]; + + // Add additional headers + $phpbb_headers = array_merge($phpbb_headers, $this->additional_headers); + + foreach ($phpbb_headers as $header => $value) + { + $this->headers->addHeader($header, $value); + } + + $headers = $this->headers; /** * Event to modify email header entries * * @event core.modify_email_headers - * @var array headers Array containing email header entries + * @var Headers headers Array containing email header entries * @since 3.1.11-RC1 + * @changed 4.0.0-a1 'headers' var type changed from array to \Symfony\Component\Mime\Header\Headers */ $vars = ['headers']; extract($this->dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - - foreach ($headers as $header => $value) - { - $this->header($header, $value); - } - - return true; + $this->headers = $headers; } /** @@ -373,7 +334,7 @@ class phpbb_email extends base * @param string $dsn Symfony Mailer transport DSN * @return void */ - public function set_dsn($dsn = '') + public function set_dsn(string $dsn = ''): void { if (!empty($dsn)) { @@ -406,7 +367,7 @@ class phpbb_email extends base * * @return string */ - public function get_dsn() + public function get_dsn(): string { return $this->dsn; } @@ -416,7 +377,7 @@ class phpbb_email extends base * * @return void */ - public function set_transport() + public function set_transport(): void { if (empty($this->dsn)) { @@ -440,7 +401,7 @@ class phpbb_email extends base /** * {@inheritDoc} */ - public function process_queue(&$queue_data) + public function process_queue(array &$queue_data): void { $queue_object_name = $this->get_queue_object_name(); $messages_count = count($queue_data[$queue_object_name]['data']); @@ -504,23 +465,18 @@ class phpbb_email extends base * * @return \Symfony\Component\Mailer\Transport\TransportInterface Symfony Mailer transport object */ - public function get_transport() + public function get_transport(): \Symfony\Component\Mailer\Transport\TransportInterface { return $this->transport; } /** - * Send out emails - * - * @return bool + * {@inheritDoc} */ - public function send() + public function send(): bool { $this->prepare_message(); - $contact_name = html_entity_decode($this->config['board_contact_name'], ENT_COMPAT); - $board_contact = trim($this->config['board_contact']); - $this->email->subject($this->subject); $this->email->text($this->msg); @@ -543,23 +499,9 @@ class phpbb_email extends base 'email', ]; extract($this->dispatcher->trigger_event('core.notification_message_email', compact($vars))); + $this->email = $email; - if (empty($this->email->getReplyto())) - { - $this->replyto($board_contact); - } - - if (empty($this->email->getFrom())) - { - $this->from($board_contact); - } - - // Build headers - foreach ($this->additional_headers as $header_name => $header_value) - { - $this->header($header_name, $header_value); - } - $this->build_header(); + $this->build_headers(); // Send message ... if (!$this->use_queue) diff --git a/phpBB/phpbb/messenger/method/phpbb_jabber.php b/phpBB/phpbb/messenger/method/jabber.php similarity index 88% rename from phpBB/phpbb/messenger/method/phpbb_jabber.php rename to phpBB/phpbb/messenger/method/jabber.php index 1bf212a25f..5e174c135b 100644 --- a/phpBB/phpbb/messenger/method/phpbb_jabber.php +++ b/phpBB/phpbb/messenger/method/jabber.php @@ -22,9 +22,9 @@ namespace phpbb\messenger\method; * @author Florian Schmitz (floele) * * Slightly modified by Acyd Burn (2006) - * Refactored to a service (2023) + * Refactored to a service (2024) */ -class phpbb_jabber extends base +class jabber extends base { /** @var string */ protected $connect_server; @@ -96,7 +96,7 @@ class phpbb_jabber extends base * * @return void */ - public function init() + public function init(): void { $this->username($this->config['jab_username']) ->password($this->config['jab_password']) @@ -113,7 +113,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function get_id() + public function get_id(): int { return NOTIFY_IM; } @@ -121,7 +121,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function get_queue_object_name() + public function get_queue_object_name(): string { return 'jabber'; } @@ -129,7 +129,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function is_enabled() + public function is_enabled(): bool { return !empty($this->config['jab_enable']) && @@ -143,9 +143,9 @@ class phpbb_jabber extends base * See http://php.net/manual/en/context.ssl.php * * @param array $options SSL context options array - * @return $this + * @return self */ - public function stream_options($options = []) + public function stream_options(array $options = []): self { if ($this->use_ssl) { @@ -160,9 +160,9 @@ class phpbb_jabber extends base * Set password to connect to server * * @param string $password Password to connect to server - * @return $this + * @return self */ - public function password($password = '') + public function password(string $password = ''): self { $this->password = html_entity_decode($password, ENT_COMPAT); @@ -173,9 +173,9 @@ class phpbb_jabber extends base * Set use of ssl to connect to server * * @param bool $use_ssl Flag indicating use of ssl to connect to server - * @return $this + * @return self */ - public function ssl($use_ssl = false) + public function ssl(bool $use_ssl = false): self { $this->use_ssl = $use_ssl && self::can_use_ssl(); @@ -187,9 +187,9 @@ class phpbb_jabber extends base * use_ssl flag should be set first * * @param int $port Port to connect to server - * @return $this + * @return self */ - public function port($port = 5222) + public function port(int $port = 5222): self { $this->port = ($port) ? $port : 5222; @@ -206,9 +206,9 @@ class phpbb_jabber extends base * Set username to connect to server * * @param string $username Username to connect to server - * @return $this + * @return self */ - public function username($username = '') + public function username(string $username = ''): self { if (strpos($username, '@') === false) { @@ -228,9 +228,9 @@ class phpbb_jabber extends base * Username should be set first * * @param string $server Server to connect - * @return $this + * @return self */ - public function server($server = '') + public function server(string $server = ''): self { $this->connect_server = ($server) ? $server : 'localhost'; $this->server = $this->jid[1] ?? $this->connect_server; @@ -239,17 +239,21 @@ class phpbb_jabber extends base } /** - * Able to use the SSL functionality? + * Check if it's possible to use the SSL functionality + * + * @return bool */ - public static function can_use_ssl() + public static function can_use_ssl(): bool { return @extension_loaded('openssl'); } /** - * Able to use TLS? + * Check if it's possible to use TLS functionality + * + * @return bool */ - public static function can_use_tls() + public static function can_use_tls(): bool { if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('stream_set_blocking') || !function_exists('stream_get_wrappers')) { @@ -272,19 +276,22 @@ class phpbb_jabber extends base } /** - * Sets the resource which is used. No validation is done here, only escaping. + * Sets the resource which is used. No validation is done here, only escaping + * * @param string $name - * @access public + * @return void */ - public function set_resource($name) + public function set_resource(string $name): void { $this->resource = $name; } /** - * Connect + * Connect to the server + * + * @return bool */ - public function connect() + public function connect(): bool { /* if (!$this->check_jid($this->username . '@' . $this->server)) { @@ -311,9 +318,11 @@ class phpbb_jabber extends base } /** - * Disconnect + * Disconnect from the server + * + * @return bool */ - public function disconnect() + public function disconnect(): bool { if ($this->connected()) { @@ -341,9 +350,11 @@ class phpbb_jabber extends base } /** - * Connected? + * Check if it's still connected to the server + * + * @return bool */ - public function connected() + public function connected(): bool { return is_resource($this->connection) && !feof($this->connection); } @@ -354,7 +365,7 @@ class phpbb_jabber extends base * * @return bool|void */ - public function login() + public function login(): bool|void { if (empty($this->features)) { @@ -368,11 +379,11 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function set_addresses($user) + public function set_addresses(array $user_row): void { - if (isset($user['user_jabber']) && $user['user_jabber']) + if (isset($user_row['user_jabber']) && $user_row['user_jabber']) { - $this->to($user['user_jabber'], (isset($user['username']) ? $user['username'] : '')); + $this->to($user_row['user_jabber'], (isset($user_row['username']) ? $user_row['username'] : '')); } } @@ -383,7 +394,7 @@ class phpbb_jabber extends base * @param string $realname Jabber "To" recipient name * @return void */ - public function to($address, $realname = '') + public function to(string $address, string $realname = ''): void { // IM-Addresses could be empty if (!trim($address)) @@ -399,7 +410,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function reset() + public function init(): void { $this->subject = $this->msg = ''; $this->additional_headers = $this->to = []; @@ -408,11 +419,9 @@ class phpbb_jabber extends base } /** - * Sets the use of messenger queue flag - * - * @return void + * {@inheritDoc} */ - public function set_use_queue($use_queue = true) + public function set_use_queue(bool $use_queue = true): void { $this->use_queue = !$this->config['jab_package_size'] ? false : $use_queue; } @@ -420,7 +429,7 @@ class phpbb_jabber extends base /** * {@inheritDoc} */ - public function process_queue(&$queue_data) + public function process_queue(array &$queue_data): void { $queue_object_name = $this->get_queue_object_name(); $messages_count = count($queue_data[$queue_object_name]['data']); @@ -473,9 +482,9 @@ class phpbb_jabber extends base } /** - * Send jabber message out - */ - public function send() + * {@inheritDoc} + */ + public function send(): void { $this->prepare_message(); @@ -537,10 +546,9 @@ class phpbb_jabber extends base * Send data to the Jabber server * * @param string $xml - * * @return int|bool */ - public function send_xml($xml) + public function send_xml(string $xml): int|bool { if ($this->connected()) { @@ -555,14 +563,14 @@ class phpbb_jabber extends base } /** - * OpenSocket + * Open socket * - * @param string $server host to connect to - * @param int $port port number + * @param string $server Host to connect to + * @param int $port Port number * * @return bool */ - public function open_socket($server, $port) + public function open_socket(string $server, int $port): bool { if (@function_exists('dns_get_record')) { @@ -590,9 +598,11 @@ class phpbb_jabber extends base } /** - * Return log + * Get connection log + * + * @return string */ - public function get_log() + public function get_log(): string { if ($this->enable_logging && count($this->log_array)) { @@ -604,8 +614,11 @@ class phpbb_jabber extends base /** * Add information to log + * + * @param string $string Log entry + * @return void */ - protected function add_to_log($string) + protected function add_to_log(string $string): void { if ($this->enable_logging) { @@ -617,9 +630,11 @@ class phpbb_jabber extends base * Listens to the connection until it gets data or the timeout is reached. * Thus, it should only be called if data is expected to be received. * - * @return mixed either false for timeout or an array with the received data + * @param int $timeout Connection timeout + * @param bool $wait Flag indicating if it should wait for the responce until timeout + * @return bool|array Either false for timeout or an array with the received data */ - public function listen($timeout = 10, $wait = false) + public function listen(int $timeout = 10, bool $wait = false): bool|array { if (!$this->connected()) { @@ -653,7 +668,7 @@ class phpbb_jabber extends base * * @return bool|void */ - public function register() + public function register(): bool|void { if (!isset($this->session['id']) || isset($this->session['jid'])) { @@ -668,13 +683,12 @@ class phpbb_jabber extends base /** * Sets account presence. No additional info required (default is "online" status) * - * @param string $message online, offline... - * @param string $type dnd, away, chat, xa or nothing - * @param bool $unavailable set this to true if you want to become unavailable - * + * @param string $message Account status (online, offline) + * @param string $type Status type (dnd, away, chat, xa or nothing) + * @param bool $unavailable Set to true to make unavailable status * @return int|bool */ - function send_presence($message = '', $type = '', $unavailable = false) + function send_presence(string $message = '', string $type = '', bool $unavailable = false): int|bool { if (!isset($this->session['jid'])) { @@ -697,10 +711,9 @@ class phpbb_jabber extends base * This handles all the different XML elements * * @param array $xml - * * @return bool|void */ - function response($xml) + function response(array $xml): bool|void { if (!is_array($xml) || !count($xml)) { @@ -1019,7 +1032,7 @@ class phpbb_jabber extends base * * @return int|bool */ - public function send_message($to, $text, $subject = '', $type = 'normal') + public function send_message(string $to, string $text, string $subject = '', string $type = 'normal'): int|bool { if (!isset($this->session['jid'])) { @@ -1042,10 +1055,9 @@ class phpbb_jabber extends base * Encrypts a password as in RFC 2831 * * @param array $data Needs data from the client-server connection - * * @return string */ - public function encrypt_password($data) + public function encrypt_password(array $data): string { // let's me think about again... foreach (array('realm', 'cnonce', 'digest-uri') as $key) @@ -1074,12 +1086,12 @@ class phpbb_jabber extends base } /** - * parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,... - * @param string $data + * Parse data string like a="b",c="d",... or like a="a, b", c, d="e", f=g,... * + * @param string $data * @return array a => b ... */ - public function parse_data($data) + public function parse_data(string $data): array { $data = explode(',', $data); $pairs = array(); @@ -1106,13 +1118,12 @@ class phpbb_jabber extends base } /** - * opposite of jabber::parse_data() - * - * @param array $data + * The opposite of jabber::parse_data() * + * @param array $data Data array * @return string */ - public function implode_data($data) + public function implode_data(arary $data): string { $return = array(); foreach ($data as $key => $value) @@ -1126,8 +1137,13 @@ class phpbb_jabber extends base * xmlize() * @author Hans Anderson * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ + * + * @param string $data Data string + * @param string|int|bool $skip_white New XML parser option value + * @param string $encoding Encoding value + * @return string */ - function xmlize($data, $skip_white = 1, $encoding = 'UTF-8') + function xmlize(string $data, string|int|bool $skip_white = 1, string $encoding = 'UTF-8'): array { $data = trim($data); @@ -1162,8 +1178,12 @@ class phpbb_jabber extends base * _xml_depth() * @author Hans Anderson * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ + * + * @param array $vals XML data array + * @param int $i XML tags depth level + * @return array */ - function _xml_depth($vals, &$i) + function _xml_depth(array $vals, int &$i): array { $children = array(); diff --git a/phpBB/phpbb/messenger/queue.php b/phpBB/phpbb/messenger/queue.php index 2206834269..abcc29c1bd 100644 --- a/phpBB/phpbb/messenger/queue.php +++ b/phpBB/phpbb/messenger/queue.php @@ -41,9 +41,6 @@ class queue /** @var service_collection */ protected $messenger_method_collection; - /** @var int */ - protected $package_size = 0; - /** @var array */ protected $queue_data = []; @@ -55,7 +52,7 @@ class queue * @param service_collection $messenger_method_collection * @param string $cache_file */ - function __construct(config $config, dispatcher $dispatcher, service_collection $messenger_method_collection, $cache_file) + public function __construct(config $config, dispatcher $dispatcher, service_collection $messenger_method_collection, $cache_file) { $this->config = $config; $this->dispatcher = $dispatcher; @@ -71,7 +68,7 @@ class queue * @param int $package_size Size of the messenger package to send * @return void */ - public function init($object, $package_size) + public function init(string $object, int $package_size): void { $this->data[$object] = []; $this->data[$object]['package_size'] = $package_size; @@ -82,10 +79,10 @@ class queue * Put message into the messenger file queue * * @param string $object Queue object type: email/jabber/etc - * @param mixed $message_data Message data to send + * @param array $message_data Message data to send * @return void */ - public function put($object, $message_data) + public function put(string $object, array $message_data): void { $this->data[$object]['data'][] = $message_data; } @@ -95,7 +92,7 @@ class queue * * @return void */ - public function process() + public function process(): void { $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); @@ -119,14 +116,12 @@ class queue /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger_method_collection->getIterator(); - while ($messenger_collection_iterator->valid()) + foreach ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if (isset($this->queue_data[$messenger_method->get_queue_object_name()])) { $messenger_method->process_queue($this->queue_data); } - $messenger_collection_iterator->next(); } if (!count($this->queue_data)) @@ -164,7 +159,7 @@ class queue * * @return void */ - public function save() + public function save(): void { if (!count($this->data)) { diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 38e48944f0..7cbc532390 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -114,9 +114,8 @@ abstract class messenger_base extends \phpbb\notification\method\base /** @psalm-suppress InvalidTemplateParam */ $messenger_collection_iterator = $this->messenger->getIterator(); - while ($messenger_collection_iterator->valid()) + while ($messenger_collection_iterator as $messenger_method) { - $messenger_method = $messenger_collection_iterator->current(); if ($messenger_method->get_id() == $notify_method || $notify_method == NOTIFY_BOTH) { $messenger_method->template($notification->get_email_template(), $user['user_lang'], '', $template_dir_prefix); @@ -131,7 +130,6 @@ abstract class messenger_base extends \phpbb\notification\method\base // Save the queue in the messenger method class (has to be called or these messages could be lost) $messenger_method->save_queue(); } - $messenger_collection_iterator->next(); } } diff --git a/phpBB/phpbb/ucp/controller/reset_password.php b/phpBB/phpbb/ucp/controller/reset_password.php index ae01972d7f..95a2a82b12 100644 --- a/phpBB/phpbb/ucp/controller/reset_password.php +++ b/phpBB/phpbb/ucp/controller/reset_password.php @@ -25,7 +25,7 @@ use phpbb\passwords\manager; use phpbb\request\request; use phpbb\template\template; use phpbb\user; -use phpbb\di\service_collection; +use phpbb\messenger\method\email; use Symfony\Component\HttpFoundation\Response; /** @@ -51,6 +51,9 @@ class reset_password /** @var log_interface */ protected $log; + /** @var email */ + protected $email_method; + /** @var manager */ protected $passwords_manager; @@ -72,9 +75,6 @@ class reset_password /** @var string PHP extension */ protected $php_ext; - /** @var service_collection */ - protected $messenger; - /** * Reset password controller constructor. * @@ -84,6 +84,7 @@ class reset_password * @param helper $helper * @param language $language * @param log_interface $log + * @param email $email_method * @param manager $passwords_manager * @param request $request * @param template $template @@ -91,12 +92,11 @@ class reset_password * @param string $users_table * @param string $root_path * @param string $php_ext - * @param service_collection $messenger */ public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, helper $helper, - language $language, log_interface $log, manager $passwords_manager, + language $language, log_interface $log, email $email_method, manager $passwords_manager, request $request, template $template, user $user, string $users_table, - string $root_path, string $php_ext, service_collection $messenger) + string $root_path, string $php_ext) { $this->config = $config; $this->db = $db; @@ -104,6 +104,7 @@ class reset_password $this->helper = $helper; $this->language = $language; $this->log = $log; + $this->email_method = $email_method; $this->passwords_manager = $passwords_manager; $this->request = $request; $this->template = $template; @@ -111,7 +112,6 @@ class reset_password $this->users_table = $users_table; $this->root_path = $root_path; $this->php_ext = $php_ext; - $this->messenger = $messenger; } /** @@ -256,19 +256,18 @@ class reset_password WHERE user_id = ' . $user_row['user_id']; $this->db->sql_query($sql); - $email = $this->messenger->offsetGet('messenger.method.email'); - $email->set_use_queue(false); - $email->template('user_forgot_password', $user_row['user_lang']); - $email->set_addresses($user_row); - $email->anti_abuse_headers($this->config, $this->user); - $email->assign_vars([ + $this->email_method->set_use_queue(false); + $this->email_method->template('user_forgot_password', $user_row['user_lang']); + $this->email_method->set_addresses($user_row); + $this->email_method->anti_abuse_headers($this->config, $this->user); + $this->email_method->assign_vars([ 'USERNAME' => html_entity_decode($user_row['username'], ENT_COMPAT), 'U_RESET_PASSWORD' => generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [ 'u' => $user_row['user_id'], 'token' => $reset_token, ], false) ]); - $email->send(); + $this->email_method->send(); return $this->helper->message($message); }