/** * Is user input required to send the MDN? * Explicit confirmation is needed in some cases to prevent mail loops * and the use of MDNs for mail bombing. * * @return boolean Is explicit user input required to send the MDN? */ public function userConfirmationNeeded() { $return_path = $this->_headers->getValue('Return-Path'); /* RFC 3798 [2.1]: Explicit confirmation is needed if there is no * Return-Path in the header. Also, "if the message contains more * than one Return-Path header, the implementation may [] treat the * situation as a failure of the comparison." */ if (empty($return_path) || is_array($return_path)) { return true; } /* RFC 3798 [2.1]: Explicit confirmation is needed if there is more * than one distinct address in the Disposition-Notification-To * header. */ $rfc822 = new Horde_Mail_Rfc822(); $addr_ob = $rfc822->parseAddressList($this->getMdnReturnAddr()); switch (count($addr_ob)) { case 0: return false; case 1: // No-op break; default: return true; } /* RFC 3798 [2.1] states that "MDNs SHOULD NOT be sent automatically * if the address in the Disposition-Notification-To header differs * from the address in the Return-Path header." This comparison is * case-sensitive for the mailbox part and case-insensitive for the * host part. */ $ret_ob = new Horde_Mail_Rfc822_Address($return_path); return $ret_ob->valid && $addr_ob->bare_address == $ret_ob->bare_address; }
/** * * @throws Horde_Mime_Exception */ protected function _setValue($value) { /* @todo Implement with traits */ $rfc822 = new Horde_Mail_Rfc822(); try { $addr_list = $rfc822->parseAddressList($value); } catch (Horde_Mail_Exception $e) { throw new Horde_Mime_Exception($e); } foreach ($addr_list as $ob) { if ($ob instanceof Horde_Mail_Rfc822_Group) { $ob->groupname = $this->_sanityCheck($ob->groupname); } else { $ob->personal = $this->_sanityCheck($ob->personal); } } switch (Horde_String::lower($this->name)) { case 'bcc': case 'cc': case 'from': case 'to': /* Catch malformed undisclosed-recipients entries. */ if (count($addr_list) == 1 && preg_match("/^\\s*undisclosed-recipients:?\\s*\$/i", $addr_list[0]->bare_address)) { $addr_list = new Horde_Mail_Rfc822_List('undisclosed-recipients:;'); } break; } if ($this->append_addr && $this->_values) { $this->_values->add($addr_list); } else { $this->_values = $addr_list; } }
public function getMdnReturnAddrProvider() { $email = 'foo1@example.com, Test <*****@*****.**>'; $rfc822 = new Horde_Mail_Rfc822(); $mail_ob = $rfc822->parseAddressList($email); return array(array(null), array('*****@*****.**'), array($email), array($mail_ob)); }
public function testBug4834() { // Bug #4834: Wrong encoding of email lists with groups. $addr = '"John Doe" <*****@*****.**>, Group: peter@example.com, jane@example.com;'; $parser = new Horde_Mail_Rfc822(); $result = $parser->parseAddressList($addr); $this->assertEquals('John Doe <*****@*****.**>, Group: peter@example.com, jane@example.com;', strval($result)); }
public function testAddHeaderWithGroup() { $email = 'Test: foo@example.com, bar@example.com;'; $rfc822 = new Horde_Mail_Rfc822(); $ob = $rfc822->parseAddressList($email); $hdrs = new Horde_Mime_Headers(); $hdrs->addHeader('To', $ob); $this->assertEquals($email, $hdrs->getValue('to')); }
/** */ protected function _setValue($value) { /* @todo Implement with traits */ $rfc822 = new Horde_Mail_Rfc822(); $addr_list = $rfc822->parseAddressList($value); foreach ($addr_list as $ob) { if ($ob instanceof Horde_Mail_Rfc822_Group) { $ob->groupname = $this->_sanityCheck($ob->groupname); } else { $ob->personal = $this->_sanityCheck($ob->personal); } } $this->_values[] = $addr_list; }
/** * Parses a comma separated list of names and e-mail addresses into a list * of attendees. * * @param string $newAttendees A comma separated * attendee list. * @param Horde_Notification_Handler $notification A notification handler. * * @return Kronolith_Attendee_List The parsed attendee list. */ public static function parse($newAttendees, Horde_Notification_Handler $notification) { $attendees = new self(); if (empty($newAttendees)) { return $attendees; } /* Parse the address without validation to see what we can get out of * it. We allow email addresses (john@example.com), email address with * user information (John Doe <*****@*****.**>), and plain names * (John Doe). */ $parser = new Horde_Mail_Rfc822(); $result = $parser->parseAddressList($newAttendees); $result->setIteratorFilter(Horde_Mail_Rfc822_List::HIDE_GROUPS); foreach ($result as $newAttendee) { if (!$newAttendee->valid) { // If we can't even get a mailbox out of the address, then it // is likely unuseable. Reject it entirely. $notification->push(sprintf(_("Unable to recognize \"%s\" as an email address."), $newAttendee), 'horde.error'); continue; } // If there is only a mailbox part, then it is just a local name. if (is_null($newAttendee->host)) { $email = null; $name = $newAttendee->bare_address; } else { // Build a full email address again and validate it. try { $parser->parseAddressList($newAttendee->writeAddress(true)); } catch (Horde_Mail_Exception $e) { $notification->push($e, 'horde.error'); continue; } $email = $newAttendee->bare_address; $name = $newAttendee->label != $newAttendee->bare_address ? $newAttendee->label : ''; } $attendees->add(new Kronolith_Attendee(array('email' => $email, 'role' => Kronolith::PART_REQUIRED, 'response' => Kronolith::RESPONSE_NONE, 'name' => $name))); } return $attendees; }
public function isValid($var, $vars, $value, &$message) { if ($var->required && empty($value['original'])) { $message = Horde_Model_Translation::t("This field is required."); return false; } if ($value['original'] != $value['confirm']) { $message = Horde_Model_Translation::t("Email addresses must match."); return false; } $rfc822 = new Horde_Mail_Rfc822(); $addr_ob = $rfc822->parseAddressList($value['original']); switch (count($addr_ob)) { case 0: $message = Horde_Model_Translation::t("You did not enter a valid email address."); return false; case 1: break; default: $message = Horde_Model_Translation::t("Only one email address allowed."); return false; } return true; }
/** * Retrieves the free/busy information for a given email address, if any * information is available. * * @param string $email The email address to look for. * @param boolean $json Whether to return the free/busy data as a simple * object suitable to be transferred as json. * * @return Horde_Icalendar_Vfreebusy|object Free/busy component. * @throws Kronolith_Exception */ public static function get($email, $json = false) { $default_domain = empty($GLOBALS['conf']['storage']['default_domain']) ? null : $GLOBALS['conf']['storage']['default_domain']; $rfc822 = new Horde_Mail_Rfc822(); try { $res = $rfc822->parseAddressList($email, array('default_domain' => $default_domain)); } catch (Horde_Mail_Exception $e) { throw new Kronolith_Exception($e); } if (!($tmp = $res[0])) { throw new Kronolith_Exception(_("No valid email address found")); } $email = $tmp->bare_address; /* Check if we can retrieve a VFB from the Free/Busy URL, if one is * set. */ $url = self::getUrl($email); if ($url) { $url = trim($url); $http = $GLOBALS['injector']->getInstance('Horde_Core_Factory_HttpClient')->create(array('request.verifyPeer' => false)); try { $response = $http->get($url); } catch (Horde_Http_Exception $e) { throw new Kronolith_Exception(sprintf(_("The free/busy url for %s cannot be retrieved."), $email)); } if ($response->code == 200 && ($data = $response->getBody())) { // Detect the charset of the iCalendar data. $contentType = $response->getHeader('Content-Type'); if ($contentType && strpos($contentType, ';') !== false) { list(, $charset, ) = explode(';', $contentType); $data = Horde_String::convertCharset($data, trim(str_replace('charset=', '', $charset)), 'UTF-8'); } $vCal = new Horde_Icalendar(); $vCal->parsevCalendar($data, 'VCALENDAR'); $components = $vCal->getComponents(); $vCal = new Horde_Icalendar(); $vFb = Horde_Icalendar::newComponent('vfreebusy', $vCal); $vFb->setAttribute('ORGANIZER', $email); $found = false; foreach ($components as $component) { if ($component instanceof Horde_Icalendar_Vfreebusy) { $found = true; $vFb->merge($component); } } if ($found) { // @todo: actually store the results in the storage, so // that they can be retrieved later. We should store the // plain iCalendar data though, to avoid versioning // problems with serialize iCalendar objects. return $json ? self::toJson($vFb) : $vFb; } } } /* Check storage driver. */ $storage = $GLOBALS['injector']->getInstance('Kronolith_Factory_Storage')->create(); try { $fb = $storage->search($email); return $json ? self::toJson($fb) : $fb; } catch (Horde_Exception_NotFound $e) { if ($url) { throw new Kronolith_Exception(sprintf(_("No free/busy information found at the free/busy url of %s."), $email)); } throw new Kronolith_Exception(sprintf(_("No free/busy url found for %s."), $email)); } }
/** */ 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 : '') . ';'; }
/** * Return fb information for the requested attendee or resource. * * Uses the following request parameters: * - user: The attendee's user name. * - email: The attendee's email address. * - resource: The resource id. */ public function getFreeBusy() { global $notification; $result = new stdClass(); if ($this->vars->user) { try { $result->fb = Kronolith_FreeBusy::getForUser($this->vars->user, array('json' => true, 'start' => $this->vars->start, 'end' => $this->vars->end)); } catch (Exception $e) { $notification->push($e->getMessage(), 'horde.warning'); } } elseif ($this->vars->email) { $rfc822 = new Horde_Mail_Rfc822(); $res = $rfc822->parseAddressList($this->vars->email); if ($res[0] && $res[0]->host) { try { $result->fb = Kronolith_FreeBusy::get($this->vars->email, true); } catch (Exception $e) { $notification->push($e->getMessage(), 'horde.warning'); } } } elseif ($this->vars->resource) { try { $resource = Kronolith::getDriver('Resource')->getResource($this->vars->resource); try { $result->fb = $resource->getFreeBusy($this->vars->start, $this->vars->end, true, true); } catch (Horde_Exception $e) { // Resource groups can't provide FB information. $result->fb = null; } } catch (Exception $e) { $notification->push($e->getMessage(), 'horde.warning'); } } return $result; }
/** * 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); }
/** * 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; }
/** * Sends this message. * * @param string $email The address list to send to. * @param Horde_Mime_Headers $headers The Horde_Mime_Headers object * holding this message's headers. * @param Horde_Mail_Transport $mailer A Horde_Mail_Transport object. * @param array $opts Additional options: * - encode: (integer) The encoding to use. A mask of self::ENCODE_* * values. * DEFAULT: Auto-determined based on transport driver. * * @throws Horde_Mime_Exception * @throws InvalidArgumentException */ public function send($email, $headers, Horde_Mail_Transport $mailer, array $opts = array()) { $old_basepart = $this->_basepart; $this->_basepart = true; /* Does the SMTP backend support 8BITMIME (RFC 1652) or * BINARYMIME (RFC 3030) extensions? Requires Net_SMTP version * 1.3+. */ $encode = self::ENCODE_7BIT; if (isset($opts['encode'])) { /* Always allow 7bit encoding. */ $encode |= $opts['encode']; } else { if ($mailer instanceof Horde_Mail_Transport_Smtp) { try { $smtp_ext = $mailer->getSMTPObject()->getServiceExtensions(); if (isset($smtp_ext['8BITMIME'])) { $encode |= self::ENCODE_8BIT; } if (isset($smtp_ext['BINARYMIME'])) { $encode |= self::ENCODE_BINARY; } } catch (Horde_Mail_Exception $e) { } } } $msg = $this->toString(array('canonical' => true, 'encode' => $encode, 'headers' => false, 'stream' => true)); /* Make sure the message has a trailing newline. */ fseek($msg, -1, SEEK_END); switch (fgetc($msg)) { case "\r": if (fgetc($msg) != "\n") { fputs($msg, "\n"); } break; default: fputs($msg, "\r\n"); break; } rewind($msg); /* Add MIME Headers if they don't already exist. */ if (!$headers->getValue('MIME-Version')) { $headers = $this->addMimeHeaders(array('encode' => $encode, 'headers' => $headers)); } if (!empty($this->_temp['toString'])) { $headers->replaceHeader('Content-Transfer-Encoding', $this->_temp['toString']); switch ($this->_temp['toString']) { case 'binary': $mailer->addServiceExtensionParameter('BODY', 'BINARYMIME'); break; case '8bit': $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); break; } } $this->_basepart = $old_basepart; $rfc822 = new Horde_Mail_Rfc822(); try { $mailer->send($rfc822->parseAddressList($email)->writeAddress(array('encode' => $this->getHeaderCharset(), 'idn' => true)), $headers->toArray(array('canonical' => true, 'charset' => $this->getHeaderCharset())), $msg); } catch (Horde_Mail_Exception $e) { throw new Horde_Mime_Exception($e); } }
/** * Verifies and sanitizes all identity properties. * * @param integer $identity The identity to verify. * * @throws Horde_Prefs_Exception */ public function verify($identity = null) { if (is_null($identity)) { $identity = $this->_default; } if (!$this->getValue('id', $identity)) { $this->setValue('id', Horde_Prefs_Translation::t("Unnamed"), $identity); } // To verify e-mail, first parse input, than re-parse in verify mode. $ob = new Horde_Mail_Rfc822_Address($this->getValue($this->_prefnames['from_addr'], $identity)); try { $rfc822 = new Horde_Mail_Rfc822(); $rfc822->parseAddressList($ob, array('validate' => true)); } catch (Horde_Mail_Exception $e) { throw new Horde_Prefs_Exception(sprintf(Horde_Prefs_Translation::t("\"%s\" is not a valid email address."), strval($ob))); } $this->setValue('from_addr', strval($ob), $identity); }
/** */ protected function _writeAddress($opts) { $addr = $this->addresses->writeAddress($opts); $groupname = $this->groupname; if (!empty($opts['encode'])) { $groupname = Horde_Mime::encode($groupname, $opts['encode']); } if (empty($opts['noquote'])) { $rfc822 = new Horde_Mail_Rfc822(); $groupname = $rfc822->encode($groupname, 'personal'); } if (!empty($opts['comment']) && !empty($this->comment)) { $rfc822 = new Horde_Mail_Rfc822(); foreach ($this->comment as $val) { $personal .= ' (' . $rfc822->encode($val, 'comment') . ')'; } } return ltrim($groupname) . ':' . (strlen($addr) ? ' ' . $addr : '') . ';'; }
/** * Sends this message. * * @param string $email The address list to send to. * @param Horde_Mime_Headers $headers The Horde_Mime_Headers object * holding this message's headers. * @param Horde_Mail_Transport $mailer A Horde_Mail_Transport object. * @param array $opts Additional options: * <pre> * - broken_rfc2231: (boolean) Attempt to work around non-RFC * 2231-compliant MUAs by generating both a RFC * 2047-like parameter name and also the correct RFC * 2231 parameter (@since 2.5.0). * DEFAULT: false * - encode: (integer) The encoding to use. A mask of self::ENCODE_* * values. * DEFAULT: Auto-determined based on transport driver. * </pre> * * @throws Horde_Mime_Exception * @throws InvalidArgumentException */ public function send($email, $headers, Horde_Mail_Transport $mailer, array $opts = array()) { $old_status = $this->_status; $this->isBasePart(true); /* Does the SMTP backend support 8BITMIME (RFC 1652)? */ $canonical = true; $encode = self::ENCODE_7BIT; if (isset($opts['encode'])) { /* Always allow 7bit encoding. */ $encode |= $opts['encode']; } elseif ($mailer instanceof Horde_Mail_Transport_Smtp) { try { $smtp_ext = $mailer->getSMTPObject()->getServiceExtensions(); if (isset($smtp_ext['8BITMIME'])) { $encode |= self::ENCODE_8BIT; } } catch (Horde_Mail_Exception $e) { } $canonical = false; } elseif ($mailer instanceof Horde_Mail_Transport_Smtphorde) { try { if ($mailer->getSMTPObject()->data_8bit) { $encode |= self::ENCODE_8BIT; } } catch (Horde_Mail_Exception $e) { } $canonical = false; } $msg = $this->toString(array('canonical' => $canonical, 'encode' => $encode, 'headers' => false, 'stream' => true)); /* Add MIME Headers if they don't already exist. */ if (!isset($headers['MIME-Version'])) { $headers = $this->addMimeHeaders(array('encode' => $encode, 'headers' => $headers)); } if (!empty($this->_temp['toString'])) { $headers->addHeader('Content-Transfer-Encoding', $this->_temp['toString']); switch ($this->_temp['toString']) { case '8bit': if ($mailer instanceof Horde_Mail_Transport_Smtp) { $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); } break; } } $this->_status = $old_status; $rfc822 = new Horde_Mail_Rfc822(); try { $mailer->send($rfc822->parseAddressList($email)->writeAddress(array('encode' => $this->getHeaderCharset() ?: true, 'idn' => true)), $headers->toArray(array('broken_rfc2231' => !empty($opts['broken_rfc2231']), 'canonical' => $canonical, 'charset' => $this->getHeaderCharset())), $msg); } catch (InvalidArgumentException $e) { // Try to rebuild the part in case it was due to // an invalid line length in a rfc822/message attachment. if ($this->_failed) { throw $e; } $this->_failed = true; $this->_sanityCheckRfc822Attachments(); try { $this->send($email, $headers, $mailer, $opts); } catch (Horde_Mail_Exception $e) { throw new Horde_Mime_Exception($e); } } catch (Horde_Mail_Exception $e) { throw new Horde_Mime_Exception($e); } }
/** * Returns a contact search result. * * @param mixed $names The search filter values. * @param array $opts Optional parameters: * - customStrict: (array) An array of fields that must match exactly. * DEFAULT: None * - fields: (array) The fields to search on. * DEFAULT: Search all configured search fields. * - forceSource: (boolean) Whether to use the specified sources, even * if they have been disabled in the preferences? * DEFAULT: false * - matchBegin: (boolean) Match word boundaries only? * DEFAULT: false * - returnFields: Only return these fields. * DEFAULT: Return all fields. * - rfc822Return: Return a Horde_Mail_Rfc822_List object. * DEFAULT: Returns an array of search results. * - sources: (array) The sources to search in. * DEFAULT: Search the user's default address book * - count_only: (boolean) If true, only return the count of matching * results. * DEFAULT: false (Return the full data set). * * @return mixed Either a hash containing the search results or a * Rfc822 List object (if 'rfc822Return' is true). * @throws Turba_Exception */ public function search($names = null, array $opts = array()) { global $attributes, $cfgSources, $injector; $opts = array_merge(array('fields' => array(), 'forceSource' => false, 'matchBegin' => false, 'returnFields' => array(), 'rfc822Return' => false, 'sources' => array(), 'customStrict' => array(), 'count_only' => false), $opts); $results = !empty($opts['count_only']) ? 0 : (empty($opts['rfc822Return']) ? array() : new Horde_Mail_Rfc822_List()); if (!isset($cfgSources) || !is_array($cfgSources) || !count($cfgSources) || is_null($names)) { return $results; } if (!is_array($names)) { $names = array($names); } if (!$opts['forceSource']) { // Make sure the selected source is activated in Turba. $addressbooks = array_keys(Turba::getAddressBooks()); foreach (array_keys($opts['sources']) as $id) { if (!in_array($opts['sources'][$id], $addressbooks)) { unset($opts['sources'][$id]); } } } // ...and ensure the default source is used as a default. if (!count($opts['sources'])) { $opts['sources'] = array(Turba::getDefaultAddressbook()); } $driver = $injector->getInstance('Turba_Factory_Driver'); foreach ($opts['sources'] as $source) { // Skip invalid sources -or- // skip sources that aren't browseable if the search is empty. if (!isset($cfgSources[$source]) || empty($cfgSources[$source]['browse']) && (!count($names) || count($names) == 1 && empty($names[0]))) { continue; } if (empty($opts['fields'][$source])) { $opts['fields'][$source] = $GLOBALS['cfgSources'][$source]['search']; } $sdriver = $driver->create($source); foreach ($names as $name) { $trimname = trim($name); $out = $criteria = array(); unset($tname); if (strlen($trimname)) { if (isset($opts['fields'][$source])) { foreach ($opts['fields'][$source] as $field) { $criteria[$field] = $trimname; } } } try { $search = $sdriver->search($criteria, Turba::getPreferredSortOrder(), 'OR', $opts['returnFields'], $opts['customStrict'], $opts['matchBegin'], $opts['count_only']); } catch (Exception $e) { continue; } if ($opts['count_only']) { $results += $search; continue; } elseif (!$search instanceof Turba_List) { continue; } $rfc822 = new Horde_Mail_Rfc822(); while ($ob = $search->next()) { $emails = $seen = array(); if ($ob->isGroup()) { /* Is a distribution list. */ $members = $ob->listMembers(); if (!$members instanceof Turba_List || !count($members)) { continue; } $listatt = $ob->getAttributes(); $listName = $ob->getValue('name'); while ($ob = $members->next()) { foreach (array_keys($ob->getAttributes()) as $key) { $value = $ob->getValue($key); if (empty($value)) { continue; } $seen_key = trim(Horde_String::lower($ob->getValue('name'))) . trim(Horde_String::lower(is_array($value) ? $value['load']['file'] : $value)); if (isset($attributes[$key]) && $attributes[$key]['type'] == 'email' && empty($seen[$seen_key])) { $emails[] = $value; $seen[$seen_key] = true; } } } if (empty($opts['rfc822Return'])) { $out[] = array('email' => implode(', ', $emails), 'id' => $listatt['__key'], 'name' => $listName, 'source' => $source); } else { $results->add(new Horde_Mail_Rfc822_Group($listName, $emails)); } } else { /* Not a group. */ $att = array('__key' => $ob->getValue('__key')); foreach (array_keys($ob->driver->getCriteria()) as $key) { $att[$key] = $ob->getValue($key); } $email = new Horde_Mail_Rfc822_List(); $display_name = $ob->hasValue('name') || !isset($ob->driver->alternativeName) ? Turba::formatName($ob) : $ob->getValue($ob->driver->alternativeName); unset($tdisplay_name); foreach (array_keys($att) as $key) { if ($ob->getValue($key) && isset($attributes[$key]) && $attributes[$key]['type'] == 'email') { $e_val = $ob->getValue($key); if (strlen($trimname)) { /* Ticket #12480: Don't return email if it * doesn't contain the search string, since * an entry can contain multiple e-mail * fields. Return all e-mails if it * occurs in the name. */ if (!isset($tname)) { $tname = Horde_String_Transliterate::toAscii($name); } if (!isset($tdisplay_name)) { $tdisplay_name = Horde_String_Transliterate::toAscii($display_name); } $add = Horde_String::ipos(Horde_String_Transliterate::toAscii($e_val), $tname) !== false || Horde_String::ipos($tdisplay_name, $tname) !== false; } else { $add = true; } if ($add) { // Multiple addresses support $email->add($rfc822->parseAddressList($e_val, array('limit' => isset($attributes[$key]['params']) && is_array($attributes[$key]['params']) && !empty($attributes[$key]['params']['allow_multi']) ? 0 : 1))); } } } if (count($email)) { foreach ($email as $val) { $seen_key = trim(Horde_String::lower($display_name)) . '/' . Horde_String::lower($val->bare_address); if (empty($seen[$seen_key])) { $seen[$seen_key] = true; if (empty($opts['rfc822Return'])) { $emails[] = $val->bare_address; } else { $val->personal = $display_name; $results->add($val); } } } } elseif (empty($opts['rfc822Return'])) { $emails[] = null; } if (empty($opts['rfc822Return'])) { foreach ($emails as $val) { $out[] = array_merge($att, array('__type' => 'Object', 'email' => $val, 'id' => $att['__key'], 'name' => $display_name, 'source' => $source)); } } } } if (!empty($out)) { $results[$name] = $out; } } } return $results; }
* License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('mail'); $account_id = isset($_GET['account_id']) ? $_GET['account_id'] : null; $subject = isset($_GET['subject']) ? $_GET['subject'] : null; $body = isset($_GET['body']) ? $_GET['body'] : null; $to = isset($_GET['to']) ? $_GET['to'] : null; $account = OCA\Mail\App::getAccount(OCP\User::getUser(), $account_id); if (!$account) { // TODO: i10n OCP\JSON::error(array('data' => array('message' => 'Unknown account'))); exit; } // get sender data $from = $account->getName(); $from_address = $account->getEMailAddress(); // parse receiver string $parser = new Horde_Mail_Rfc822(); $tos = $parser->parseAddressList($to, array('validate' => true)); foreach ($tos as $t) { // sent mail OCP\Util::sendMail($t->bare_address, $t->label, $subject, $body, $from_address, $from); } // // TODO: save message to 'Sent' folder // TODO: remove from drafts folder as well // OCP\JSON::success();
/** * Parse a MIME message and create a new ticket. * * @param string $text This is the full text of the MIME message. * @param array $info An array of information for the new ticket. * This should include: * - 'queue' => queue id * - 'type' => type id * - 'state' => state id * - 'priority' => priority id * - 'ticket' => ticket id (prevents creation * of new tickets) * @param string $auth_user This will be the Horde user that creates the * ticket. If null, we will try to deduce from * the message's From: header. We do NOT default * to $GLOBALS['registry']->getAuth(). * * @return Whups_Ticket Ticket. */ public static function processMail($text, array $info, $auth_user = null) { global $conf; $message = Horde_Mime_Part::parseMessage($text); if (preg_match("/^(.*?)\r?\n\r?\n/s", $text, $matches)) { $hdrText = $matches[1]; } else { $hdrText = $text; } $headers = Horde_Mime_Headers::parseHeaders($hdrText); // If this message was generated by Whups, don't process it. if ($headers->getValue('X-Whups-Generated')) { return true; } // Try to avoid bounces, auto-replies, and mailing list responses. $from = $headers->getValue('from'); if (strpos($headers->getValue('Content-Type'), 'multipart/report') !== false || stripos($from, 'mailer-daemon@') !== false || stripos($from, 'postmaster@') !== false || !is_null($headers->getValue('X-Failed-Recipients')) || !is_null($headers->getValue('X-Autoreply-Domain')) || $headers->getValue('Auto-Submitted') == 'auto-replied' || $headers->getValue('Precedence') == 'auto_reply' || $headers->getValue('X-Precedence') == 'auto_reply' || $headers->getValue('X-Auto-Response-Suppress') == 'All' || $headers->getValue('X-List-Administrivia') == 'Yes') { return true; } if ($reply_to = $headers->getValue('reply-to')) { $from = $reply_to; } $fromAddress = new Horde_Mail_Rfc822_Address($from); $listeners = array($fromAddress->bare_address); if ($cc = $headers->getValue('cc')) { $rfc822 = new Horde_Mail_Rfc822(); foreach ($rfc822->parseAddressList($cc) as $address) { if ($address->valid) { $listeners[] = $address->bare_address; } } } // Use the message subject as the ticket summary. $info['summary'] = trim($headers->getValue('subject')); if (empty($info['summary'])) { $info['summary'] = _("[No Subject]"); } // Format the message into a comment. $comment = _("Received message:") . "\n\n"; if (!empty($GLOBALS['conf']['mail']['include_headers'])) { foreach ($headers->toArray(array('nowrap' => true)) as $name => $vals) { if (!in_array(strtolower($name), array('subject', 'from', 'to', 'cc', 'date'))) { if (is_array($vals)) { foreach ($vals as $val) { $comment .= $name . ': ' . $val . "\n"; } } else { $comment .= $name . ': ' . $vals . "\n"; } } } $comment .= "\n"; } // Look for the body part. $body_id = $message->findBody(); if ($body_id) { $part = $message->getPart($body_id); $content = Horde_String::convertCharset($part->getContents(), $part->getCharset(), 'UTF-8'); switch ($part->getType()) { case 'text/plain': $comment .= $content; break; case 'text/html': $comment .= Horde_Text_Filter::filter($content, array('Html2text'), array(array('width' => 0))); break; default: $comment .= _("[ Could not render body of message. ]"); break; } } else { $comment .= _("[ Could not render body of message. ]"); } $info['comment'] = $comment . "\n"; // Try to determine the Horde user for creating the ticket. if (empty($auth_user)) { $auth_user = self::_findAuthUser($fromAddress->bare_address); } $author = $auth_user; if (empty($auth_user) && !empty($info['default_auth'])) { $auth_user = $info['default_auth']; if (!empty($from)) { $info['user_email'] = $from; } } if (empty($auth_user) && !empty($conf['mail']['username'])) { $auth_user = $conf['mail']['username']; if (!empty($from)) { $info['user_email'] = $from; } } // Authenticate as the correct Horde user. if (!empty($auth_user) && $auth_user != $GLOBALS['registry']->getAuth()) { $GLOBALS['registry']->setAuth($auth_user, array()); } // Extract attachments. foreach ($message->partIterator() as $part) { if (!$part->isAttachment()) { continue; } $tmp_name = Horde::getTempFile('whups'); $fp = @fopen($tmp_name, 'wb'); if (!$fp) { throw new Whups_Exception(sprintf('Cannot open file %s for writing.', $tmp_name)); } fwrite($fp, $part->getContents()); fclose($fp); $part_name = $part->getName(true); if (!$part_name) { $ptype = $part->getPrimaryType(); switch ($ptype) { case 'multipart': case 'application': $part_name = sprintf(_("%s part"), ucfirst($part->getSubType())); break; default: $part_name = sprintf(_("%s part"), ucfirst($ptype)); break; } if ($ext = Horde_Mime_Magic::mimeToExt($part->getType())) { $part_name .= '.' . $ext; } } $attachments[] = array('name' => $part_name, 'tmp_name' => $tmp_name); } // See if we can match this message to an existing ticket. if ($ticket = self::_findTicket($info)) { $ticket->change('comment', $info['comment']); $ticket->change('comment-email', $from); $ticket->change('message', $text); if ($attachments) { $ticket->change('attachments', $attachments); } foreach ($listeners as $listener) { $GLOBALS['whups_driver']->addUniqueListener($ticket, $listener); } $ticket->commit($author); } elseif (!empty($info['ticket'])) { // Didn't match an existing ticket though a ticket number had been // specified. throw new Whups_Exception(sprintf(_("Could not find ticket \"%s\"."), $info['ticket'])); } else { if (!empty($info['guess-queue'])) { // Try to guess the queue name for the new ticket from the // message subject. $queues = $GLOBALS['whups_driver']->getQueues(); foreach ($queues as $queueId => $queueName) { if (preg_match('/\\b' . preg_quote($queueName, '/') . '\\b/i', $info['summary'])) { $info['queue'] = $queueId; break; } } } $info['message'] = $text; $info['attachments'] = $attachments; $info['listeners'] = $listeners; // Create a new ticket. $ticket = Whups_Ticket::newTicket($info, $author); } }
/** * @dataProvider addHeaderWithGroupProvider */ public function testAddHeaderWithGroup($header, $email) { $rfc822 = new Horde_Mail_Rfc822(); $ob = $rfc822->parseAddressList($email); $hdrs = new Horde_Mime_Headers(); $hdrs->addHeader($header, $ob); /* @deprecated */ $this->assertEquals($email, $hdrs->getValue($header)); $this->assertEquals($email, $hdrs[$header]->value); }
public static function getAuthorEmail($name) { try { $users = $GLOBALS['VC']->getUsers($GLOBALS['chora_conf']['cvsusers']); if (isset($users[$name])) { return $users[$name]['mail']; } } catch (Horde_Vcs_Exception $e) { } try { $parser = new Horde_Mail_Rfc822(); $res = $parser->parseAddressList($name); if ($tmp = $res[0]) { return $tmp->bare_address; } } catch (Horde_Mail_Exception $e) { try { if (preg_match('|<(\\S+)>|', $name, $matches)) { return self::getAuthorEmail($matches[1]); } } catch (Horde_Mail_Exception $e) { } } return $name; }
/** * Returns formatted string representing a task organizer. * * @param string $organizer The organinzer, as an email or mailto: format. * @param boolean $link Whether to link to an email compose screen. * * @return string The formatted organizer name. */ public static function formatOrganizer($organizer, $link = false) { if (empty($organizer)) { return; } $rfc = new Horde_Mail_Rfc822(); $list = $rfc->parseAddressList(str_ireplace('mailto:', '', $organizer), array('limit' => 1)); if (empty($list)) { return; } $email = $list[0]; if ($link && $GLOBALS['registry']->hasMethod('mail/compose')) { return Horde::link($GLOBALS['registry']->call('mail/compose', array(array('to' => $email->bare_address)))) . htmlspecialchars($email->writeAddress()) . '</a>'; } else { return htmlspecialchars($email->writeAddress()); } }
/** * Generates the Sieve script to do the filtering specified in the rules. */ protected function _generate() { $this->_addItem(Ingo::RULE_ALL, new Ingo_Script_Sieve_Comment("Sieve Filter\n" . _("Generated by Ingo") . ' (http://www.horde.org/apps/ingo/) (' . trim(strftime($this->_params['date_format'] . ', ' . $this->_params['time_format'])) . ")")); $filters = $this->_params['storage']->retrieve(Ingo_Storage::ACTION_FILTERS); foreach ($filters->getFilterList($this->_params['skip']) as $filter) { /* Check to make sure this is a valid rule and that the rule is not disabled. */ if (!$this->_validRule($filter['action']) || !empty($filter['disable'])) { continue; } $action = array(); switch ($filter['action']) { case Ingo_Storage::ACTION_KEEP: if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } $action[] = new Ingo_Script_Sieve_Action_Keep(); if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Removeflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } break; case Ingo_Storage::ACTION_DISCARD: $action[] = new Ingo_Script_Sieve_Action_Discard(); break; case Ingo_Storage::ACTION_MOVE: if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } $action[] = new Ingo_Script_Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $filter['action-value']))); if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Removeflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } break; case Ingo_Storage::ACTION_REJECT: $action[] = new Ingo_Script_Sieve_Action_Reject(array('reason' => $filter['action-value'])); break; case Ingo_Storage::ACTION_REDIRECT: $parser = new Horde_Mail_Rfc822(); foreach ($parser->parseAddressList($filter['action-value']) as $address) { $action[] = new Ingo_Script_Sieve_Action_Redirect(array('address' => $address)); } break; case Ingo_Storage::ACTION_REDIRECTKEEP: if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } $parser = new Horde_Mail_Rfc822(); foreach ($parser->parseAddressList($filter['action-value']) as $address) { $action[] = new Ingo_Script_Sieve_Action_Redirect(array('address' => $address)); } $action[] = new Ingo_Script_Sieve_Action_Keep(); if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Removeflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } break; case Ingo_Storage::ACTION_MOVEKEEP: if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } $action[] = new Ingo_Script_Sieve_Action_Keep(); $action[] = new Ingo_Script_Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $filter['action-value']))); if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Removeflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } break; case Ingo_Storage::ACTION_FLAGONLY: if (!empty($filter['flags'])) { $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'], 'imapflags' => !empty($this->_params['imapflags']))); } break; case Ingo_Storage::ACTION_NOTIFY: $action[] = new Ingo_Script_Sieve_Action_Notify(array('address' => $filter['action-value'], 'name' => $filter['name'], 'notify' => !empty($this->_params['notify']))); break; case Ingo_Storage::ACTION_WHITELIST: $this->_addWhitelistBlocks(); continue 2; case Ingo_Storage::ACTION_BLACKLIST: $this->_addBlacklistBlocks(); continue 2; case Ingo_Storage::ACTION_VACATION: $this->_addVacationBlocks(); continue 2; case Ingo_Storage::ACTION_FORWARD: $this->_addForwardBlocks(); continue 2; case Ingo_Storage::ACTION_SPAM: $this->_addSpamBlocks(); continue 2; } $this->_addItem(Ingo::RULE_FILTER, new Ingo_Script_Sieve_Comment($filter['name'])); if ($filter['stop']) { $action[] = new Ingo_Script_Sieve_Action_Stop(); } if ($filter['combine'] == Ingo_Storage::COMBINE_ANY) { $test = new Ingo_Script_Sieve_Test_Anyof(); } else { $test = new Ingo_Script_Sieve_Test_Allof(); } foreach ($filter['conditions'] as $condition) { $tmp = ''; switch ($condition['match']) { case 'equal': $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'eq', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'not equal': $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'ne', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'less than': if ($condition['field'] == 'Size') { /* Message Size Test. */ $tmp = new Ingo_Script_Sieve_Test_Size(array('comparison' => ':under', 'size' => $condition['value'])); } else { /* Relational Test. */ $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'lt', 'headers' => $condition['field'], 'value' => $condition['value'])); } $test->addTest($tmp); break; case 'less than or equal to': $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'le', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'greater than': if ($condition['field'] == 'Size') { /* Message Size Test. */ $tmp = new Ingo_Script_Sieve_Test_Size(array('comparison' => ':over', 'size' => $condition['value'])); } else { /* Relational Test. */ $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'gt', 'headers' => $condition['field'], 'value' => $condition['value'])); } $test->addTest($tmp); break; case 'greater than or equal to': $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'ge', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'exists': $tmp = new Ingo_Script_Sieve_Test_Exists(array('headers' => $condition['field'])); $test->addTest($tmp); break; case 'not exist': $tmp = new Ingo_Script_Sieve_Test_Exists(array('headers' => $condition['field'])); $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'contains': case 'not contain': case 'is': case 'not is': case 'begins with': case 'not begins with': case 'ends with': case 'not ends with': case 'regex': case 'not regex': case 'matches': case 'not matches': $comparator = isset($condition['case']) && $condition['case'] ? 'i;octet' : 'i;ascii-casemap'; $vals = array('headers' => preg_replace('/(.)(?<!\\\\)\\,(.)/', "\$1\n\$2", $condition['field']), 'comparator' => $comparator); $use_address_test = false; if ($condition['match'] != 'regex') { $condition['value'] = preg_replace('/(.)(?<!\\\\)\\,(.)/', "\$1\n\$2", $condition['value']); } /* Do 'smarter' searching for fields where we know we have * e-mail addresses. */ if (preg_match('/^(From|To|Cc|Bcc)/', $condition['field'])) { $vals['addresses'] = $condition['value']; $use_address_test = true; } else { $vals['strings'] = $condition['value']; } switch ($condition['match']) { case 'contains': $vals['match-type'] = ':contains'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; case 'not contain': $vals['match-type'] = ':contains'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'is': $vals['match-type'] = ':is'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; case 'not is': $vals['match-type'] = ':is'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'begins with': $vals['match-type'] = ':matches'; if ($use_address_test) { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['addresses']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = $v . '*'; } $vals['addresses'] = implode("\r\n", $add_arr); } else { $vals['addresses'] .= '*'; } $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['strings']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = $v . '*'; } $vals['strings'] = implode("\r\n", $add_arr); } else { $vals['strings'] .= '*'; } if ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } $test->addTest($tmp); break; case 'not begins with': $vals['match-type'] = ':matches'; if ($use_address_test) { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['addresses']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = $v . '*'; } $vals['addresses'] = implode("\r\n", $add_arr); } else { $vals['addresses'] .= '*'; } $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['strings']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = $v . '*'; } $vals['strings'] = implode("\r\n", $add_arr); } else { $vals['strings'] .= '*'; } if ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'ends with': $vals['match-type'] = ':matches'; if ($use_address_test) { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['addresses']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = '*' . $v; } $vals['addresses'] = implode("\r\n", $add_arr); } else { $vals['addresses'] = '*' . $vals['addresses']; } $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['strings']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = '*' . $v; } $vals['strings'] = implode("\r\n", $add_arr); } else { $vals['strings'] = '*' . $vals['strings']; } if ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } $test->addTest($tmp); break; case 'not ends with': $vals['match-type'] = ':matches'; if ($use_address_test) { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['addresses']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = '*' . $v; } $vals['addresses'] = implode("\r\n", $add_arr); } else { $vals['addresses'] = '*' . $vals['addresses']; } $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\\r\\n|\\n|\\r)', $vals['strings']); if (count($add_arr) > 1) { foreach ($add_arr as $k => $v) { $add_arr[$k] = '*' . $v; } $vals['strings'] = implode("\r\n", $add_arr); } else { $vals['strings'] = '*' . $vals['strings']; } if ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'regex': case 'not regex': $vals['match-type'] = ':regex'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } if ($condition['match'] == 'not regex') { $tmp = new Ingo_Script_Sieve_Test_Not($tmp); } $test->addTest($tmp); break; case 'matches': $vals['match-type'] = ':matches'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; case 'not matches': $vals['match-type'] = ':matches'; if ($use_address_test) { $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; } } } $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_addItem(Ingo::RULE_FILTER, $if); } /* Add blocks that have to go to the end. */ foreach ($this->_endBlocks as $block) { $this->_addItem(Ingo::RULE_FILTER, $block); } }
/** */ 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']); } if (empty($opts['noquote'])) { $personal = $rfc822->encode($personal, 'personal'); } } if (!empty($opts['comment']) && !empty($this->comment)) { foreach ($this->comment as $val) { $personal .= ' (' . $rfc822->encode($val, 'comment') . ')'; } } return strlen($personal) && $personal != $address ? ltrim($personal) . ' <' . $address . '>' : $address; }
/** * Sends this message. * * @param string $email The address list to send to. * @param Horde_Mime_Headers $headers The Horde_Mime_Headers object * holding this message's headers. * @param Horde_Mail_Transport $mailer A Horde_Mail_Transport object. * @param array $opts Additional options: * - encode: (integer) The encoding to use. A mask of self::ENCODE_* * values. * DEFAULT: Auto-determined based on transport driver. * * @throws Horde_Mime_Exception * @throws InvalidArgumentException */ public function send($email, $headers, Horde_Mail_Transport $mailer, array $opts = array()) { $old_basepart = $this->_basepart; $this->_basepart = true; /* Does the SMTP backend support 8BITMIME (RFC 1652)? */ $canonical = true; $encode = self::ENCODE_7BIT; if (isset($opts['encode'])) { /* Always allow 7bit encoding. */ $encode |= $opts['encode']; } elseif ($mailer instanceof Horde_Mail_Transport_Smtp) { try { $smtp_ext = $mailer->getSMTPObject()->getServiceExtensions(); if (isset($smtp_ext['8BITMIME'])) { $encode |= self::ENCODE_8BIT; } } catch (Horde_Mail_Exception $e) { } $canonical = false; } elseif ($mailer instanceof Horde_Mail_Transport_Smtphorde) { try { if ($mailer->getSMTPObject()->data_8bit) { $encode |= self::ENCODE_8BIT; } } catch (Horde_Mail_Exception $e) { } $canonical = false; } $msg = $this->toString(array('canonical' => $canonical, 'encode' => $encode, 'headers' => false, 'stream' => true)); /* Add MIME Headers if they don't already exist. */ if (!$headers->getValue('MIME-Version')) { $headers = $this->addMimeHeaders(array('encode' => $encode, 'headers' => $headers)); } if (!empty($this->_temp['toString'])) { $headers->replaceHeader('Content-Transfer-Encoding', $this->_temp['toString']); switch ($this->_temp['toString']) { case '8bit': if ($mailer instanceof Horde_Mail_Transport_Smtp) { $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); } elseif ($mailer instanceof Horde_Mail_Transport_Smtphorde) { $mailer->send8bit = true; } break; } } $this->_basepart = $old_basepart; $rfc822 = new Horde_Mail_Rfc822(); try { $mailer->send($rfc822->parseAddressList($email)->writeAddress(array('encode' => $this->getHeaderCharset(), 'idn' => true)), $headers->toArray(array('canonical' => $canonical, 'charset' => $this->getHeaderCharset())), $msg); } catch (Horde_Mail_Exception $e) { throw new Horde_Mime_Exception($e); } }
/** * Take a set of recipients and parse them, returning an array of bare * addresses (forward paths) that can be passed to sendmail or an SMTP * server with the 'RCPT TO:' command. * * @param mixed $recipients Either a comma-separated list of recipients * (RFC822 compliant), or an array of * recipients, each RFC822 valid. * * @return array Forward paths (bare addresses, IDN encoded). * @throws Horde_Mail_Exception */ public function parseRecipients($recipients) { // Parse recipients, leaving out all personal info. This is // for smtp recipients, etc. All relevant personal information // should already be in the headers. $rfc822 = new Horde_Mail_Rfc822(); return $rfc822->parseAddressList($recipients, array('validate' => $this->eai ? 'eai' : true))->bare_addresses_idn; }
/** */ 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; }
/** * Returns an address object for a header. * * @param string $field The header to return as an object. * * @return Horde_Mail_Rfc822_List The object for the requested field. * Returns null if field doesn't exist. */ public function getOb($field) { if (($value = $this->getValue($field)) === null) { return null; } $rfc822 = new Horde_Mail_Rfc822(); return $rfc822->parseAddressList($value); }
/** * Take a set of recipients and parse them, returning an array of bare * addresses (forward paths) that can be passed to sendmail or an SMTP * server with the 'RCPT TO:' command. * * @param mixed Either a comma-separated list of recipients (RFC822 * compliant), or an array of recipients, each RFC822 valid. * * @return array Forward paths (bare addresses). * @throws Horde_Mail_Exception */ public function parseRecipients($recipients) { // if we're passed an array, assume addresses are valid and // implode them before parsing. if (is_array($recipients)) { $recipients = implode(', ', $recipients); } // Parse recipients, leaving out all personal info. This is // for smtp recipients, etc. All relevant personal information // should already be in the headers. $rfc822 = new Horde_Mail_Rfc822(); $addresses = $rfc822->parseAddressList($recipients, array('validate' => true)); return $addresses->bare_addresses; }