Files
server/usr/share/psa-pear/pear/php/Horde/Mail/Autoconfig.php
2026-01-07 20:52:11 +01:00

237 lines
7.2 KiB
PHP

<?php
/**
* Copyright 2014-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @category Horde
* @copyright 2014-2016 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Mail_Autoconfig
*/
/**
* Object to perform autodetermination of mail configuration parameters.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2014-2016 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Mail_Autoconfig
*/
class Horde_Mail_Autoconfig
{
/**
* Drivers. Shared between all instances.
*
* @var array
*/
protected static $_driverlist;
/**
* Driver list.
*
* @var array
*/
protected $_drivers;
/**
* Load the list of drivers.
*
* @return array
*/
public static function getDrivers()
{
if (isset(self::$_driverlist)) {
return self::$_driverlist;
}
$fi = new FilesystemIterator(__DIR__ . '/Autoconfig/Driver');
$class_prefix = __CLASS__ . '_Driver_';
$drivers = array();
foreach ($fi as $val) {
if ($val->isFile()) {
$cname = $class_prefix . $val->getBasename('.php');
if (class_exists($cname)) {
$ob = new $cname();
if ($ob instanceof Horde_Mail_Autoconfig_Driver) {
$drivers[$ob->priority][] = $ob;
}
}
}
}
ksort($drivers, SORT_NUMERIC);
$flatten = array();
array_walk_recursive(
$drivers,
function($a) use (&$flatten) { $flatten[] = $a; }
);
self::$_driverlist = $flatten;
return $flatten;
}
/**
* Constructor.
*
* @param array $opts Configuration options:
* - drivers: (array) Use this list of drivers instead of the default
* autodetected list of drivers contained in this package.
*/
public function __construct(array $opts = array())
{
$this->_drivers = isset($opts['drivers'])
? $opts['drivers']
: self::getDrivers();
}
/**
* Determine the configuration for a message submission agent (MSA).
*
* @param string $email An e-mail address.
* @param array $opts Additional options:
* - auth: (mixed) If set, will perform additional check to verify that
* user can authenticate to server. Either a string (password)
* or a Horde_Smtp_Password object.
* - insecure: (boolean) If true and checking authentication, will allow
* non-secure authentication types.
*
* @return Horde_Mail_Autoconfig_Server The server object to use, or
* false if no server could be
* found.
*
* @throws Horde_Mail_Autoconfig_Exception
*/
public function getMsaConfig($email, array $opts = array())
{
return $this->_getConfig('msaSearch', $email, $opts);
}
/**
* Determine the configuration for a message storage access server (i.e.
* IMAP and/or POP3 server).
*
* @param string $email An e-mail address.
* @param array $opts Additional options:
* - auth: (mixed) If set, will perform additional check to verify that
* user can authenticate to server. Either a string (password)
* or a Horde_Smtp_Password object.
* - insecure: (boolean) If true and checking authentication, will allow
* non-secure authentication types.
* - no_imap: (boolean) If true, will not autoconfig IMAP servers.
* - no_pop3: (boolean) If true, will not autoconfig POP3 servers.
*
* @return Horde_Mail_Autoconfig_Server The server object to use, or
* false if no server could be
* found.
* @throws Horde_Mail_Autoconfig_Exception
*/
public function getMailConfig($email, array $opts = array())
{
return $this->_getConfig('mailSearch', $email, $opts);
}
/* Internal methods. */
/**
* Parse e-mail input.
*
* @param string $email An e-mail address.
*
* @return array The email object and a list of (sub)domains.
* @throws Horde_Mail_Autoconfig_Exception
*/
protected function _parseEmail($email)
{
$rfc822 = new Horde_Mail_Rfc822();
try {
$alist = $rfc822->parseAddressList($email, array(
'limit' => 1
));
} catch (Horde_Mail_Exception $e) {
throw new Horde_Mail_Autoconfig_Exception($e);
}
if (!($ob = $alist[0])) {
throw new Horde_Mail_Autoconfig_Exception(
'Could not parse e-mail address given.'
);
}
$host = $alist[0]->host_idn;
if (!strlen($host)) {
throw new Horde_Mail_Autoconfig_Exception(
'Could not determine domain name from e-mail address given.'
);
}
/* Split into subdomains, and add with deepest subdomain first. */
$domains = array();
$parts = explode('.', $host);
while (count($parts) >= 2) {
$domains[] = implode('.', $parts);
array_shift($parts);
}
return array($alist[0], $domains);
}
/**
* Determine autoconfiguration details.
*
* @param string $type The type of driver search to do.
* @param string $email An e-mail address.
* @param array $opts Options (see getMsaConfig() and getMailConfig()).
*
* @return mixed See getMsaConfig() and getMailConfig().
* @throws Horde_Mail_Autoconfig_Exception
*/
public function _getConfig($type, $email, $opts)
{
list($email_ob, $domains) = $this->_parseEmail($email);
$dconfig = array(
'email' => $email_ob,
/* This is only used for IMAP/POP3 driver, but not harm in
* adding for MSA driver. */
'no_imap' => !empty($opts['no_imap']),
'no_pop3' => !empty($opts['no_pop3'])
);
foreach ($this->_drivers as $val) {
$res = $val->$type($domains, $dconfig);
if ($res) {
foreach ($res as $val2) {
$vconfig = $opts;
if ($val2->username) {
$vconfig['users'] = array($val2->username);
} elseif ($email_ob->valid) {
/* RFC 6186 says to always try full email first, so
* use that as a default for all drivers that don't
* explicitly set a username. */
$vconfig['users'] = array(
$email_ob->bare_address,
$email_ob->mailbox
);
}
if ($val2->valid($vconfig)) {
return $val2;
}
}
}
}
return false;
}
}