setLanguage() public method

Set the language(s) of this part.
public setLanguage ( mixed $lang )
$lang mixed A language string, or an array of language strings.
Exemplo n.º 1
0
 /**
  * Recursively parse BODYSTRUCTURE data from a FETCH return (see
  * RFC 3501 [7.4.2]).
  *
  * @param Horde_Imap_Client_Tokenize $data  Data returned from the server.
  *
  * @return Horde_Mime_Part  Mime part object.
  */
 protected function _parseBodystructure(Horde_Imap_Client_Tokenize $data)
 {
     $ob = new Horde_Mime_Part();
     // If index 0 is an array, this is a multipart part.
     if (($entry = $data->next()) === true) {
         do {
             $ob->addPart($this->_parseBodystructure($data));
         } while (($entry = $data->next()) === true);
         // The subpart type.
         $ob->setType('multipart/' . $entry);
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         // This is parameter information.
         if (($tmp = $data->next()) === false) {
             return $ob;
         } elseif ($tmp === true) {
             foreach ($this->_parseStructureParams($data, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
     } else {
         $ob->setType($entry . '/' . $data->next());
         if ($data->next() === true) {
             foreach ($this->_parseStructureParams($data, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setContentId($tmp);
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setDescription(Horde_Mime::decode($tmp));
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setTransferEncoding($tmp);
         }
         $ob->setBytes($data->next());
         // If the type is 'message/rfc822' or 'text/*', several extra
         // fields are included
         switch ($ob->getPrimaryType()) {
             case 'message':
                 if ($ob->getSubType() == 'rfc822') {
                     if ($data->next() === true) {
                         // Ignore: envelope
                         $data->flushIterator(false);
                     }
                     if ($data->next() === true) {
                         $ob->addPart($this->_parseBodystructure($data));
                     }
                     $data->next();
                     // Ignore: lines
                 }
                 break;
             case 'text':
                 $data->next();
                 // Ignore: lines
                 break;
         }
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         // Ignore: MD5
         if ($data->next() === false) {
             return $ob;
         }
     }
     // This is disposition information
     if (($tmp = $data->next()) === false) {
         return $ob;
     } elseif ($tmp === true) {
         $ob->setDisposition($data->next());
         if ($data->next() === true) {
             foreach ($this->_parseStructureParams($data, 'content-disposition') as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
         $data->next();
     }
     // This is language information. It is either a single value or a list
     // of values.
     if (($tmp = $data->next()) === false) {
         return $ob;
     } elseif (!is_null($tmp)) {
         $ob->setLanguage($tmp === true ? $data->flushIterator() : $tmp);
     }
     // Ignore location (RFC 2557) and consume closing paren.
     $data->flushIterator(false);
     return $ob;
 }
Exemplo n.º 2
0
 /**
  * Recursively parse BODYSTRUCTURE data from a FETCH return (see
  * RFC 3501 [7.4.2]).
  *
  * @param array $data  The tokenized information from the server.
  *
  * @return array  The array of bodystructure information.
  */
 protected function _parseStructure($data)
 {
     $ob = new Horde_Mime_Part();
     // If index 0 is an array, this is a multipart part.
     if (is_array($data[0])) {
         // Keep going through array values until we find a non-array.
         for ($i = 0, $cnt = count($data); $i < $cnt; ++$i) {
             if (!is_array($data[$i])) {
                 break;
             }
             $ob->addPart($this->_parseStructure($data[$i]));
         }
         // The first string entry after an array entry gives us the
         // subpart type.
         $ob->setType('multipart/' . $data[$i]);
         // After the subtype is further extension information. This
         // information MAY not appear for BODYSTRUCTURE requests.
         // This is parameter information.
         if (isset($data[++$i]) && is_array($data[$i])) {
             foreach ($this->_parseStructureParams($data[$i], 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
         // This is disposition information.
         if (isset($data[++$i]) && is_array($data[$i])) {
             $ob->setDisposition($data[$i][0]);
             foreach ($this->_parseStructureParams($data[$i][1], 'content-disposition') as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
         // This is language information. It is either a single value or
         // a list of values.
         if (isset($data[++$i])) {
             $ob->setLanguage($data[$i]);
         }
         // Ignore: location (RFC 2557)
         // There can be further information returned in the future, but
         // for now we are done.
     } else {
         $ob->setType($data[0] . '/' . $data[1]);
         foreach ($this->_parseStructureParams($data[2], 'content-type') as $key => $val) {
             $ob->setContentTypeParameter($key, $val);
         }
         if ($data[3] !== null) {
             $ob->setContentId($data[3]);
         }
         if ($data[4] !== null) {
             $ob->setDescription(Horde_Mime::decode($data[4]));
         }
         if ($data[5] !== null) {
             $ob->setTransferEncoding($data[5]);
         }
         if ($data[6] !== null) {
             $ob->setBytes($data[6]);
         }
         // If the type is 'message/rfc822' or 'text/*', several extra
         // fields are included
         switch ($ob->getPrimaryType()) {
             case 'message':
                 if ($ob->getSubType() == 'rfc822') {
                     // Ignore: envelope
                     $ob->addPart($this->_parseStructure($data[8]));
                     // Ignore: lines
                     $i = 10;
                 } else {
                     $i = 7;
                 }
                 break;
             case 'text':
                 // Ignore: lines
                 $i = 8;
                 break;
             default:
                 $i = 7;
                 break;
         }
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         // Ignore: MD5
         // This is disposition information
         if (isset($data[++$i]) && is_array($data[$i])) {
             $ob->setDisposition($data[$i][0]);
             foreach ($this->_parseStructureParams($data[$i][1], 'content-disposition') as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
         // This is language information. It is either a single value or
         // a list of values.
         if (isset($data[++$i])) {
             $ob->setLanguage($data[$i]);
         }
         // Ignore: location (RFC 2557)
     }
     return $ob;
 }
Exemplo n.º 3
0
 /**
  * Recursively parse BODYSTRUCTURE data from a FETCH return (see
  * RFC 3501 [7.4.2]).
  *
  * @param Horde_Imap_Client_Tokenize $data  Data returned from the server.
  *
  * @return array  The array of bodystructure information.
  */
 protected function _parseBodystructure(Horde_Imap_Client_Tokenize $data)
 {
     $ob = new Horde_Mime_Part();
     // If index 0 is an array, this is a multipart part.
     if (is_object($entry = $data->rewind())) {
         // Keep going through array values until we find a non-array.
         do {
             $ob->addPart($this->_parseBodystructure($entry));
         } while (is_object($entry = $data->next()));
         // The first string entry after an array entry gives us the
         // subpart type.
         $ob->setType('multipart/' . $entry);
         // After the subtype is further extension information. This
         // information MAY not appear for BODYSTRUCTURE requests.
         // This is parameter information.
         if (is_object($tmp = $data->next())) {
             foreach ($this->_parseStructureParams($tmp, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
     } else {
         $ob->setType($entry . '/' . $data->next());
         if (is_object($tmp = $data->next())) {
             foreach ($this->_parseStructureParams($tmp, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setContentId($tmp);
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setDescription(Horde_Mime::decode($tmp));
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setTransferEncoding($tmp);
         }
         $ob->setBytes($data->next());
         // If the type is 'message/rfc822' or 'text/*', several extra
         // fields are included
         switch ($ob->getPrimaryType()) {
             case 'message':
                 if ($ob->getSubType() == 'rfc822') {
                     $data->next();
                     // Ignore: envelope
                     $ob->addPart($this->_parseBodystructure($data->next()));
                     $data->next();
                     // Ignore: lines
                 }
                 break;
             case 'text':
                 $data->next();
                 // Ignore: lines
                 break;
         }
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         $data->next();
         // Ignore: MD5
     }
     // This is disposition information
     if (is_object($tmp = $data->next())) {
         $ob->setDisposition($tmp->rewind());
         foreach ($this->_parseStructureParams($tmp->next(), 'content-disposition') as $key => $val) {
             $ob->setDispositionParameter($key, $val);
         }
     }
     // This is language information. It is either a single value or a list
     // of values.
     if (($tmp = $data->next()) !== false) {
         $ob->setLanguage($tmp);
     }
     $data->next();
     // Ignore: location (RFC 2557)
     return $ob;
 }
Exemplo n.º 4
0
 public function testNullCharactersNotAllowedInMimeHeaderData()
 {
     $part = new Horde_Mime_Part();
     $part->setType("text/plain");
     $this->assertEquals('text/plain', $part->getType());
     $part->setDisposition("inline");
     $this->assertEquals('inline', $part->getDisposition());
     $part->setDispositionParameter('size', '123' . "" . '456');
     $this->assertEquals(123456, $part->getDispositionParameter('size'));
     $part->setDispositionParameter('foo', "foobar");
     $this->assertEquals('foobar', $part->getDispositionParameter('foo'));
     $part->setCharset("utf-8");
     $this->assertEquals('utf-8', $part->getCharset());
     $part->setName("foobar");
     $this->assertEquals('foobar', $part->getName());
     $this->assertEquals('foobar', $part->getDispositionParameter('filename'));
     $this->assertEquals('foobar', $part->getContentTypeParameter('name'));
     $part->setLanguage("en");
     $this->assertEquals(array('en'), $part->getLanguage());
     $part->setLanguage(array("en", "de"));
     $this->assertEquals(array('en', 'de'), $part->getLanguage());
     $part->setDuration('123' . "" . '456');
     $this->assertEquals(123456, $part->getDuration());
     $part->setBytes('123' . "" . '456');
     $this->assertEquals(123456, $part->getBytes());
     $part->setDescription("foobar");
     $this->assertEquals('foobar', $part->getDescription());
     $part->setContentTypeParameter('foo', "foobar");
     $this->assertEquals('foobar', $part->getContentTypeParameter('foo'));
     $part->setContentId("foobar");
     $this->assertEquals('foobar', $part->getContentId());
 }
Exemplo n.º 5
0
 /**
  * Save message to sent-mail mailbox, if configured to do so.
  *
  * @param Horde_Mime_Headers $headers     Headers object.
  * @param Horde_Mime_Part $save_msg       Message data to save.
  * @param Horde_Mail_Rfc822_List $recips  Recipient list.
  * @param array $opts                     See buildAndSendMessage()
  */
 protected function _saveToSentMail(Horde_Mime_Headers $headers, Horde_Mime_Part $save_msg, Horde_Mail_Rfc822_List $recips, $opts)
 {
     global $injector, $language, $notification, $prefs;
     if (empty($opts['sent_mail']) || $prefs->isLocked('save_sent_mail') && !$prefs->getValue('save_sent_mail') || !$prefs->isLocked('save_sent_mail') && empty($opts['save_sent'])) {
         return;
     }
     $imp_imap = $injector->getInstance('IMP_Factory_Imap')->create();
     /* If message contains EAI addresses, we need to verify that the IMAP
      * server can handle this data in order to save. */
     foreach ($recips as $val) {
         if ($val->eai) {
             if ($imp_imap->client_ob->capability->query('UTF8', 'ACCEPT')) {
                 break;
             }
             $notification->push(sprintf(_("Message sent successfully, but not saved to %s."), $sent_mail->display));
             return;
         }
     }
     /* Strip attachments if requested. */
     if (!empty($opts['strip_attachments'])) {
         $save_msg->buildMimeIds();
         /* Don't strip any part if this is a text message with both
          * plaintext and HTML representation. */
         if ($save_msg->getType() != 'multipart/alternative') {
             for ($i = 2;; ++$i) {
                 if (!($oldPart = $save_msg[$i])) {
                     break;
                 }
                 $replace_part = new Horde_Mime_Part();
                 $replace_part->setType('text/plain');
                 $replace_part->setCharset($this->charset);
                 $replace_part->setLanguage($language);
                 $replace_part->setContents('[' . _("Attachment stripped: Original attachment type") . ': "' . $oldPart->getType() . '", ' . _("name") . ': "' . $oldPart->getName(true) . '"]');
                 $save_msg[$i] = $replace_part;
             }
         }
     }
     /* Generate the message string. */
     $fcc = $save_msg->toString(array('defserver' => $imp_imap->config->maildomain, 'headers' => $headers, 'stream' => true));
     /* Make sure sent mailbox is created. */
     $sent_mail = IMP_Mailbox::get($opts['sent_mail']);
     $sent_mail->create();
     $flags = array(Horde_Imap_Client::FLAG_SEEN, Horde_Imap_Client::FLAG_MDNSENT);
     try {
         $imp_imap->append($sent_mail, array(array('data' => $fcc, 'flags' => $flags)));
     } catch (IMP_Imap_Exception $e) {
         $notification->push(sprintf(_("Message sent successfully, but not saved to %s."), $sent_mail->display));
     }
 }
Exemplo n.º 6
0
 /**
  * Builds and sends a MIME message.
  *
  * @param string $body                  The message body.
  * @param array $header                 List of message headers.
  * @param IMP_Prefs_Identity $identity  The Identity object for the sender
  *                                      of this message.
  * @param array $opts                   An array of options w/the
  *                                      following keys:
  *  - encrypt: (integer) A flag whether to encrypt or sign the message.
  *            One of:
  *    - IMP_Crypt_Pgp::ENCRYPT</li>
  *    - IMP_Crypt_Pgp::SIGNENC</li>
  *    - IMP_Crypt_Smime::ENCRYPT</li>
  *    - IMP_Crypt_Smime::SIGNENC</li>
  *  - html: (boolean) Whether this is an HTML message.
  *          DEFAULT: false
  *  - pgp_attach_pubkey: (boolean) Attach the user's PGP public key to the
  *                       message?
  *  - priority: (string) The message priority ('high', 'normal', 'low').
  *  - save_sent: (boolean) Save sent mail?
  *  - sent_mail: (IMP_Mailbox) The sent-mail mailbox (UTF-8).
  *  - strip_attachments: (bool) Strip attachments from the message?
  *  - signature: (string) The message signature.
  *  - readreceipt: (boolean) Add return receipt headers?
  *  - useragent: (string) The User-Agent string to use.
  *  - vcard_attach: (string) Attach the user's vCard (value is name to
  *                  display as vcard filename).
  *
  * @throws Horde_Exception
  * @throws IMP_Compose_Exception
  * @throws IMP_Compose_Exception_Address
  * @throws IMP_Exception
  */
 public function buildAndSendMessage($body, $header, IMP_Prefs_Identity $identity, array $opts = array())
 {
     global $conf, $injector, $notification, $prefs, $registry, $session;
     /* We need at least one recipient & RFC 2822 requires that no 8-bit
      * characters can be in the address fields. */
     $recip = $this->recipientList($header);
     if (!count($recip['list'])) {
         if ($recip['has_input']) {
             throw new IMP_Compose_Exception(_("Invalid e-mail address."));
         }
         throw new IMP_Compose_Exception(_("Need at least one message recipient."));
     }
     $header = array_merge($header, $recip['header']);
     /* Check for correct identity usage. */
     if (!$this->getMetadata('identity_check') && count($recip['list']) === 1) {
         $identity_search = $identity->getMatchingIdentity($recip['list'], false);
         if (!is_null($identity_search) && $identity->getDefault() != $identity_search) {
             $this->_setMetadata('identity_check', true);
             $e = new IMP_Compose_Exception(_("Recipient address does not match the currently selected identity."));
             $e->tied_identity = $identity_search;
             throw $e;
         }
     }
     /* Check body size of message. */
     $imp_imap = $injector->getInstance('IMP_Factory_Imap')->create();
     if (!$imp_imap->accessCompose(IMP_Imap::ACCESS_COMPOSE_BODYSIZE, strlen($body))) {
         Horde::permissionDeniedError('imp', 'max_bodysize');
         throw new IMP_Compose_Exception(sprintf(_("Your message body has exceeded the limit by body size by %d characters."), strlen($body) - $imp_imap->max_compose_bodysize));
     }
     $from = new Horde_Mail_Rfc822_Address($header['from']);
     if (is_null($from->host)) {
         $from->host = $imp_imap->config->maildomain;
     }
     /* Prepare the array of messages to send out.  May be more
      * than one if we are encrypting for multiple recipients or
      * are storing an encrypted message locally. */
     $encrypt = empty($opts['encrypt']) ? 0 : $opts['encrypt'];
     $send_msgs = array();
     $msg_options = array('encrypt' => $encrypt, 'html' => !empty($opts['html']), 'identity' => $identity, 'pgp_attach_pubkey' => !empty($opts['pgp_attach_pubkey']) && $prefs->getValue('use_pgp') && $prefs->getValue('pgp_public_key'), 'signature' => is_null($opts['signature']) ? $identity : $opts['signature'], 'vcard_attach' => !empty($opts['vcard_attach']) && $registry->hasMethod('contacts/ownVCard') ? (strlen($opts['vcard_attach']) ? $opts['vcard_attach'] : 'vcard') . '.vcf' : null);
     /* Must encrypt & send the message one recipient at a time. */
     if ($prefs->getValue('use_smime') && in_array($encrypt, array(IMP_Crypt_Smime::ENCRYPT, IMP_Crypt_Smime::SIGNENC))) {
         foreach ($recip['list'] as $val) {
             $list_ob = new Horde_Mail_Rfc822_List($val);
             $send_msgs[] = array('base' => $this->_createMimeMessage($list_ob, $body, $msg_options), 'recipients' => $list_ob);
         }
         /* Must target the encryption for the sender before saving message
          * in sent-mail. */
         $save_msg = $this->_createMimeMessage(IMP::parseAddressList($header['from']), $body, $msg_options);
     } else {
         /* Can send in clear-text all at once, or PGP can encrypt
          * multiple addresses in the same message. */
         $msg_options['from'] = $from;
         $save_msg = $this->_createMimeMessage($recip['list'], $body, $msg_options);
         $send_msgs[] = array('base' => $save_msg, 'recipients' => $recip['list']);
     }
     /* Initalize a header object for the outgoing message. */
     $headers = $this->_prepareHeaders($header, $opts);
     /* Add a Received header for the hop from browser to server. */
     $headers->addReceivedHeader(array('dns' => $injector->getInstance('Net_DNS2_Resolver'), 'server' => $conf['server']['name']));
     /* Add Reply-To header. */
     if (!empty($header['replyto']) && $header['replyto'] != $from->bare_address) {
         $headers->addHeader('Reply-to', $header['replyto']);
     }
     /* Add the 'User-Agent' header. */
     if (empty($opts['useragent'])) {
         $headers->setUserAgent('Internet Messaging Program (IMP) ' . $registry->getVersion());
     } else {
         $headers->setUserAgent($opts['useragent']);
     }
     $headers->addUserAgentHeader();
     /* Add preferred reply language(s). */
     if ($lang = @unserialize($prefs->getValue('reply_lang'))) {
         $headers->addHeader('Accept-Language', implode(',', $lang));
     }
     /* Send the messages out now. */
     $sentmail = $injector->getInstance('IMP_Sentmail');
     foreach ($send_msgs as $val) {
         switch (intval($this->replyType(true))) {
             case self::REPLY:
                 $senttype = IMP_Sentmail::REPLY;
                 break;
             case self::FORWARD:
                 $senttype = IMP_Sentmail::FORWARD;
                 break;
             case self::REDIRECT:
                 $senttype = IMP_Sentmail::REDIRECT;
                 break;
             default:
                 $senttype = IMP_Sentmail::NEWMSG;
                 break;
         }
         try {
             $this->_prepSendMessageAssert($val['recipients'], $headers, $val['base']);
             $this->sendMessage($val['recipients'], $headers, $val['base']);
             /* Store history information. */
             $msg_id = new Horde_Mail_Rfc822_Identification($headers->getValue('message-id'));
             $sentmail->log($senttype, reset($msg_id->ids), $val['recipients'], true);
         } catch (IMP_Compose_Exception_Address $e) {
             throw $e;
         } catch (IMP_Compose_Exception $e) {
             /* Unsuccessful send. */
             if ($e->log()) {
                 $msg_id = new Horde_Mail_Rfc822_Identification($headers->getValue('message-id'));
                 $sentmail->log($senttype, reset($msg_id->ids), $val['recipients'], false);
             }
             throw new IMP_Compose_Exception(sprintf(_("There was an error sending your message: %s"), $e->getMessage()));
         }
     }
     $recipients = strval($recip['list']);
     if ($this->_replytype) {
         /* Log the reply. */
         if ($indices = $this->getMetadata('indices')) {
             switch ($this->_replytype) {
                 case self::FORWARD:
                 case self::FORWARD_ATTACH:
                 case self::FORWARD_BODY:
                 case self::FORWARD_BOTH:
                     $log = new IMP_Maillog_Log_Forward($recipients);
                     break;
                 case self::REPLY:
                 case self::REPLY_SENDER:
                     $log = new IMP_Maillog_Log_Reply();
                     break;
                 case IMP_Compose::REPLY_ALL:
                     $log = new IMP_Maillog_Log_Replyall();
                     break;
                 case IMP_Compose::REPLY_LIST:
                     $log = new IMP_Maillog_Log_Replylist();
                     break;
             }
             $log_msgs = array();
             foreach ($indices as $val) {
                 foreach ($val->uids as $val2) {
                     $log_msgs[] = new IMP_Maillog_Message(new IMP_Indices($val->mbox, $val2));
                 }
             }
             $injector->getInstance('IMP_Maillog')->log($log_msgs, $log);
         }
         $imp_message = $injector->getInstance('IMP_Message');
         $reply_uid = new IMP_Indices($this);
         switch ($this->replyType(true)) {
             case self::FORWARD:
                 /* Set the Forwarded flag, if possible, in the mailbox.
                  * See RFC 5550 [5.9] */
                 $imp_message->flag(array('add' => array(Horde_Imap_Client::FLAG_FORWARDED)), $reply_uid);
                 break;
             case self::REPLY:
                 /* Make sure to set the IMAP reply flag and unset any
                  * 'flagged' flag. */
                 $imp_message->flag(array('add' => array(Horde_Imap_Client::FLAG_ANSWERED), 'remove' => array(Horde_Imap_Client::FLAG_FLAGGED)), $reply_uid);
                 break;
         }
     }
     Horde::log(sprintf("Message sent to %s from %s (%s)", $recipients, $registry->getAuth(), $session->get('horde', 'auth/remoteAddr')), 'INFO');
     /* Should we save this message in the sent mail mailbox? */
     if (!empty($opts['sent_mail']) && (!$prefs->isLocked('save_sent_mail') && !empty($opts['save_sent']) || $prefs->isLocked('save_sent_mail') && $prefs->getValue('save_sent_mail'))) {
         /* Keep Bcc: headers on saved messages. */
         if (count($header['bcc'])) {
             $headers->addHeader('Bcc', $header['bcc']);
         }
         /* Strip attachments if requested. */
         if (!empty($opts['strip_attachments'])) {
             $save_msg->buildMimeIds();
             /* Don't strip any part if this is a text message with both
              * plaintext and HTML representation. */
             if ($save_msg->getType() != 'multipart/alternative') {
                 for ($i = 2;; ++$i) {
                     if (!($oldPart = $save_msg->getPart($i))) {
                         break;
                     }
                     $replace_part = new Horde_Mime_Part();
                     $replace_part->setType('text/plain');
                     $replace_part->setCharset($this->charset);
                     $replace_part->setLanguage($GLOBALS['language']);
                     $replace_part->setContents('[' . _("Attachment stripped: Original attachment type") . ': "' . $oldPart->getType() . '", ' . _("name") . ': "' . $oldPart->getName(true) . '"]');
                     $save_msg->alterPart($i, $replace_part);
                 }
             }
         }
         /* Generate the message string. */
         $fcc = $save_msg->toString(array('defserver' => $imp_imap->config->maildomain, 'headers' => $headers, 'stream' => true));
         /* Make sure sent mailbox is created. */
         $sent_mail = IMP_Mailbox::get($opts['sent_mail']);
         $sent_mail->create();
         $flags = array(Horde_Imap_Client::FLAG_SEEN, Horde_Imap_Client::FLAG_MDNSENT);
         try {
             $imp_imap->append($sent_mail, array(array('data' => $fcc, 'flags' => $flags)));
         } catch (IMP_Imap_Exception $e) {
             $notification->push(sprintf(_("Message sent successfully, but not saved to %s."), $sent_mail->display));
         }
     }
     /* Delete the attachment data. */
     $this->deleteAllAttachments();
     /* Save recipients to address book? */
     $this->_saveRecipients($recip['list']);
     /* Call post-sent hook. */
     try {
         $injector->getInstance('Horde_Core_Hooks')->callHook('post_sent', 'imp', array($save_msg['msg'], $headers));
     } catch (Horde_Exception_HookNotSet $e) {
     }
 }