* Calendar/Mail: send meeting requests including html body like current Exchange server does it

This commit is contained in:
Ralf Becker 2015-10-19 19:48:52 +00:00
parent 1be489b706
commit 2ce94499c0
2 changed files with 95 additions and 27 deletions

View File

@ -1142,7 +1142,20 @@ class calendar_uiforms extends calendar_ui
//error_log(__METHOD__.__LINE__.array2string($to));
}
}
list($subject,$body) = $this->bo->get_update_message($event,$added ? MSG_ADDED : MSG_MODIFIED); // update-message is in TZ of the user
// prefer event description over standard notification text
if (empty($event['description']))
{
list(,$body) = $this->bo->get_update_message($event,$added ? MSG_ADDED : MSG_MODIFIED); // update-message is in TZ of the user
}
else
{
$body = $event['description'];
}
// respect user preference about html mail
if ($GLOBALS['egw_info']['user']['preferences']['mail']['composeOptions'] != 'text')
{
$body = '<pre>'.$body.'</pre>';
}
//error_log(__METHOD__.print_r($event,true));
$boical = new calendar_ical();
// we need to pass $event[id] so iCal class reads event again,
@ -1158,7 +1171,7 @@ class calendar_uiforms extends calendar_ui
//error_log(__METHOD__.__LINE__.array2string($to));
$vars = array(
'menuaction' => 'mail.mail_compose.compose',
'mimeType' => 'plain', // force type to plain as thunderbird seems to try to be smart while parsing html messages with ics attachments
'mimeType' => $GLOBALS['egw_info']['user']['preferences']['mail']['composeOptions'] != 'text' ? 'html' : 'plain',
'preset[to]' => $to,
'preset[subject]' => $event['title'],
'preset[body]' => $body,

View File

@ -330,21 +330,21 @@ class egw_mailer extends Horde_Mime_Mail
{
throw new egw_exception_not_found("File '$data' not found!");
}
$part = new Horde_Mime_Part();
if ($type || !is_resource($data)) $part->setType($type ? $type : egw_vfs::mime_content_type($data));
$matches = null;
if (preg_match('/^([^;]+);\s*([^=]+)=([^;]+)$/', $type, $matches))
{
$part->setContentTypeParameter($matches[2], $matches[3]);
}
$part->setContents($resource);
// store "text/calendar" as _htmlBody, to trigger "multipart/alternative"
if (stripos($type,"text/calendar; method=") !== false)
if (empty($type) && !is_resource($data)) $type = egw_vfs::mime_content_type($data);
// set "text/calendar; method=*" as alternativ body
$matches = null;
if (preg_match('|^text/calendar; method=([^;]+)|i', $type, $matches))
{
$this->_htmlBody = $part;
$this->setAlternativBody($resource, $type, array('method' => $matches[1]), 'utf-8');
return;
}
$part = new Horde_Mime_Part();
$part->setType($type);
$part->setContents($resource);
// setting name, also sets content-disposition attachment (!), therefore we have to do it after "text/calendar; method=" handling
if ($name || !is_resource($data)) $part->setName($name ? $name : egw_vfs::basename($data));
@ -375,7 +375,7 @@ class egw_mailer extends Horde_Mime_Mail
}
$part_id = $this->addAttachment($data, $name, $type);
error_log(__METHOD__."(".array2string($data).", '$cid', '$name', '$type') added with (temp.) part_id=$part_id");
//error_log(__METHOD__."(".array2string($data).", '$cid', '$name', '$type') added with (temp.) part_id=$part_id");
$part = $this->_parts[$part_id];
$part->setDisposition('inline');
@ -403,22 +403,19 @@ class egw_mailer extends Horde_Mime_Mail
$type = func_get_arg(3);
}
// set "text/calendar; method=*" as alternativ body
$matches = null;
if (preg_match('|^text/calendar; method=([^;]+)|i', $type, $matches))
{
$this->setAlternativBody($content, $type, array('method' => $matches[1]), 'utf-8');
return;
}
$part = new Horde_Mime_Part();
$part->setType($type);
$matches = null;
if (preg_match('/^([^;]+);\s*([^=]+)=([^;]+)$/', $type, $matches))
{
$part->setContentTypeParameter($matches[2], $matches[3]);
}
$part->setCharset('utf-8');
$part->setContents($content);
// store "text/calendar" as _htmlBody, to trigger "multipart/alternative"
if (stripos($type,"text/calendar; method=") !== false)
{
$this->_htmlBody = $part;
return;
}
// this should not be necessary, because binary data get detected by mime-type,
// but at least Cyrus complains about NUL characters
$part->setTransferEncoding('base64', array('send' => true));
@ -428,6 +425,28 @@ class egw_mailer extends Horde_Mime_Mail
return $this->addMimePart($part);
}
/**
* Sets alternativ body, eg. text/calendar has highest / last alternativ
*
* Until pull request to Horde_Mime_Mail gets approved.
*
* @param string|resource $content
* @param string $type eg. "text/calendar" or "text/calendar; method=REQUEST"
* @param array $parameters =array() eg. array('method' => 'REQUEST')
* @param string $charset =null default to $this->_charset="utf-8"
*/
function setAlternativBody($content, $type, $parameters=array(), $charset=null)
{
$this->_alternativBody = new Horde_Mime_Part();
$this->_alternativBody->setType($type);
foreach($parameters as $label => $data)
{
$this->_alternativBody->setContentTypeParameter($label, $data);
}
$this->_alternativBody->setCharset($charset ? $charset : $this->_charset);
$this->_alternativBody->setContents($content);
}
/**
* Send mail, injecting mail transport from account
*
@ -481,8 +500,44 @@ class egw_mailer extends Horde_Mime_Mail
}
try {
parent::send($this->account->smtpTransport(), true, // true: keep Message-ID
$this->_body && $this->_body->getType() != 'multipart/encrypted'); // no flowed for encrypted messages
// no flowed for encrypted messages
$flowed = $this->_body && $this->_body->getType() != 'multipart/encrypted';
// vvv until pull request to Horde_Mime_Mail gets approved vvvvvvvvv
if (!empty($this->_alternativBody) && empty($this->_htmlBody))
{
$this->_htmlBody = $this->_alternativBody;
unset($this->_alternativBody);
}
if (!empty($this->_alternativBody))
{
parent::send(new Horde_Mail_Transport_Null, true, $flowed); // true: keep Message-ID
$this->_base[] = $this->_alternativBody;
/* Build recipients. */
$recipients = clone $this->_recipients;
foreach (array('to', 'cc') as $header) {
if (($h = $this->_headers[$header])) {
$recipients->add($h->getAddressList());
}
}
if ($this->_bcc) {
$recipients->add($this->_bcc);
}
/* Trick Horde_Mime_Part into re-generating the message headers. */
$this->_headers->removeHeader('MIME-Version');
/* Send message. */
$recipients->unique();
$this->_base->send($recipients->writeAddress(), $this->_headers, $this->account->smtpTransport());
}
else
// ^^^ until pull request to Horde_Mime_Mail gets approved ^^^^^^^^^
{
parent::send($this->account->smtpTransport(), true, $flowed); // true: keep Message-ID
}
}
catch (Exception $e) {
// in case of errors/exceptions call hook again with previous returned mail_id and error-message to log