package.xml 0000644 0001750 0000764 00000045507 12267540554 013214 0 ustar slusarz slusarz
Horde_Mailpear.horde.orgHorde Mail LibraryProvides interfaces for sending e-mail messages and parsing e-mail addresses.Michael Slusarzslusarzslusarz@horde.orgyes2014-01-212.1.42.1.0stablestableBSD-2-Clause
* [mms] More thorough job trying to parse addresses that contain an @ but no domain information.
5.3.01.7.0Horde_Exceptionpear.horde.org2.0.03.0.0alpha13.0.0alpha1Horde_Mimepear.horde.org2.0.03.0.0alpha13.0.0alpha1Horde_Stream_Filterpear.horde.org2.0.03.0.0alpha13.0.0alpha1Horde_Smtppear.horde.org1.0.02.0.0alpha12.0.0alpha1Horde_Supportpear.horde.org2.0.03.0.0alpha13.0.0alpha1Horde_Testpear.horde.org2.1.03.0.0alpha13.0.0alpha1Net_DNS2pear.php.netNet_SMTPpear.php.net1.6.01.0.0alpha11.0.0alphaalpha2011-03-08BSD-2-Clause
* First alpha release for Horde 4.
1.0.0beta11.0.0betabeta2011-03-16BSD-2-Clause
* First beta release for Horde 4.
1.0.0RC11.0.0betabeta2011-03-22BSD-2-Clause
* First release candidate for Horde 4.
* [jan] Fix passing arguments to sendmail binary (Gonçalo Queirós, Bug #9693).
1.0.0RC21.0.0betabeta2011-03-29BSD-2-Clause
* Second release candidate for Horde 4.
1.0.01.0.0stablestable2011-04-06BSD-2-Clause
* First stable release for Horde 4.
1.0.11.0.0stablestable2011-09-20BSD-2-Clause
* [mms] Fix parseAddressList() for empty address strings (Bug #10534).
* [mms] Fix SMTP error codes/messages (Bug #10498).
1.0.21.0.0stablestable2011-11-18BSD-2-Clause
* [mms] Always use canonical line endings in sendmail driver (Bug #10696).
1.0.31.0.0stablestable2012-01-17BSD-2-Clause
* [mms] Fix line-endings for transport drivers that send messages using local tools/programs.
1.1.01.1.0stablestable2012-02-22BSD-2-Clause
* [mms] Created Horde_Mail_Rfc822_Address and Horde_Mail_Rfc822_Group objects to represent e-mail addresses.
* [mms] Improved parser for e-mail addresses (Request #10949).
1.2.01.2.0stablestable2012-04-10BSD-2-Clause
* [mms] Added Horde_Mail_Rfc822_Address#encoded property.
* [mms] Better support for IDN hosts in non-validate address parsing mode (Bug #11021).
* [mms] Added Horde_Mail_Rfc822#trimAddress().
* [mms] Add optional arguments to the Horde_Mail_Rfc822_Group constructor.
* [mms] Horde_Mail_Rfc822#parseAddressList() now accepts Horde_Mail_Rfc822_Objects within the first argument.
* [mms] The address and group objects now extend the base Horde_Mail_Rfc822_Object class.
* [mms] Add optional arguments to the Horde_Mail_Rfc822_Group constructor.
* [mms] First argument to Horde_Mail_Rfc822#parseAddressList() can now be an array of addresses.
* [mms] Add Horde_Mail_Rfc822#encode().
* [mms] Workaround unexpected return from PHP_EOL in Mail transport drivers.
1.2.11.2.0stablestable2012-04-10BSD-2-Clause
*
2012-07-052.0.0alpha12.0.0alpha1alphaalphaBSD-2-Clause
* First alpha release for Horde 5.
* [mms] Implement new 2.0 API. See UPGRADING for full details of changes.
2.0.0beta12.0.0beta1betabeta2012-07-19BSD-2-Clause
* First beta release for Horde 5.
2.0.0beta22.0.0beta1betabeta2012-08-29BSD-2-Clause
* [mms] Add Horde_Mail_Rfc822_Address#matchDomain().
* [mms] Add Horde_Mail_Rfc822_Address#matchInsensitive().
* [mms] Fix parsing Return-Path header when using sendmail driver (Bug #11361).
2.0.02.0.0stablestable2012-10-30BSD-2-Clause
* First stable release for Horde 5.
2.0.12.0.0stablestable2012-11-16BSD-2-Clause
* [mms] Ensure bare address is output to SMTP MAIL command.
2.0.22.0.0stablestable2012-12-03BSD-2-Clause
* [mms] Fix default_domain parameter to Horde_Mail_Rfc822 (Bug #11804).
2.0.32.0.0stablestable2012-12-26BSD-2-Clause
* [mms] Fix behavior of 'persist' option in SMTP transport driver.
2.0.42.0.0stablestable2013-03-05BSD-2-Clause
* [mms] Improve unit tests.
2.0.52.0.0stablestable2013-04-08BSD-2-Clause
* [mms] Correctly encode IDN domains when sending mail (Bug #12116).
2.0.62.0.0stablestable2013-07-16BSD-2-Clause
* [mms] Honor 'pipelining' configuration option in SMTP transport driver.
2.1.02.1.0stablestable2013-08-22BSD-2-Clause
* [mms] Added the Horde_Mail_Transport_Smtphorde driver.
* [mms] Added the 'bare_addresses_idn' property to Horde_Mail_Rfc822_List.
* [mms] Added the 'bare_address_idn' property to Horde_Mail_Rfc822_Address.
2.1.12.1.0stablestable2013-08-26BSD-2-Clause
* [mms] Workaround broken Net_SMTP handling regarding the end of message data (Bug #12614).
2.1.22.1.0stablestable2013-10-15BSD-2-Clause
* [mms] Discard personal information when it is identical to e-mail address.
2.1.32.1.0stablestable2014-01-17BSD-2-Clause
* [mms] Correctly identify e-mail addresses without domain information when validating.
2.1.42.1.0stablestable2014-01-21BSD-2-Clause
* [mms] More thorough job trying to parse addresses that contain an @ but no domain information.
Horde_Mail-2.1.4/doc/Horde/Mail/COPYING 0000644 0001750 0000764 00000002430 12267540554 017251 0 ustar slusarz slusarz Copyright 1999-2013 Horde LLC. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HORDE PROJECT
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Horde_Mail-2.1.4/doc/Horde/Mail/UPGRADING 0000644 0001750 0000764 00000006642 12267540554 017472 0 ustar slusarz slusarz ======================
Upgrading Horde_Mail
======================
:Contact: dev@lists.horde.org
.. contents:: Contents
.. section-numbering::
This lists the API changes between releases of the package.
Upgrading to 2.1
================
- Horde_Mail_Rfc822_Address
Added the 'bare_address_idn' property.
- Horde_Mail_Rfc822_List
Added the 'bare_addresses_idn' property.
- Horde_Mail_Transport_Smtphorde
This Transport driver has been added.
Upgrading to 2.0
================
- Horde_Mail
This class has been removed (no more Horde_Mail#factory()). Directly
instantiate a transport driver instead.
- Horde_Mail_Rfc822
The 'num_groups' property has been removed.
The validateMailbox() method has been removed.
parseAddressList() now returns a Horde_Mail_Rfc822_List object.
The 'group' parameter to parseAddressList() has been added.
The 'nest_groups' parameter to parseAddressList() has been removed.
parseAddressList() does not validate by default.
- Horde_Mail_Rfc822_Address
The object can no longer be accessed as an array.
Removed the 'adl', 'route', and 'personal_decoded' properties.
The 'personal' property now always returns the MIME decoded personal part.
The 'host' property now always returns the IDN decoded host.
The 'encode' and 'idn' parameters to writeAddress() have changed behavior.
Added the 'host_idn' and 'valid' properties.
Renamed the 'full_address' property to 'bare_address'.
- Horde_Mail_Rfc822_Group
The object can no longer be accessed as an array.
Removed the 'groupname_decoded' property.
The 'groupname' property now always returns the MIME decoded groupname.
The 'encode' and 'idn' parameters to writeAddress() have changed behavior.
Added the 'valid' property.
- Horde_Mail_Rfc822_Object
Added a match() method.
Passing boolean true to writeAddress() now defaults to full encoding of
the address.
Upgrading To 1.2
================
Method API additions
--------------------
- Horde_Mail_Rfc822#parseAddressList()
The first argument can now be a Horde_Mail_Rfc822_Object or an array of
address strings and/or Horde_Mail_Rfc822_Objects.
- Horde_Mail_Rfc822_Address#__construct()
The constructor now takes 1 optional argument: address.
- Horde_Mail_Rfc822_Group#__construct()
The constructor now takes 2 optional arguments: groupname and group
addresses.
New Methods
-----------
- Horde_Mail_Rfc822#encode()
- Horde_Mail_Rfc822#trimAddress()
New Objects
-----------
- Horde_Mail_Rfc822_Object
Horde_Mail_Rfc822_Address and Horde_Mail_Rfc822_Group now extend this
class. Allows for easier determination if an object contains RFC 822
element information.
Upgrading To 1.1
================
New Objects
-----------
Horde_Mail_Rfc822::parseAddressList() now returns an array of
Horde_Mail_Rfc822_Address objects (and Horde_Mail_Rfc822_Group objects, if
nest_groups is true).
These objects are backward compatible with the former array representation.
They also include additional functionality.
- Horde_Mail_Rfc822_Address
Anything other than accessing these properties is a new feature available
only since 1.1.0:
- adl
- comment
- host
- mailbox
- personal
- Horde_Mail_Rfc822_Group
Anything other than accessing these properties is a new feature available
only since 1.1.0:
- addresses
- groupname
Horde_Mail-2.1.4/lib/Horde/Mail/Rfc822/Address.php 0000644 0001750 0000764 00000014745 12267540554 021277 0 ustar slusarz slusarz
* @category Horde
* @copyright 2012-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*
* @property-read string $bare_address The bare mailbox@host address.
* @property-read string $bare_address_idn The bare mailbox@host address (IDN
* encoded). (@since 2.1.0)
* @property-read string $encoded The full MIME/IDN encoded address (UTF-8).
* @property string $host Returns the host part (UTF-8).
* @property-read string $host_idn Returns the IDN encoded host part.
* @property-read string $label The shorthand label for this address.
* @property string $personal The personal part (UTF-8).
* @property-read string $personal_encoded The MIME encoded personal part
* (UTF-8).
* @property-read boolean $valid Returns true if there is enough information
* in object to create a valid address.
*/
class Horde_Mail_Rfc822_Address extends Horde_Mail_Rfc822_Object
{
/**
* Comments associated with the personal phrase.
*
* @var array
*/
public $comment = array();
/**
* Local-part of the address.
*
* @var string
*/
public $mailbox = null;
/**
* Hostname of the address.
*
* @var string
*/
protected $_host = null;
/**
* Personal part of the address.
*
* @var string
*/
protected $_personal = null;
/**
* Constructor.
*
* @param string $address If set, address is parsed and used as the
* object address. Address is not validated;
* first e-mail address parsed is used.
*/
public function __construct($address = null)
{
if (!is_null($address)) {
$rfc822 = new Horde_Mail_Rfc822();
$addr = $rfc822->parseAddressList($address);
if (count($addr)) {
foreach ($addr[0] as $key => $val) {
$this->$key = $val;
}
}
}
}
/**
*/
public function __set($name, $value)
{
switch ($name) {
case 'host':
$value = ltrim($value, '@');
$this->_host = function_exists('idn_to_utf8')
? strtolower(idn_to_utf8($value))
: strtolower($value);
break;
case 'personal':
$this->_personal = strlen($value)
? Horde_Mime::decode($value)
: null;
break;
}
}
/**
*/
public function __get($name)
{
switch ($name) {
case 'bare_address':
return is_null($this->host)
? $this->mailbox
: $this->mailbox . '@' . $this->host;
case 'bare_address_idn':
$personal = $this->_personal;
$this->_personal = null;
$res = $this->encoded;
$this->_personal = $personal;
return $res;
case 'encoded':
return $this->writeAddress(true);
case 'host':
return $this->_host;
case 'host_idn':
return function_exists('idn_to_ascii')
? idn_to_ascii($this->_host)
: $this->host;
case 'label':
return is_null($this->personal)
? $this->bare_address
: $this->_personal;
case 'personal':
return (strcasecmp($this->_personal, $this->bare_address) === 0)
? null
: $this->_personal;
case 'personal_encoded':
return Horde_Mime::encode($this->personal);
case 'valid':
return (bool)strlen($this->mailbox);
default:
return null;
}
}
/**
*/
protected function _writeAddress($opts)
{
$rfc822 = new Horde_Mail_Rfc822();
$address = $rfc822->encode($this->mailbox, 'address');
$host = empty($opts['idn']) ? $this->host : $this->host_idn;
if (strlen($host)) {
$address .= '@' . $host;
}
$personal = $this->personal;
if (strlen($personal)) {
if (!empty($opts['encode'])) {
$personal = Horde_Mime::encode($this->personal, $opts['encode']);
}
$personal = $rfc822->encode($personal, 'personal');
}
return (strlen($personal) && ($personal != $address))
? $personal . ' <' . $address . '>'
: $address;
}
/**
*/
public function match($ob)
{
if (!($ob instanceof Horde_Mail_Rfc822_Address)) {
$ob = new Horde_Mail_Rfc822_Address($ob);
}
return ($this->bare_address == $ob->bare_address);
}
/**
* Do a case-insensitive match on the address. Per RFC 822/2822/5322,
* although the host portion of an address is case-insensitive, the
* mailbox portion is platform dependent.
*
* @param mixed $ob Address data.
*
* @return boolean True if the data reflects the same case-insensitive
* address.
*/
public function matchInsensitive($ob)
{
if (!($ob instanceof Horde_Mail_Rfc822_Address)) {
$ob = new Horde_Mail_Rfc822_Address($ob);
}
return (Horde_String::lower($this->bare_address) == Horde_String::lower($ob->bare_address));
}
/**
* Do a case-insensitive match on the address for a given domain.
* Matches as many parts of the subdomain in the address as is given in
* the input.
*
* @param string $domain Domain to match.
*
* @return boolean True if the address matches the given domain.
*/
public function matchDomain($domain)
{
$host = $this->host;
if (is_null($host)) {
return false;
}
$match_domain = explode('.', $domain);
$match_host = array_slice(explode('.', $host), count($match_domain) * -1);
return (strcasecmp($domain, implode('.', $match_host)) === 0);
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Rfc822/Group.php 0000644 0001750 0000764 00000007105 12267540554 020776 0 ustar slusarz slusarz
* @category Horde
* @copyright 2012-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*
* @property string $groupname Groupname (UTF-8).
* @property-read string $groupname_encoded MIME encoded groupname (UTF-8).
* @property-read string $label The shorthand label for this group.
* @property-read boolean $valid Returns true if there is enough information
* in object to create a valid address.
*/
class Horde_Mail_Rfc822_Group extends Horde_Mail_Rfc822_Object implements Countable
{
/**
* List of group e-mail address objects.
*
* @var Horde_Mail_Rfc822_GroupList
*/
public $addresses;
/**
* Group name (MIME decoded).
*
* @var string
*/
protected $_groupname = 'Group';
/**
* Constructor.
*
* @param string $groupname If set, used as the group name.
* @param mixed $addresses If a GroupList object, used as the address
* list. Any other non-null value is parsed and
* used as the address list (addresses not
* verified; sub-groups are ignored).
*/
public function __construct($groupname = null, $addresses = null)
{
if (!is_null($groupname)) {
$this->groupname = $groupname;
}
if (is_null($addresses)) {
$this->addresses = new Horde_Mail_Rfc822_GroupList();
} elseif ($addresses instanceof Horde_Mail_Rfc822_GroupList) {
$this->addresses = clone $addresses;
} else {
$rfc822 = new Horde_Mail_Rfc822();
$this->addresses = $rfc822->parseAddressList($addresses, array(
'group' => true
));
}
}
/**
*/
public function __set($name, $value)
{
switch ($name) {
case 'groupname':
$this->_groupname = Horde_Mime::decode($value);
break;
}
}
/**
*/
public function __get($name)
{
switch ($name) {
case 'groupname':
case 'label':
return $this->_groupname;
case 'groupname_encoded':
return Horde_Mime::encode($this->_groupname);
case 'valid':
return (bool)strlen($this->_groupname);
default:
return null;
}
}
/**
*/
protected function _writeAddress($opts)
{
$addr = $this->addresses->writeAddress($opts);
$groupname = $this->groupname;
if (!empty($opts['encode'])) {
$groupname = Horde_Mime::encode($groupname, $opts['encode']);
}
$rfc822 = new Horde_Mail_Rfc822();
return $rfc822->encode($groupname, 'personal') . ':' .
(strlen($addr) ? (' ' . $addr) : '') . ';';
}
/**
*/
public function match($ob)
{
return $this->addresses->match($ob);
}
/* Countable methods. */
/**
* Address count.
*
* @return integer The number of addresses.
*/
public function count()
{
return count($this->addresses);
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Rfc822/GroupList.php 0000644 0001750 0000764 00000002512 12267540554 021627 0 ustar slusarz slusarz
* @category Horde
* @copyright 2012-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Rfc822_GroupList extends Horde_Mail_Rfc822_List
{
/**
* Add objects to the container.
*
* @param mixed $obs A RFC 822 object (or list of objects) to store in
* this object.
*/
public function add($obs)
{
if ($obs instanceof Horde_Mail_Rfc822_Object) {
$obs = array($obs);
}
foreach ($obs as $val) {
/* Only allow addresses. */
if ($val instanceof Horde_Mail_Rfc822_Address) {
parent::add($val);
}
}
}
/**
* Group count.
*
* @return integer The number of groups in the list.
*/
public function groupCount()
{
return 0;
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Rfc822/List.php 0000644 0001750 0000764 00000030352 12267540554 020615 0 ustar slusarz slusarz
* @category Horde
* @copyright 2012-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*
* @property-read array $addresses The list of all addresses (address
* w/personal parts).
* @property-read array $bare_addresses The list of all addresses (mail@host).
* @property-read array $bare_addresses_idn The list of all addresses
* (mail@host; IDN encoded).
* (@since 2.1.0)
* @property-read array $base_addresses The list of ONLY base addresses
* (Address objects).
* @property-read array $raw_addresses The list of all addresses (Address
* objects).
*/
class Horde_Mail_Rfc822_List extends Horde_Mail_Rfc822_Object implements ArrayAccess, Countable, SeekableIterator, Serializable
{
/** Filter masks. */
const HIDE_GROUPS = 1;
const BASE_ELEMENTS = 2;
/**
* List data.
*
* @var array
*/
protected $_data = array();
/**
* Current Iterator filter.
*
* @var array
*/
protected $_filter = array();
/**
* Current Iterator pointer.
*
* @var array
*/
protected $_ptr;
/**
* Constructor.
*
* @param mixed $obs Address data to store in this object.
*/
public function __construct($obs = null)
{
if (!is_null($obs)) {
$this->add($obs);
}
}
/**
*/
public function __get($name)
{
switch ($name) {
case 'addresses':
case 'bare_addresses':
case 'bare_addresses_idn':
case 'base_addresses':
case 'raw_addresses':
$old = $this->_filter;
$mask = ($name == 'base_addresses')
? self::BASE_ELEMENTS
: self::HIDE_GROUPS;
$this->setIteratorFilter($mask, empty($old['filter']) ? null : $old['filter']);
$out = array();
foreach ($this as $val) {
switch ($name) {
case 'addresses':
$out[] = strval($val);
break;
case 'bare_addresses':
$out[] = $val->bare_address;
break;
case 'bare_addresses_idn':
$out[] = $val->bare_address_idn;
break;
case 'base_addresses':
case 'raw_addresses':
$out[] = clone $val;
break;
}
}
$this->_filter = $old;
return $out;
}
}
/**
* Add objects to the container.
*
* @param mixed $obs Address data to store in this object.
*/
public function add($obs)
{
foreach ($this->_normalize($obs) as $val) {
$this->_data[] = $val;
}
}
/**
* Remove addresses from the container. This method ignores Group objects.
*
* @param mixed $obs Addresses to remove.
*/
public function remove($obs)
{
$old = $this->_filter;
$this->setIteratorFilter(self::HIDE_GROUPS | self::BASE_ELEMENTS);
foreach ($this->_normalize($obs) as $val) {
$remove = array();
foreach ($this as $key => $val2) {
if ($val2->match($val)) {
$remove[] = $key;
}
}
foreach (array_reverse($remove) as $key) {
unset($this[$key]);
}
}
$this->_filter = $old;
}
/**
* Removes duplicate addresses from list. This method ignores Group
* objects.
*/
public function unique()
{
$exist = $remove = array();
$old = $this->_filter;
$this->setIteratorFilter(self::HIDE_GROUPS | self::BASE_ELEMENTS);
// For duplicates, we use the first address that contains personal
// information.
foreach ($this as $key => $val) {
$bare = $val->bare_address;
if (isset($exist[$bare])) {
if (($exist[$bare] == -1) || is_null($val->personal)) {
$remove[] = $key;
} else {
$remove[] = $exist[$bare];
$exist[$bare] = -1;
}
} else {
$exist[$bare] = is_null($val->personal)
? $key
: -1;
}
}
foreach (array_reverse($remove) as $key) {
unset($this[$key]);
}
$this->_filter = $old;
}
/**
* Group count.
*
* @return integer The number of groups in the list.
*/
public function groupCount()
{
$ret = 0;
foreach ($this->_data as $val) {
if ($val instanceof Horde_Mail_Rfc822_Group) {
++$ret;
}
}
return $ret;
}
/**
* Set the Iterator filter.
*
* @param integer $mask Filter masks.
* @param mixed $filter An e-mail, or as list of e-mails, to filter by.
*/
public function setIteratorFilter($mask = 0, $filter = null)
{
$this->_filter = array();
if ($mask) {
$this->_filter['mask'] = $mask;
}
if (!is_null($filter)) {
$rfc822 = new Horde_Mail_Rfc822();
$this->_filter['filter'] = $rfc822->parseAddressList($filter);
}
}
/**
*/
protected function _writeAddress($opts)
{
$out = array();
foreach ($this->_data as $val) {
$out[] = $val->writeAddress($opts);
}
return implode(', ', $out);
}
/**
*/
public function match($ob)
{
if (!($ob instanceof Horde_Mail_Rfc822_List)) {
$ob = new Horde_Mail_Rfc822_List($ob);
}
$a = $this->bare_addresses;
sort($a);
$b = $ob->bare_addresses;
sort($b);
return ($a == $b);
}
/**
* Does this list contain the given e-mail address?
*
* @param mixed $address An e-mail address.
*
* @return boolean True of the e-mail address is contained in the list.
*/
public function contains($address)
{
$ob = new Horde_Mail_Rfc822_Address($address);
foreach ($this->raw_addresses as $val) {
if ($val->match($ob)) {
return true;
}
}
return false;
}
/**
* Normalize objects to add to list.
*
* @param mixed $obs Address data to store in this object.
*
* @return array Entries to add.
*/
protected function _normalize($obs)
{
$add = array();
if (!($obs instanceof Horde_Mail_Rfc822_List) &&
!is_array($obs)) {
$obs = array($obs);
}
foreach ($obs as $val) {
if (is_string($val)) {
$rfc822 = new Horde_Mail_Rfc822();
$val = $rfc822->parseAddressList($val);
}
if ($val instanceof Horde_Mail_Rfc822_List) {
$val->setIteratorFilter(self::BASE_ELEMENTS);
foreach ($val as $val2) {
$add[] = $val2;
}
} elseif ($val instanceof Horde_Mail_Rfc822_Object) {
$add[] = $val;
}
}
return $add;
}
/* ArrayAccess methods. */
/**
*/
public function offsetExists($offset)
{
return !is_null($this[$offset]);
}
/**
*/
public function offsetGet($offset)
{
try {
$this->seek($offset);
return $this->current();
} catch (OutOfBoundsException $e) {
return null;
}
}
/**
*/
public function offsetSet($offset, $value)
{
if ($ob = $this[$offset]) {
if (is_null($this->_ptr['subidx'])) {
$tmp = $this->_normalize($value);
if (isset($tmp[0])) {
$this->_data[$this->_ptr['idx']] = $tmp[0];
}
} else {
$ob[$offset] = $value;
}
$this->_ptr = null;
}
}
/**
*/
public function offsetUnset($offset)
{
if ($ob = $this[$offset]) {
if (is_null($this->_ptr['subidx'])) {
unset($this->_data[$this->_ptr['idx']]);
$this->_data = array_values($this->_data);
} else {
unset($ob->addresses[$this->_ptr['subidx']]);
}
$this->_ptr = null;
}
}
/* Countable methods. */
/**
* Address count.
*
* @return integer The number of addresses.
*/
public function count()
{
return count($this->addresses);
}
/* Iterator methods. */
public function current()
{
if (!$this->valid()) {
return null;
}
$ob = $this->_data[$this->_ptr['idx']];
return is_null($this->_ptr['subidx'])
? $ob
: $ob->addresses[$this->_ptr['subidx']];
}
public function key()
{
return $this->_ptr['key'];
}
public function next()
{
if (is_null($this->_ptr['subidx'])) {
$curr = $this->current();
if (($curr instanceof Horde_Mail_Rfc822_Group) && count($curr)) {
$this->_ptr['subidx'] = 0;
} else {
++$this->_ptr['idx'];
}
$curr = $this->current();
} elseif (!($curr = $this->_data[$this->_ptr['idx']]->addresses[++$this->_ptr['subidx']])) {
$this->_ptr['subidx'] = null;
++$this->_ptr['idx'];
$curr = $this->current();
}
if (!is_null($curr)) {
if (!empty($this->_filter) && $this->_iteratorFilter($curr)) {
$this->next();
} else {
++$this->_ptr['key'];
}
}
}
public function rewind()
{
$this->_ptr = array(
'idx' => 0,
'key' => 0,
'subidx' => null
);
if ($this->valid() &&
!empty($this->_filter) &&
$this->_iteratorFilter($this->current())) {
$this->next();
$this->_ptr['key'] = 0;
}
}
public function valid()
{
return (!empty($this->_ptr) && isset($this->_data[$this->_ptr['idx']]));
}
public function seek($position)
{
if (!$this->valid() ||
($position < $this->_ptr['key'])) {
$this->rewind();
}
for ($i = $this->_ptr['key']; ; ++$i) {
if ($i == $position) {
return;
}
$this->next();
if (!$this->valid()) {
throw new OutOfBoundsException('Position not found.');
}
}
}
protected function _iteratorFilter($ob)
{
if (!empty($this->_filter['mask'])) {
if (($this->_filter['mask'] & self::HIDE_GROUPS) &&
($ob instanceof Horde_Mail_Rfc822_Group)) {
return true;
}
if (($this->_filter['mask'] & self::BASE_ELEMENTS) &&
!is_null($this->_ptr['subidx'])) {
return true;
}
}
if (!empty($this->_filter['filter']) &&
($ob instanceof Horde_Mail_Rfc822_Address)) {
foreach ($this->_filter['filter'] as $val) {
if ($ob->match($val)) {
return true;
}
}
}
return false;
}
/* Serializable methods. */
public function serialize()
{
return serialize($this->_data);
}
public function unserialize($data)
{
$this->_data = unserialize($data);
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Rfc822/Object.php 0000644 0001750 0000764 00000004661 12267540554 021114 0 ustar slusarz slusarz
* @category Horde
* @copyright 2012-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
abstract class Horde_Mail_Rfc822_Object
{
/**
* String representation of object.
*
* @return string Returns the full e-mail address.
*/
public function __toString()
{
return $this->writeAddress();
}
/**
* Write an address given information in this part.
*
* @param mixed $opts If boolean true, is equivalent to passing true for
* both 'encode' and 'idn'. If an array, these
* keys are supported:
* - encode: (mixed) MIME encode the personal/groupname parts?
* If boolean true, encodes in 'UTF-8'.
* If a string, encodes using this charset.
* DEFAULT: false
* - idn: (boolean) If true, encodes IDN domain names
* (Punycode/RFC 3490).
* Requires the idn or intl PHP module.
* DEFAULT: false
*
* @return string The correctly escaped/quoted address.
*/
public function writeAddress($opts = array())
{
if ($opts === true) {
$opts = array(
'encode' => 'UTF-8',
'idn' => true
);
} elseif (!empty($opts['encode']) && ($opts['encode'] === true)) {
$opts['encode'] = 'UTF-8';
}
return $this->_writeAddress($opts);
}
/**
* Class-specific implementation of writeAddress().
*
* @see writeAddress()
*
* @param array $opts See writeAddress().
*
* @return string The correctly escaped/quoted address.
*/
abstract protected function _writeAddress($opts);
/**
* Compare this object against other data.
*
* @param mixed $ob Address data.
*
* @return boolean True if the data reflects the same canonical address.
*/
abstract public function match($ob);
}
Horde_Mail-2.1.4/lib/Horde/Mail/Transport/Mail.php 0000644 0001750 0000764 00000010703 12267540554 021610 0 ustar slusarz slusarz
* @author Michael Slusarz
* @category Horde
* @copyright 2010-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Transport_Mail extends Horde_Mail_Transport
{
/**
* @param array $params Additional parameters:
* - args: (string) Extra arguments for the mail() function.
*/
public function __construct(array $params = array())
{
$this->_params = array_merge($this->_params, $params);
}
/**
*/
public function send($recipients, array $headers, $body)
{
$headers = $this->_sanitizeHeaders($headers);
$recipients = $this->parseRecipients($recipients);
$subject = '';
foreach (array_keys($headers) as $hdr) {
if (strcasecmp($hdr, 'Subject') === 0) {
// Get the Subject out of the headers array so that we can
// pass it as a separate argument to mail().
$subject = $headers[$hdr];
unset($headers[$hdr]);
} elseif (strcasecmp($hdr, 'To') === 0) {
// Remove the To: header. The mail() function will add its
// own To: header based on the contents of $recipients.
unset($headers[$hdr]);
}
}
// Flatten the headers out.
list(, $text_headers) = $this->prepareHeaders($headers);
// mail() requires a string for $body. If resource, need to convert
// to a string.
if (is_resource($body)) {
$body_str = '';
stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
stream_filter_append($body, 'horde_eol', STREAM_FILTER_READ, array('eol' => $this->sep));
rewind($body);
while (!feof($body)) {
$body_str .= fread($body, 8192);
}
$body = $body_str;
} else {
// Convert EOL characters in body.
$body = $this->_normalizeEOL($body);
}
// We only use mail()'s optional fifth parameter if the additional
// parameters have been provided and we're not running in safe mode.
if (empty($this->_params) || ini_get('safe_mode')) {
$result = mail($recipients, $subject, $body, $text_headers);
} else {
$result = mail($recipients, $subject, $body, $text_headers, isset($this->_params['args']) ? $this->_params['args'] : '');
}
// If the mail() function returned failure, we need to create an
// Exception and return it instead of the boolean result.
if ($result === false) {
throw new Horde_Mail_Exception('mail() returned failure.');
}
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Transport/Mock.php 0000644 0001750 0000764 00000010356 12267540554 021623 0 ustar slusarz slusarz
* @author Michael Slusarz
* @category Horde
* @copyright 2010-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Transport_Mock extends Horde_Mail_Transport
{
/**
* Array of messages that have been sent with the mock.
*
* @var array
*/
public $sentMessages = array();
/**
* Callback before sending mail.
*
* @var callback
*/
protected $_preSendCallback;
/**
* Callback after sending mai.
*
* @var callback
*/
protected $_postSendCallback;
/**
* @param array Optional parameters:
* - postSendCallback: (callback) Called after an email would have been
* sent.
* - preSendCallback: (callback) Called before an email would be sent.
*/
public function __construct(array $params = array())
{
if (isset($params['preSendCallback']) &&
is_callable($params['preSendCallback'])) {
$this->_preSendCallback = $params['preSendCallback'];
}
if (isset($params['postSendCallback']) &&
is_callable($params['postSendCallback'])) {
$this->_postSendCallback = $params['postSendCallback'];
}
}
/**
*/
public function send($recipients, array $headers, $body)
{
if ($this->_preSendCallback) {
call_user_func_array($this->_preSendCallback, array($this, $recipients, $headers, $body));
}
$headers = $this->_sanitizeHeaders($headers);
list($from, $text_headers) = $this->prepareHeaders($headers);
if (is_resource($body)) {
stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
stream_filter_append($body, 'horde_eol', STREAM_FILTER_READ, array('eol' => $this->sep));
rewind($body);
$body_txt = stream_get_contents($body);
} else {
$body_txt = $this->_normalizeEOL($body);
}
$from = $this->_getFrom($from, $headers);
$recipients = $this->parseRecipients($recipients);
$this->sentMessages[] = array(
'body' => $body_txt,
'from' => $from,
'headers' => $headers,
'header_text' => $text_headers,
'recipients' => $recipients
);
if ($this->_postSendCallback) {
call_user_func_array($this->_postSendCallback, array($this, $recipients, $headers, $body_txt));
}
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Transport/Null.php 0000644 0001750 0000764 00000004313 12267540554 021640 0 ustar slusarz slusarz
* @author Michael Slusarz
* @category Horde
* @copyright 2010-2013 Horde LLC
* @copyright 2010 Phil Kernick
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Transport_Null extends Horde_Mail_Transport
{
/**
*/
public function send($recipients, array $headers, $body)
{
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Transport/Sendmail.php 0000644 0001750 0000764 00000014140 12267540554 022461 0 ustar slusarz slusarz
* @author Michael Slusarz
* @category Horde
* @copyright 2010-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Transport_Sendmail extends Horde_Mail_Transport
{
/**
* Any extra command-line parameters to pass to the sendmail or
* sendmail wrapper binary.
*
* @var string
*/
protected $_sendmailArgs = '-i';
/**
* The location of the sendmail or sendmail wrapper binary on the
* filesystem.
*
* @var string
*/
protected $_sendmailPath = '/usr/sbin/sendmail';
/**
* Constructor.
*
* @param array $params Additional parameters:
* - sendmail_args: (string) Any extra parameters to pass to the sendmail
* or sendmail wrapper binary.
* DEFAULT: -i
* - sendmail_path: (string) The location of the sendmail binary on the
* filesystem.
* DEFAULT: /usr/sbin/sendmail
*/
public function __construct(array $params = array())
{
if (isset($params['sendmail_args'])) {
$this->_sendmailArgs = $params['sendmail_args'];
}
if (isset($params['sendmail_path'])) {
$this->_sendmailPath = $params['sendmail_path'];
}
}
/**
*/
public function send($recipients, array $headers, $body)
{
$recipients = implode(' ', array_map('escapeshellarg', $this->parseRecipients($recipients)));
$headers = $this->_sanitizeHeaders($headers);
list($from, $text_headers) = $this->prepareHeaders($headers);
$from = $this->_getFrom($from, $headers);
$mail = @popen($this->_sendmailPath . (empty($this->_sendmailArgs) ? '' : ' ' . $this->_sendmailArgs) . ' -f ' . escapeshellarg($from) . ' -- ' . $recipients, 'w');
if (!$mail) {
throw new Horde_Mail_Exception('Failed to open sendmail [' . $this->_sendmailPath . '] for execution.');
}
// Write the headers following by two newlines: one to end the headers
// section and a second to separate the headers block from the body.
fputs($mail, $text_headers . $this->sep . $this->sep);
if (is_resource($body)) {
stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
stream_filter_append($body, 'horde_eol', STREAM_FILTER_READ, array('eol' => $this->sep));
rewind($body);
while (!feof($body)) {
fputs($mail, fread($body, 8192));
}
} else {
fputs($mail, $this->_normalizeEOL($body));
}
$result = pclose($mail);
if (!$result) {
return;
}
switch ($result) {
case 64: // EX_USAGE
$msg = 'command line usage error';
break;
case 65: // EX_DATAERR
$msg = 'data format error';
break;
case 66: // EX_NOINPUT
$msg = 'cannot open input';
break;
case 67: // EX_NOUSER
$msg = 'addressee unknown';
break;
case 68: // EX_NOHOST
$msg = 'host name unknown';
break;
case 69: // EX_UNAVAILABLE
$msg = 'service unavailable';
break;
case 70: // EX_SOFTWARE
$msg = 'internal software error';
break;
case 71: // EX_OSERR
$msg = 'system error';
break;
case 72: // EX_OSFILE
$msg = 'critical system file missing';
break;
case 73: // EX_CANTCREAT
$msg = 'cannot create output file';
break;
case 74: // EX_IOERR
$msg = 'input/output error';
case 75: // EX_TEMPFAIL
$msg = 'temporary failure';
break;
case 76: // EX_PROTOCOL
$msg = 'remote error in protocol';
break;
case 77: // EX_NOPERM
$msg = 'permission denied';
break;
case 78: // EX_CONFIG
$msg = 'configuration error';
break;
case 79: // EX_NOTFOUND
$msg = 'entry not found';
break;
default:
$msg = 'unknown error';
break;
}
throw new Horde_Mail_Exception('sendmail: ' . $msg . ' (' . $result . ')', $result);
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Transport/Smtp.php 0000644 0001750 0000764 00000027163 12267540554 021661 0 ustar slusarz slusarz
* @author Jon Parise
* @author Michael Slusarz
* @category Horde
* @copyright 2010-2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Transport_Smtp extends Horde_Mail_Transport
{
/* Error: Failed to create a Net_SMTP object */
const ERROR_CREATE = 10000;
/* Error: Failed to connect to SMTP server */
const ERROR_CONNECT = 10001;
/* Error: SMTP authentication failure */
const ERROR_AUTH = 10002;
/* Error: No From: address has been provided */
const ERROR_FROM = 10003;
/* Error: Failed to set sender */
const ERROR_SENDER = 10004;
/* Error: Failed to add recipient */
const ERROR_RECIPIENT = 10005;
/* Error: Failed to send data */
const ERROR_DATA = 10006;
/**
* The SMTP greeting.
*
* @var string
*/
public $greeting = null;
/**
* The SMTP queued response.
*
* @var string
*/
public $queuedAs = null;
/**
* SMTP connection object.
*
* @var Net_SMTP
*/
protected $_smtp = null;
/**
* The list of service extension parameters to pass to the Net_SMTP
* mailFrom() command.
*
* @var array
*/
protected $_extparams = array();
/**
* Constructor.
*
* @param array $params Additional parameters:
* - auth: (mixed) SMTP authentication.
* This value may be set to true, false or the name of a
* specific authentication method. If the value is set to true,
* the Net_SMTP package will attempt to use the best
* authentication method advertised by the remote SMTP server.
* DEFAULT: false.
* - debug: (boolean) Activate SMTP debug mode?
* DEFAULT: false
* - host: (string) The server to connect to.
* DEFAULT: localhost
* - localhost: (string) Hostname or domain that will be sent to the
* remote SMTP server in the HELO / EHLO message.
* DEFAULT: localhost
* - password: (string) The password to use for SMTP auth.
* DEFAULT: NONE
* - persist: (boolean) Should the SMTP connection persist?
* DEFAULT: false
* - pipelining: (boolean) Use SMTP command pipelining.
* Use SMTP command pipelining (specified in RFC 2920) if
* the SMTP server supports it. This speeds up delivery
* over high-latency connections.
* DEFAULT: false (use default value from Net_SMTP)
* - port: (integer) The port to connect to.
* DEFAULT: 25
* - timeout: (integer) The SMTP connection timeout.
* DEFAULT: NONE
* - username: (string) The username to use for SMTP auth.
* DEFAULT: NONE
*/
public function __construct(array $params = array())
{
$this->_params = array_merge(array(
'auth' => false,
'debug' => false,
'host' => 'localhost',
'localhost' => 'localhost',
'password' => '',
'persist' => false,
'pipelining' => false,
'port' => 25,
'timeout' => null,
'username' => ''
), $params);
/* Destructor implementation to ensure that we disconnect from any
* potentially-alive persistent SMTP connections. */
register_shutdown_function(array($this, 'disconnect'));
/* SMTP requires CRLF line endings. */
$this->sep = "\r\n";
}
/**
*/
public function send($recipients, array $headers, $body)
{
/* If we don't already have an SMTP object, create one. */
$this->getSMTPObject();
$headers = $this->_sanitizeHeaders($headers);
/* Make sure the message has a trailing newline. */
if (is_resource($body)) {
fseek($body, -1, SEEK_END);
switch (fgetc($body)) {
case "\r":
if (fgetc($body) != "\n") {
fputs($body, "\n");
}
break;
default:
fputs($body, "\r\n");
break;
}
rewind($body);
} elseif (substr($body, -2, 0) != "\r\n") {
$body .= "\r\n";
}
try {
list($from, $textHeaders) = $this->prepareHeaders($headers);
} catch (Horde_Mail_Exception $e) {
$this->_smtp->rset();
throw $e;
}
try {
$from = $this->_getFrom($from, $headers);
} catch (Horde_Mail_Exception $e) {
$this->_smtp->rset();
throw new Horde_Mail_Exception('No From: address has been provided', self::ERROR_FROM);
}
$params = '';
foreach ($this->_extparams as $key => $val) {
$params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
}
$res = $this->_smtp->mailFrom($from, ltrim($params));
if ($res instanceof PEAR_Error) {
$this->_error(sprintf("Failed to set sender: %s", $from), $res, self::ERROR_SENDER);
}
try {
$recipients = $this->parseRecipients($recipients);
} catch (Horde_Mail_Exception $e) {
$this->_smtp->rset();
throw $e;
}
foreach ($recipients as $recipient) {
$res = $this->_smtp->rcptTo($recipient);
if ($res instanceof PEAR_Error) {
$this->_error("Failed to add recipient: $recipient", $res, self::ERROR_RECIPIENT);
}
}
/* Send the message's headers and the body as SMTP data. Net_SMTP does
* the necessary EOL conversions. */
$res = $this->_smtp->data($body, $textHeaders);
list(,$args) = $this->_smtp->getResponse();
if (preg_match("/Ok: queued as (.*)/", $args, $queued)) {
$this->queuedAs = $queued[1];
}
/* We need the greeting; from it we can extract the authorative name
* of the mail server we've really connected to. Ideal if we're
* connecting to a round-robin of relay servers and need to track
* which exact one took the email */
$this->greeting = $this->_smtp->getGreeting();
if ($res instanceof PEAR_Error) {
$this->_error('Failed to send data', $res, self::ERROR_DATA);
}
/* If persistent connections are disabled, destroy our SMTP object. */
if (!$this->_params['persist']) {
$this->disconnect();
}
}
/**
* Connect to the SMTP server by instantiating a Net_SMTP object.
*
* @return Net_SMTP The SMTP object.
* @throws Horde_Mail_Exception
*/
public function getSMTPObject()
{
if ($this->_smtp) {
return $this->_smtp;
}
$this->_smtp = new Net_SMTP(
$this->_params['host'],
$this->_params['port'],
$this->_params['localhost']
);
/* Set pipelining. */
if ($this->_params['pipelining']) {
$this->_smtp->pipelining = true;
}
/* If we still don't have an SMTP object at this point, fail. */
if (!($this->_smtp instanceof Net_SMTP)) {
throw new Horde_Mail_Exception('Failed to create a Net_SMTP object', self::ERROR_CREATE);
}
/* Configure the SMTP connection. */
if ($this->_params['debug']) {
$this->_smtp->setDebug(true);
}
/* Attempt to connect to the configured SMTP server. */
$res = $this->_smtp->connect($this->_params['timeout']);
if ($res instanceof PEAR_Error) {
$this->_error('Failed to connect to ' . $this->_params['host'] . ':' . $this->_params['port'], $res, self::ERROR_CONNECT);
}
/* Attempt to authenticate if authentication has been enabled. */
if ($this->_params['auth']) {
$method = is_string($this->_params['auth'])
? $this->_params['auth']
: '';
$res = $this->_smtp->auth($this->_params['username'], $this->_params['password'], $method);
if ($res instanceof PEAR_Error) {
$this->_error("$method authentication failure", $res, self::ERROR_AUTH);
}
}
return $this->_smtp;
}
/**
* Add parameter associated with a SMTP service extension.
*
* @param string $keyword Extension keyword.
* @param string $value Any value the keyword needs.
*/
public function addServiceExtensionParameter($keyword, $value = null)
{
$this->_extparams[$keyword] = $value;
}
/**
* Disconnect and destroy the current SMTP connection.
*
* @return boolean True if the SMTP connection no longer exists.
*/
public function disconnect()
{
/* If we have an SMTP object, disconnect and destroy it. */
if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
$this->_smtp = null;
}
/* We are disconnected if we no longer have an SMTP object. */
return ($this->_smtp === null);
}
/**
* Build a standardized string describing the current SMTP error.
*
* @param string $text Custom string describing the error context.
* @param PEAR_Error $error PEAR_Error object.
* @param integer $e_code Error code.
*
* @throws Horde_Mail_Exception
*/
protected function _error($text, $error, $e_code)
{
/* Split the SMTP response into a code and a response string. */
list($code, $response) = $this->_smtp->getResponse();
/* Abort current SMTP transaction. */
$this->_smtp->rset();
/* Build our standardized error string. */
throw new Horde_Mail_Exception($text . ' [SMTP: ' . $error->getMessage() . " (code: $code, response: $response)]", $e_code);
}
}
Horde_Mail-2.1.4/lib/Horde/Mail/Transport/Smtphorde.php 0000644 0001750 0000764 00000011553 12267540554 022677 0 ustar slusarz slusarz
* @category Horde
* @copyright 2013 Horde LLC
* @license http://www.horde.org/licenses/bsd New BSD License
* @package Mail
*/
class Horde_Mail_Transport_Smtphorde extends Horde_Mail_Transport
{
/**
* Send the message as 8bit?
*
* @var boolean
*/
public $send8bit = false;
/**
* SMTP object.
*
* @var Horde_Smtp
*/
protected $_smtp = null;
/**
* Constructor.
*
* @param array $params Additional parameters:
*
*
* debug: (string) If set, will output debug information to the stream
* provided. The value can be any PHP supported wrapper that
* can be opened via fopen().
* DEFAULT: No debug output
*
*
* host: (string) The SMTP server.
* DEFAULT: localhost
*
*
* password: (string) The SMTP password.
* DEFAULT: NONE
*
*
* port: (string) The SMTP port.
* DEFAULT: 587
*
*
* secure: (string) Use SSL or TLS to connect.
* DEFAULT: No encryption
*