Example #1
0
 /**
  * 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;
 }
Example #2
0
 /**
  *
  * @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;
     }
 }
Example #3
0
 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));
 }
Example #4
0
 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));
 }
Example #5
0
 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'));
 }
Example #6
0
 /**
  */
 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;
 }
Example #7
0
File: List.php Project: horde/horde
 /**
  * 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;
 }
Example #8
0
 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;
 }
Example #9
0
 /**
  * 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));
     }
 }
Example #10
0
 /**
  */
 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 : '') . ';';
 }
Example #11
0
 /**
  * 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;
 }
Example #12
0
 /**
  * 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);
 }
Example #13
0
 /**
  * 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;
 }
Example #14
0
 /**
  * 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);
     }
 }
Example #15
0
 /**
  * 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);
 }
Example #16
0
 /**
  */
 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 : '') . ';';
 }
Example #17
0
 /**
  * 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);
     }
 }
Example #18
0
File: Api.php Project: Gomez/horde
 /**
  * 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;
 }
Example #19
0
 * 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();
Example #20
0
File: Mail.php Project: horde/horde
 /**
  * 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);
     }
 }
Example #21
0
 /**
  * @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);
 }
Example #22
0
 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;
 }
Example #23
0
 /**
  * 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());
     }
 }
Example #24
0
 /**
  * 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);
     }
 }
Example #25
0
 /**
  */
 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;
 }
Example #26
0
 /**
  * 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);
     }
 }
Example #27
0
 /**
  * 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;
 }
Example #28
0
 /**
  */
 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;
 }
Example #29
0
 /**
  * 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);
 }
Example #30
0
 /**
  * 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;
 }