public function buildAndSendMessage($body, $header, IMP_Prefs_Identity $identity, array $opts = array())
{
global $injector, $prefs, $registry, $session;
/* Set up defaults. */
$opts = array_merge(array('encrypt' => IMP::ENCRYPT_NONE), $opts);
/* 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));
}
/* We need at least one recipient. */
$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."));
}
/* Recipient checks. */
$this->_prepSendMessageAssert($recip['list']);
/* 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;
}
}
/* 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->addHeaderOb(Horde_Core_Mime_Headers_Received::createHordeHop());
/* Add the 'User-Agent' header. */
$headers->addHeaderOb(new Horde_Mime_Headers_UserAgent(null, empty($opts['useragent']) ? 'Internet Messaging Program (IMP) ' . $registry->getVersion() : $opts['useragent']));
/* Add preferred reply language(s). */
if ($lang = @unserialize($prefs->getValue('reply_lang'))) {
$headers->addHeader('Accept-Language', implode(',', $lang));
}
$message = $this->_createMimeMessage($body, array('html' => !empty($opts['html']), 'identity' => $identity, 'pgp_attach_pubkey' => !empty($opts['pgp_attach_pubkey']) && $prefs->getValue('use_pgp') && $prefs->getValue('pgp_public_key'), 'recip' => $recip['list'], '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));
/* Pass to hook to allow alteration of message details. */
try {
$injector->getInstance('Horde_Core_Hooks')->callHook('pre_sent', 'imp', array($message, $headers, $this));
/* Re-parse headers to determine up-to-date recipient list. */
$tmp_recip = array();
foreach (array('to', 'cc', 'bcc') as $val) {
if ($tmp_hdr = $headers[$val]) {
$tmp_recip[$val] = $tmp_hdr->getAddressList(true);
}
}
$recip = $this->recipientList($tmp_recip);
} catch (Horde_Exception_HookNotSet $e) {
}
/* Get from address. Done after pre_sent hook since from address could
* be changed by hook. */
$from = $headers['from']->getAddressList(true)->first();
if (is_null($from->host)) {
$from->host = $imp_imap->config->maildomain;
}
/* Add Reply-To header. Done after pre_sent hook since from address
* could be change by hook and/or Reply-To was set by hook. */
if (!empty($header['replyto']) && $header['replyto'] != $from->bare_address && !isset($headers['reply-to'])) {
$headers->addHeader('Reply-To', $header['replyto']);
}
$message = $this->_encryptMessage($message, $opts['encrypt'], $recip['list'], $from);
/* Send the messages out now. */
try {
$this->sendMessage($recip['list'], $headers, $message);
/* Store history information. Even if history is inactive, this
* will provide Message ID of message. */
$msgid = $this->_logSentmail($headers, $recip['list'], true);
} catch (IMP_Compose_Exception_Address $e) {
throw $e;
} catch (IMP_Compose_Exception $e) {
/* Unsuccessful send. */
if ($e->log()) {
$this->_logSentmail($headers, $recip['list'], false);
}
throw new IMP_Compose_Exception(sprintf(_("There was an error sending your message: %s"), $e->getMessage()));
}
if ($this->_replytype) {
/* Log the reply. */
if ($indices = $this->getMetadata('indices')) {
$log_data = array('msgid' => $msgid, 'folder' => empty($opts['sent_mail']) ? null : $opts['sent_mail']);
switch ($this->_replytype) {
case self::FORWARD:
case self::FORWARD_ATTACH:
case self::FORWARD_BODY:
case self::FORWARD_BOTH:
$ob = 'IMP_Maillog_Log_Forward';
$log_data['recipients'] = strval($recip['list']);
break;
case self::REPLY:
case self::REPLY_SENDER:
$ob = 'IMP_Maillog_Log_Reply';
break;
case IMP_Compose::REPLY_ALL:
$ob = 'IMP_Maillog_Log_Replyall';
break;
case IMP_Compose::REPLY_LIST:
$ob = 'IMP_Maillog_Log_Replylist';
break;
}
$log = new $ob($log_data);
$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);
}
$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] */
$reply_uid->flag(array(Horde_Imap_Client::FLAG_FORWARDED));
break;
case self::REPLY:
/* Make sure to set the IMAP reply flag and unset any
* 'flagged' flag. */
$reply_uid->flag(array(Horde_Imap_Client::FLAG_ANSWERED), array(Horde_Imap_Client::FLAG_FLAGGED));
break;
}
}
Horde::log(sprintf("Message sent to %s from %s (%s)", strval($recip['list']), $registry->getAuth(), $session->get('horde', 'auth/remoteAddr')), 'INFO');
/* Save message to the sent mail mailbox. */
$this->_saveToSentMail($headers, $message, $recip['list'], $opts);
/* 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($message, $headers));
} catch (Horde_Exception_HookNotSet $e) {
}
}