1: <?php
2: /**
3: * Copyright 2009-2014 Horde LLC (http://www.horde.org/)
4: *
5: * See the enclosed file COPYING for license information (GPL). If you
6: * did not receive this file, see http://www.horde.org/licenses/gpl.
7: *
8: * @category Horde
9: * @copyright 2009-2014 Horde LLC
10: * @license http://www.horde.org/licenses/gpl GPL
11: * @package IMP
12: */
13:
14: /**
15: * IMP external API interface.
16: *
17: * This file defines IMP's external API interface. Other applications
18: * can interact with IMP through this API.
19: *
20: * @author Michael Slusarz <slusarz@horde.org>
21: * @category Horde
22: * @copyright 2009-2014 Horde LLC
23: * @license http://www.horde.org/licenses/gpl GPL
24: * @package IMP
25: */
26: class IMP_Api extends Horde_Registry_Api
27: {
28: /**
29: * The listing of API calls that do not require permissions checking.
30: *
31: * @var array
32: */
33: protected $_noPerms = array(
34: 'compose', 'batchCompose'
35: );
36:
37: /**
38: * Returns a compose window link.
39: *
40: * @param string|array $args List of arguments to pass to compose page.
41: * If this is passed in as a string, it will be
42: * parsed as a
43: * toaddress?subject=foo&cc=ccaddress
44: * (mailto-style) string.
45: * @param array $extra Hash of extra, non-standard arguments to
46: * pass to compose page.
47: *
48: * @return Horde_Url The link to the message composition screen.
49: */
50: public function compose($args = array(), $extra = array())
51: {
52: $link = $this->batchCompose(array($args), array($extra));
53: return $link[0];
54: }
55:
56: /**
57: * Return a list of compose window links.
58: *
59: * @param string|array $args List of arguments to pass to compose page.
60: * If this is passed in as a string, it will be
61: * parsed as a
62: * toaddress?subject=foo&cc=ccaddress
63: * (mailto-style) string.
64: * @param array $extra List of hashes of extra, non-standard
65: * arguments to pass to compose page.
66: *
67: * @return array The list of Horde_Url objects with links to the message
68: * composition screen.
69: */
70: public function batchCompose($args = array(), $extra = array())
71: {
72: $links = array();
73: foreach ($args as $i => $arg) {
74: $tmp = new IMP_Compose_Link($arg);
75: $links[$i] = $tmp->link();
76: if (!empty($extra[$i])) {
77: $links[$i]->add($extra[$i]);
78: }
79: }
80: return $links;
81: }
82:
83: /**
84: * Returns the list of mailboxes.
85: *
86: * @return array The list of IMAP mailboxes. A list of arrays with the
87: * following keys:
88: * - d: (string) The namespace delimiter.
89: * - label: (string) Human readable label (UTF-8).
90: * - level: (integer) The child level of this element.
91: * - ob: (Horde_Imap_Client_Mailbox) A mailbox object.
92: * - subscribed: (boolean) True if mailbox is subscribed (@since 6.2.0).
93: */
94: public function mailboxList()
95: {
96: global $injector;
97:
98: $iterator = new IMP_Ftree_IteratorFilter(
99: $injector->getInstance('IMP_Ftree')
100: );
101: $iterator->add(array(
102: $iterator::CONTAINERS,
103: $iterator::REMOTE,
104: $iterator::VFOLDER
105: ));
106: $mboxes = array();
107:
108: foreach ($iterator as $val) {
109: $mbox_ob = $val->mbox_ob;
110: $sub = $mbox_ob->sub;
111:
112: $mboxes[] = array(
113: // TODO: Remove for IMP 7.
114: 'a' => $sub ? 8 : 0,
115: 'd' => $mbox_ob->namespace_delimiter,
116: 'label' => $mbox_ob->label,
117: 'level' => $val->level,
118: 'ob' => $mbox_ob->imap_mbox_ob,
119: 'subscribed' => $sub
120: );
121: }
122:
123: return $mboxes;
124: }
125:
126: /**
127: * Creates a new mailbox.
128: *
129: * @param string $mbox The name of the mailbox to create (UTF-8).
130: * @param array $options Additional options:
131: * - full: (boolean) If true, $mbox is a full mailbox name. If false,
132: * $mbox will be created in the default namespace.
133: * DEFAULT: false
134: *
135: * @return Horde_Imap_Client_Mailbox The mailbox name created or false on
136: * failure.
137: *
138: * @throws IMP_Exception
139: */
140: public function createMailbox($mbox, array $options = array())
141: {
142: $fname = IMP_Mailbox::get($mbox);
143: if (empty($options['full'])) {
144: $fname = $fname->namespace_append;
145: }
146:
147: return $fname->create()
148: ? $fname->imap_mbox_ob
149: : false;
150: }
151:
152: /**
153: * Deletes messages from a mailbox.
154: *
155: * @param string $mailbox The name of the mailbox (UTF-8).
156: * @param array $indices The list of UIDs to delete.
157: *
158: * @return integer|boolean The number of messages deleted if successful,
159: * false if not.
160: */
161: public function deleteMessages($mailbox, $indices)
162: {
163: return $GLOBALS['injector']->getInstance('IMP_Message')->delete(
164: new IMP_Indices($mailbox, $indices),
165: array('nuke' => true)
166: );
167: }
168:
169: /**
170: * Copies messages to a mailbox.
171: *
172: * @param string $mailbox The name of the source mailbox (UTF-8).
173: * @param array $indices The list of UIDs to copy.
174: * @param string $target The name of the target mailbox (UTF-8).
175: *
176: * @return boolean True if successful, false if not.
177: */
178: public function copyMessages($mailbox, $indices, $target)
179: {
180: return $GLOBALS['injector']->getInstance('IMP_Message')->copy(
181: $target,
182: 'copy',
183: new IMP_Indices($mailbox, $indices),
184: array('create' => true)
185: );
186: }
187:
188: /**
189: * Moves messages to a mailbox.
190: *
191: * @param string $mailbox The name of the source mailbox (UTF-8).
192: * @param array $indices The list of UIDs to move.
193: * @param string $target The name of the target mailbox (UTF-8).
194: *
195: * @return boolean True if successful, false if not.
196: */
197: public function moveMessages($mailbox, $indices, $target)
198: {
199: return $GLOBALS['injector']->getInstance('IMP_Message')->copy(
200: $target,
201: 'move',
202: new IMP_Indices($mailbox, $indices),
203: array('create' => true)
204: );
205: }
206:
207: /**
208: * Flag messages.
209: *
210: * @param string $mailbox The name of the source mailbox (UTF-8).
211: * @param array $indices The list of UIDs to flag.
212: * @param array $flags The flags to set.
213: * @param boolean $set True to set flags, false to clear flags.
214: *
215: * @return boolean True if successful, false if not.
216: */
217: public function flagMessages($mailbox, $indices, $flags, $set)
218: {
219: return $GLOBALS['injector']->getInstance('IMP_Message')->flag(array(
220: ($set ? 'add' : 'remove') => $flags
221: ), new IMP_Indices($mailbox, $indices));
222: }
223:
224: /**
225: * Ensures a list of user-defined IMAP flag(s) for the current user exist.
226: * Silently ignores any flags that are already defined.
227: *
228: * @param array $flags An array of user-defined flag names.
229: * @since 6.3.0
230: */
231: public function addFlags(array $flags)
232: {
233: $imp_flags = $GLOBALS['injector']->getInstance('IMP_Flags');
234: foreach ($flags as $flag) {
235: try {
236: $imp_flags->addFlag($flag);
237: } catch (IMP_Exception $e) {
238: }
239: }
240: }
241:
242: /**
243: * Perform a search query on the remote IMAP server.
244: *
245: * @param string $mailbox The name of the source
246: * mailbox (UTF-8).
247: * @param Horde_Imap_Client_Search_Query $query The query object.
248: *
249: * @return array The search results (UID list).
250: */
251: public function searchMailbox($mailbox, $query)
252: {
253: $results = IMP_Mailbox::get($mailbox)->runSearchQuery($query);
254: return isset($results[strval($mailbox)])
255: ? $results[strval($mailbox)]
256: : array();
257: }
258:
259: /**
260: * Returns information on the currently logged on IMAP server.
261: *
262: * @return mixed An array with the following entries:
263: * - hostspec: (string) The server hostname.
264: * - port: (integer) The server port.
265: * - protocol: (string) Either 'imap' or 'pop'.
266: * - secure: (string) Either 'none', 'ssl', or 'tls'.
267: */
268: public function server()
269: {
270: $imap_ob = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
271:
272: return array(
273: 'hostspec' => $imap_ob->getParam('hostspec'),
274: 'port' => $imap_ob->getParam('port'),
275: 'protocol' => $imap_ob->isImap() ? 'imap' : 'pop',
276: 'secure' => $imap_ob->getParam('secure')
277: );
278: }
279:
280: /**
281: * Returns the list of favorite recipients.
282: *
283: * @param integer $limit Return this number of recipients.
284: * @param array $filter A list of messages types that should be
285: * returned. Valid types: 'forward', 'mdn', 'new',
286: * 'reply', and 'redirect'. A value of null returns
287: * all message types.
288: *
289: * @return array A list with the $limit most favourite recipients.
290: * @throws IMP_Exception
291: */
292: public function favouriteRecipients($limit,
293: $filter = array('new', 'forward', 'reply', 'redirect'))
294: {
295: if (!empty($filter)) {
296: $new_filter = array();
297: foreach ($filter as $val) {
298: switch ($val) {
299: case 'forward':
300: $new_filter[] = IMP_Sentmail::FORWARD;
301: break;
302:
303: case 'mdn':
304: $new_filter[] = IMP_Sentmail::MDN;
305: break;
306:
307: case 'new':
308: $new_filter[] = IMP_Sentmail::NEWMSG;
309: break;
310:
311: case 'redirect':
312: $new_filter[] = IMP_Sentmail::REDIRECT;
313: break;
314:
315: case 'reply':
316: $new_filter[] = IMP_Sentmail::REPLY;
317: break;
318: }
319: }
320:
321: $filter = $new_filter;
322: }
323:
324: return $GLOBALS['injector']->getInstance('IMP_Sentmail')->favouriteRecipients($limit, $filter);
325: }
326:
327: /**
328: * Log an entry to the IMP_Sentmail system.
329: *
330: * @param string $action The performed action. One of:
331: * - forward
332: * - mdn
333: * - new
334: * - redirect
335: * - reply
336: * @param string|array $recipients The message recipients.
337: * @param string $message_id The Message-ID.
338: * @param boolean $success Was the message successfully sent?
339: */
340: public function logRecipient(
341: $reason, $recipients, $message_id, $success = true
342: )
343: {
344: $GLOBALS['injector']->getInstance('IMP_Sentmail')->log(
345: $reason,
346: $message_id,
347: $recipients,
348: $success
349: );
350: }
351:
352: /**
353: * Returns the Horde_Imap_Client object created using the IMP credentials.
354: *
355: * @return Horde_Imap_Client_Base The imap object.
356: */
357: public function imapOb()
358: {
359: return $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->client_ob;
360: }
361:
362: /**
363: * Return the list of user-settable IMAP flags.
364: *
365: * @param string $mailbox If set, returns the list of flags filtered by
366: * what the mailbox allows (UTF-8).
367: *
368: * @return array A list of IMP_Flag_Base objects.
369: * @since 6.3.0
370: */
371: public function flagList($mailbox = null)
372: {
373: return $GLOBALS['injector']->getInstance('IMP_Flags')->getList(array(
374: 'imap' => true,
375: 'mailbox' => $mailbox
376: ));
377: }
378:
379: /**
380: * Return the list of special mailboxes.
381: *
382: * @return @see IMP_Mailbox::getSpecialMailboxes()
383: */
384: public function getSpecialMailboxes()
385: {
386: return IMP_Mailbox::getSpecialMailboxes();
387: }
388:
389: /**
390: * Obtain the Maillog for a given message.
391: *
392: * @since 6.1.0
393: * @todo This should not be returning a Horde_History_Log object.
394: *
395: * @param string $mid The Message-ID to obtain the log for.
396: *
397: * @return Horde_History_Log The log object.
398: */
399: public function getMaillog($mid)
400: {
401: global $injector, $registry;
402:
403: $log = $injector->getInstance('IMP_Maillog')->getLog(
404: new IMP_Maillog_Message($mid)
405: );
406:
407: $history = array();
408: foreach ($log as $val) {
409: $history[] = array(
410: 'history_action' => $val->action,
411: 'history_desc' => '',
412: 'history_id' => 0,
413: 'history_modseq' => 0,
414: 'history_ts' => $val->timestamp,
415: 'history_who' => $registry->getAuth()
416: );
417: }
418:
419: return new Horde_History_Log($mid, $history);
420: }
421:
422: /**
423: * Log an entry in the Maillog.
424: *
425: * @since 6.1.0
426: * @todo Rewrite this. $action and $data are both IMP specific, so they
427: * aren't intended to be set from outside of IMP. And $mid should
428: * be replaced by mailbox/UID.
429: *
430: * @param string $action The action to log.
431: * @param string $mid The Message-ID.
432: * @param string $data Additional data.
433: */
434: public function logMaillog($action, $mid, $data = null)
435: {
436: switch ($action) {
437: case 'forward':
438: $log = new IMP_Maillog_Log_Forward($data['recipients']);
439: break;
440:
441: case 'mdn':
442: $log = new IMP_Maillog_Log_Mdn();
443: break;
444:
445: case 'redirect':
446: $log = new IMP_Maillog_Log_Redirect($data['recipients']);
447: break;
448:
449: case 'reply':
450: $log = new IMP_Maillog_Log_Reply();
451: break;
452:
453: case 'reply_all':
454: $log = new IMP_Maillog_Log_Replyall();
455: break;
456:
457: case 'reply_list':
458: $log = new IMP_Maillog_Log_Replylist();
459: break;
460: }
461:
462: $GLOBALS['injector']->getInstance('IMP_Maillog')->log(
463: new IMP_Maillog_Message($mid),
464: $log
465: );
466: }
467:
468: /**
469: * Returns a list of Message-IDs that have been added to the Maillog since
470: * the specified timestamp.
471: *
472: * @since 6.1.0
473: * @todo This should not be returning Message-IDs.
474: *
475: * @param integer $ts The timestamp to start searching from. Only entries
476: * after this timestamp will be returned.
477: *
478: * @return array An array of Message-IDs that have been changed since $ts.
479: */
480: public function getMaillogChanges($ts)
481: {
482: return array_map(
483: 'strval',
484: $GLOBALS['injector']->getInstance('IMP_Maillog')->getChanges($ts)
485: );
486: }
487:
488: }
489: