protected function _createMimeMessage($body, array $options = array())
{
global $injector, $prefs, $registry;
/* Get body text. */
if (empty($options['html'])) {
$body_html = null;
} else {
$tfilter = $injector->getInstance('Horde_Core_Factory_TextFilter');
$body_html = $tfilter->filter($body, 'Xss', array('return_dom' => true, 'strip_style_attributes' => false));
$body_html_body = $body_html->getBody();
$body = $tfilter->filter($body_html->returnHtml(), 'Html2text', array('width' => 0));
}
$hooks = $injector->getInstance('Horde_Core_Hooks');
/* We need to do the attachment check before any of the body text
* has been altered. */
if (!count($this) && !$this->getMetadata('attach_body_check')) {
$this->_setMetadata('attach_body_check', true);
try {
$check = $hooks->callHook('attach_body_check', 'imp', array($body));
} catch (Horde_Exception_HookNotSet $e) {
$check = array();
}
if (!empty($check) && preg_match('/\\b(' . implode('|', array_map('preg_quote', $check, array_fill(0, count($check), '/'))) . ')\\b/i', $body, $matches)) {
throw IMP_Compose_Exception::createAndLog('DEBUG', sprintf(_("Found the word %s in the message text although there are no files attached to the message. Did you forget to attach a file? (This check will not be performed again for this message.)"), $matches[0]));
}
}
/* Add signature data. */
if (!empty($options['signature'])) {
if (is_string($options['signature'])) {
if (empty($options['html'])) {
$body .= "\n\n" . trim($options['signature']);
} else {
$html_sig = trim($options['signature']);
$body .= "\n" . $tfilter->filter($html_sig, 'Html2text');
}
} else {
$sig = $options['signature']->getSignature('text');
$body .= $sig;
if (!empty($options['html'])) {
$html_sig = $options['signature']->getSignature('html');
if (!strlen($html_sig) && strlen($sig)) {
$html_sig = $this->text2html($sig);
}
}
}
if (!empty($options['html'])) {
try {
$sig_ob = new IMP_Compose_HtmlSignature($html_sig);
} catch (IMP_Exception $e) {
throw new IMP_Compose_Exception($e);
}
foreach ($sig_ob->dom->getBody()->childNodes as $child) {
$body_html_body->appendChild($body_html->dom->importNode($child, true));
}
}
}
/* Add linked attachments. */
if (empty($options['nofinal'])) {
$this->_linkAttachments($body, $body_html);
}
/* Get trailer text (if any). */
if (empty($options['nofinal']) && !empty($options['recip'])) {
try {
$trailer = $hooks->callHook('trailer', 'imp', array(false, $options['identity'], $options['recip']));
$html_trailer = $hooks->callHook('trailer', 'imp', array(true, $options['identity'], $options['recip']));
} catch (Horde_Exception_HookNotSet $e) {
$trailer = $html_trailer = null;
}
$body .= strval($trailer);
if (!empty($options['html'])) {
if (is_null($html_trailer) && strlen($trailer)) {
$html_trailer = $this->text2html($trailer);
}
if (strlen($html_trailer)) {
$t_dom = new Horde_Domhtml($html_trailer, 'UTF-8');
foreach ($t_dom->getBody()->childNodes as $child) {
$body_html_body->appendChild($body_html->dom->importNode($child, true));
}
}
}
}
/* Convert text to sending charset. HTML text will be converted
* via Horde_Domhtml. */
$body = Horde_String::convertCharset($body, 'UTF-8', $this->charset);
/* Set up the body part now. */
$textBody = new Horde_Mime_Part();
$textBody->setType('text/plain');
$textBody->setCharset($this->charset);
$textBody->setDisposition('inline');
/* Send in flowed format. */
$flowed = new Horde_Text_Flowed($body, $this->charset);
$flowed->setDelSp(true);
$textBody->setContentTypeParameter('format', 'flowed');
$textBody->setContentTypeParameter('DelSp', 'Yes');
$text_contents = $flowed->toFlowed();
$textBody->setContents($text_contents);
/* Determine whether or not to send a multipart/alternative
* message with an HTML part. */
if (!empty($options['html'])) {
$htmlBody = new Horde_Mime_Part();
$htmlBody->setType('text/html');
$htmlBody->setCharset($this->charset);
$htmlBody->setDisposition('inline');
$htmlBody->setDescription(Horde_String::convertCharset(_("HTML Message"), 'UTF-8', $this->charset));
/* Add default font CSS information here. */
$styles = array();
if ($font_family = $prefs->getValue('compose_html_font_family')) {
$styles[] = 'font-family:' . $font_family;
}
if ($font_size = intval($prefs->getValue('compose_html_font_size'))) {
$styles[] = 'font-size:' . $font_size . 'px';
}
if (!empty($styles)) {
$body_html_body->setAttribute('style', implode(';', $styles));
}
if (empty($options['nofinal'])) {
$this->_cleanHtmlOutput($body_html);
}
$to_add = $this->_convertToRelated($body_html, $htmlBody);
/* Now, all parts referred to in the HTML data have been added
* to the attachment list. Convert to multipart/related if
* this is the case. Exception: if text representation is empty,
* just send HTML part. */
if (strlen(trim($text_contents))) {
$textpart = new Horde_Mime_Part();
$textpart->setType('multipart/alternative');
$textpart[] = $textBody;
$textpart[] = $to_add;
$textpart->setHeaderCharset($this->charset);
$textBody->setDescription(Horde_String::convertCharset(_("Plaintext Message"), 'UTF-8', $this->charset));
} else {
$textpart = $to_add;
}
$htmlBody->setContents($tfilter->filter($body_html->returnHtml(array('charset' => $this->charset, 'metacharset' => true)), 'Cleanhtml', array('charset' => $this->charset)));
$base = $textpart;
} else {
$base = $textpart = strlen(trim($text_contents)) ? $textBody : null;
}
/* Add attachments. */
if (empty($options['noattach'])) {
$parts = array();
foreach ($this as $val) {
if (!$val->related && !$val->linked) {
$parts[] = $val->getPart(true);
}
}
if (!empty($options['pgp_attach_pubkey'])) {
$parts[] = $injector->getInstance('IMP_Crypt_Pgp')->publicKeyMIMEPart();
}
if (!empty($options['vcard_attach'])) {
try {
$vpart = new Horde_Mime_Part();
$vpart->setType('text/x-vcard');
$vpart->setCharset('UTF-8');
$vpart->setContents($registry->call('contacts/ownVCard'));
$vpart->setName($options['vcard_attach']);
$parts[] = $vpart;
} catch (Horde_Exception $e) {
throw new IMP_Compose_Exception(sprintf(_("Can't attach contact information: %s"), $e->getMessage()));
}
}
if (!empty($parts)) {
if (is_null($base) && count($parts) === 1) {
/* If this is a single attachment with no text, the
* attachment IS the message. */
$base = reset($parts);
} else {
$base = new Horde_Mime_Part();
$base->setType('multipart/mixed');
if (!is_null($textpart)) {
$base[] = $textpart;
}
foreach ($parts as $val) {
$base[] = $val;
}
}
}
}
/* If we reach this far with no base, we are sending a blank message.
* Assume this is what the user wants. */
if (is_null($base)) {
$base = $textBody;
}
/* Flag this as the base part and rebuild MIME IDs. */
$base->isBasePart(true);
$base->buildMimeIds();
return $base;
}