egroupware/mail/profile.php

241 lines
7.3 KiB
PHP

<?php
/**
* Profiling of diverse mail functions
*
* For Apache FCGI you need the following rewrite rule:
*
* RewriteEngine on
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
*
* Otherwise authentication request will be send over and over again, as password is NOT available to PHP!
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package mail
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2014 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @version $Id$
*/
$starttime = microtime(true);
$GLOBALS['egw_info'] = array(
'flags' => array(
'disable_Template_class' => True,
'noheader' => True,
'currentapp' => 'mail',
'autocreate_session_callback' => 'EGroupware\\Api\\Header\\Authenticate::autocreate_session_callback',
'auth_realm' => 'EGroupware mail profile',
)
);
include(dirname(__DIR__).'/header.inc.php');
$headertime = microtime(true);
use EGroupware\Api\Mail\Account as emailadmin_account;
use EGroupware\Api\Mail\Imap as emailadmin_imap;
// on which mail account do we work, if not specified use default one (connects to imap server!)
$acc_id = isset($_GET['acc_id']) && (int)$_GET['acc_id'] > 0 ? (int)$_GET['acc_id'] : emailadmin_account::get_default_acc_id();
// calling emailadmin_account::read with explicit account_id to not cache object for current user!
$account = emailadmin_account::read($acc_id, $GLOBALS['egw_info']['user']['account_id']);
// switching off caching by default
// if caching is enabled mail_times will always provit from previous running horde_times!
$cache = isset($_GET['cache']) && $_GET['cache'];
if (!$cache) unset(emailadmin_imap::$default_params['cache']);
$accounttime = microtime(true);
$times = array(
'header' => $headertime - $starttime,
'acc_id' => $acc_id,
'account' => (string)$account,
'cache' => $cache,
'read' => $accounttime - $headertime,
);
php_times($account, $times);
horde_times($account, $times);
mail_times($acc_id, $times);
Header('Content-Type: application/json; charset=utf-8');
echo json_encode($times, JSON_PRETTY_PRINT);
function php_times($account, array &$times, $prefix='php_')
{
$starttime = microtime(true);
switch($account->acc_imap_ssl & ~emailadmin_account::SSL_VERIFY)
{
case emailadmin_account::SSL_SSL:
$schema = 'ssl';
break;
case emailadmin_account::SSL_TLS:
$schema = 'tls';
break;
case emailadmin_account::SSL_STARTTLS:
default:
$schema = 'tcp';
break;
}
$error_number = $error_string = null;
$stream = stream_socket_client(
$schema . '://' . $account->acc_imap_host . ':' . $account->acc_imap_port,
$error_number,
$error_string,
20,
STREAM_CLIENT_CONNECT,
/* @todo: As of PHP 5.6, TLS connections require valid certs.
* However, this is BC-breaking to this library. For now, keep
* pre-5.6 behavior. */
stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false
)
))
);
$connect_response = fgets($stream);
// starttls (untested)
if ($stream && ($account->acc_imap_ssl & ~emailadmin_account::SSL_VERIFY) == emailadmin_account::SSL_STARTTLS)
{
fwrite($stream, "10 STARTTLS\r\n");
stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
$starttls_response = fgets($stream);
}
stream_set_timeout($stream, 20);
if (function_exists('stream_set_read_buffer')) {
stream_set_read_buffer($stream, 0);
}
stream_set_write_buffer($stream, 0);
$connect = microtime(true);
fwrite($stream, "20 LOGIN $account->acc_imap_username $account->acc_imap_password\r\n");
$login_response = fgets($stream);
$endtime = microtime(true);
$times += array(
$prefix.'connect' => $connect - $starttime,
//$prefix.'connect_response' => $connect_response,
$prefix.'login' => $endtime - $starttime,
//$prefix.'login_response' => $login_response,
);
fclose($stream);
unset($connect_response, $starttls_response, $login_response, $error_number, $error_string);
}
function mail_times($acc_id, array &$times, $prefix='mail_')
{
global $cache;
$starttime = microtime(true);
// instanciate mail for given acc_id - have to set it as preference ;-)
$GLOBALS['egw_info']['user']['preferences']['mail']['ActiveProfileID'] = $acc_id;
// instanciation should call openConnection
$mail_ui = new mail_ui();
$mail_ui->mail_bo->openConnection($acc_id);
$logintime = microtime(true);
// fetch mailboxes
$mboxes = $mail_ui->getFolderTree(/*$_fetchCounters=*/false, null, /*$_subscribedOnly=*/true,
/*$_returnNodeOnly=*/true, $cache, /*$_popWizard=*/false);
$listmailboxestime = microtime(true);
// get first 20 mails
$query = array(
'start' => 0,
'num_rows' => 20,
'filter' => 'any',
'filter2' => 'quick',
'search' => '',
'order' => 'date',
'sort' => 'DESC',
);
$rows = $readonlys = array();
$mail_ui->get_rows($query, $rows, $readonlys);
$fetchtime = microtime(true);
if (isset($_GET['uid']) && (int)$_GET['uid'] > 0)
{
$uid = (int)$_GET['uid'];
}
else // use uid of first returned row
{
$row = array_shift($rows);
$uid = $row['uid'];
}
$mail_ui->get_load_email_data($uid, null, 'INBOX');
$bodytime = microtime(true);
$times += array(
$prefix.'login' => $logintime - $starttime,
$prefix.'listmailboxes' => $listmailboxestime - $logintime,
$prefix.'fetch' => $fetchtime - $listmailboxestime,
$prefix.'total' => $fetchtime - $starttime,
$prefix.'body' => $bodytime - $fetchtime,
//$prefix.'mboxes' => $mboxes,
);
unset($mboxes);
$mail_ui->mail_bo->icServer->close();
$mail_ui->mail_bo->icServer->logout();
}
function horde_times(emailadmin_account $account, array &$times, $prefix='horde_')
{
$starttime = microtime(true);
$imap = $account->imapServer();
// connect to imap server
$imap->login();
$logintime = microtime(true);
// list all subscribed mailboxes incl. attributes and children
$mboxes = $imap->listMailboxes('*', Horde_Imap_Client::MBOX_SUBSCRIBED, array(
'attributes' => true,
'children' => true,
));
$listmailboxestime = microtime(true);
// fetch 20 newest mails
horde_fetch($imap);
$fetchtime = microtime(true);
$times += array(
$prefix.'login' => $logintime - $starttime,
$prefix.'listmailboxes' => $listmailboxestime - $logintime,
$prefix.'fetch' => $fetchtime - $listmailboxestime,
$prefix.'total' => $fetchtime - $starttime,
//$prefix.'mboxes' => $mboxes,
);
unset($mboxes);
$imap->close();
$imap->logout();
}
function horde_fetch(Horde_Imap_Client_Socket $client, $mailbox='INBOX')
{
$squery = new Horde_Imap_Client_Search_Query();
// using a date filter to limit returned uids, gives huge speed improvement on big mailboxes, because less uids returned
//$squery->dateSearch(new DateTime('-30days'), Horde_Imap_Client_Search_Query::DATE_SINCE, false, false);
$squery->flag('DELETED', $set=false);
$sorted = $client->search($mailbox, $squery, array(
'sort' => array(Horde_Imap_Client::SORT_REVERSE, Horde_Imap_Client::SORT_SEQUENCE),
));
$first20uids = new Horde_Imap_Client_Ids();
$first20uids->add(array_slice($sorted['match']->ids, 0, 20));
$fquery = new Horde_Imap_Client_Fetch_Query();
$fquery->headers('headers', array('Subject', 'From', 'To', 'Cc', 'Date'), array('peek' => true,'cache' => true));
$fquery->structure();
$fquery->flags();
$fquery->imapDate();
return $client->fetch($mailbox, $fquery, array(
'ids' => $first20uids,
));
}