1: <?php
2: /**
3: * Base class for Horde_Imap_Client package. Defines common constants and
4: * provides factory for creating an IMAP client object.
5: *
6: * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
7: *
8: * See the enclosed file COPYING for license information (LGPL). If you
9: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
10: *
11: * @author Michael Slusarz <slusarz@horde.org>
12: * @category Horde
13: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
14: * @package Imap_Client
15: */
16: class Horde_Imap_Client
17: {
18: /* Constants for openMailbox() */
19: const OPEN_READONLY = 1;
20: const OPEN_READWRITE = 2;
21: const OPEN_AUTO = 3;
22:
23: /* Constants for listMailboxes() */
24: const MBOX_SUBSCRIBED = 1;
25: const MBOX_SUBSCRIBED_EXISTS = 2;
26: const MBOX_UNSUBSCRIBED = 3;
27: const MBOX_ALL = 4;
28:
29: /* Constants for status() */
30: const STATUS_MESSAGES = 1;
31: const STATUS_RECENT = 2;
32: const STATUS_UIDNEXT = 4;
33: const STATUS_UIDVALIDITY = 8;
34: const STATUS_UNSEEN = 16;
35: const STATUS_ALL = 32;
36: const STATUS_FIRSTUNSEEN = 64;
37: const STATUS_FLAGS = 128;
38: const STATUS_PERMFLAGS = 256;
39: const STATUS_HIGHESTMODSEQ = 512;
40: const STATUS_LASTMODSEQ = 1024;
41: const STATUS_LASTMODSEQUIDS = 2048;
42: const STATUS_UIDNOTSTICKY = 4096;
43:
44: /* Constants for search() */
45: const SORT_ARRIVAL = 1;
46: const SORT_CC = 2;
47: const SORT_DATE = 3;
48: const SORT_FROM = 4;
49: const SORT_REVERSE = 5;
50: const SORT_SIZE = 6;
51: const SORT_SUBJECT = 7;
52: const SORT_TO = 8;
53: /* SORT_THREAD provided for completeness - it is not a valid sort criteria
54: * for search() (use thread() instead). */
55: const SORT_THREAD = 9;
56: /* Sort criteria defined in RFC 5957 */
57: const SORT_DISPLAYFROM = 10;
58: const SORT_DISPLAYTO = 11;
59: /* SORT_SEQUENCE does a simple numerical sort on the returned
60: * UIDs/sequence numbers. */
61: const SORT_SEQUENCE = 12;
62: /* Fuzzy sort criteria defined in RFC 6203 */
63: const SORT_RELEVANCY = 13;
64:
65: /* Search results constants */
66: const SEARCH_RESULTS_COUNT = 1;
67: const SEARCH_RESULTS_MATCH = 2;
68: const SEARCH_RESULTS_MAX = 3;
69: const SEARCH_RESULTS_MIN = 4;
70: const SEARCH_RESULTS_SAVE = 5;
71: /* Fuzzy sort criteria defined in RFC 6203 */
72: const SEARCH_RESULTS_RELEVANCY = 6;
73:
74: /* DEPRECATED: Use SEARCH_RESULTS_* instead. */
75: const SORT_RESULTS_COUNT = 1;
76: const SORT_RESULTS_MATCH = 2;
77: const SORT_RESULTS_MAX = 3;
78: const SORT_RESULTS_MIN = 4;
79: const SORT_RESULTS_SAVE = 5;
80:
81: /* Constants for thread() */
82: const THREAD_ORDEREDSUBJECT = 1;
83: const THREAD_REFERENCES = 2;
84: const THREAD_REFS = 3;
85:
86: /* Fetch criteria constants. */
87: const FETCH_STRUCTURE = 1;
88: const FETCH_FULLMSG = 2;
89: const FETCH_HEADERTEXT = 3;
90: const FETCH_BODYTEXT = 4;
91: const FETCH_MIMEHEADER = 5;
92: const FETCH_BODYPART = 6;
93: const FETCH_BODYPARTSIZE = 7;
94: const FETCH_HEADERS = 8;
95: const FETCH_ENVELOPE = 9;
96: const FETCH_FLAGS = 10;
97: const FETCH_IMAPDATE = 11;
98: const FETCH_SIZE = 12;
99: const FETCH_UID = 13;
100: const FETCH_SEQ = 14;
101: const FETCH_MODSEQ = 15;
102:
103: /* IMAP data types (RFC 3501 [4]) */
104: const DATA_ASTRING = 1;
105: const DATA_ATOM = 2;
106: const DATA_DATETIME = 3;
107: const DATA_LISTMAILBOX = 4;
108: const DATA_MAILBOX = 5;
109: const DATA_NSTRING = 6;
110: const DATA_NUMBER = 7;
111: const DATA_STRING = 8;
112:
113: /* Namespace constants. */
114: const NS_PERSONAL = 1;
115: const NS_OTHER = 2;
116: const NS_SHARED = 3;
117:
118: /* ACL constants (RFC 4314 [2.1]). */
119: const ACL_LOOKUP = 'l';
120: const ACL_READ = 'r';
121: const ACL_SEEN = 's';
122: const ACL_WRITE = 'w';
123: const ACL_INSERT = 'i';
124: const ACL_POST = 'p';
125: const ACL_CREATEMBOX = 'k';
126: const ACL_DELETEMBOX = 'x';
127: const ACL_DELETEMSGS = 't';
128: const ACL_EXPUNGE = 'e';
129: const ACL_ADMINISTER = 'a';
130: // Deprecated constants (RFC 2086 [3]; RFC 4314 [2.1.1])
131: const ACL_CREATE = 'c';
132: const ACL_DELETE = 'd';
133:
134: /* System flags. */
135: // RFC 3501 [2.3.2]
136: const FLAG_ANSWERED = '\\answered';
137: const FLAG_DELETED = '\\deleted';
138: const FLAG_DRAFT = '\\draft';
139: const FLAG_FLAGGED = '\\flagged';
140: const FLAG_RECENT = '\\recent';
141: const FLAG_SEEN = '\\seen';
142: // RFC 3503 [3.3]
143: const FLAG_MDNSENT = '$mdnsent';
144: // RFC 5550 [2.8]
145: const FLAG_FORWARDED = '$forwarded';
146: // RFC 5788 registered keywords:
147: // http://www.ietf.org/mail-archive/web/morg/current/msg00441.html
148: const FLAG_JUNK = '$junk';
149: const FLAG_NOTJUNK = '$notjunk';
150:
151: /* Special-use mailbox attributes (RFC 6154 [2]). */
152: const SPECIALUSE_ALL = '\\All';
153: const SPECIALUSE_ARCHIVE = '\\Archive';
154: const SPECIALUSE_DRAFTS = '\\Drafts';
155: const SPECIALUSE_FLAGGED = '\\Flagged';
156: const SPECIALUSE_JUNK = '\\Junk';
157: const SPECIALUSE_SENT = '\\Sent';
158: const SPECIALUSE_TRASH = '\\Trash';
159:
160: /* Debugging constants. */
161: const DEBUG_RAW = 0;
162: const DEBUG_CLIENT = 1;
163: const DEBUG_INFO = 2;
164: const DEBUG_SERVER = 3;
165: // Time, in seconds, for a slow command.
166: const SLOW_COMMAND = 1;
167:
168: /**
169: * Capability dependencies.
170: *
171: * @var array
172: */
173: static public $capability_deps = array(
174: // RFC 5162 [1]
175: 'QRESYNC' => array(
176: // QRESYNC requires CONDSTORE, but the latter is implied and is
177: // not required to be listed.
178: 'ENABLE'
179: ),
180: // RFC 5182 [2.1]
181: 'SEARCHRES' => array(
182: 'ESEARCH'
183: ),
184: // RFC 5255 [3.1]
185: 'LANGUAGE' => array(
186: 'NAMESPACE'
187: ),
188: // RFC 5957 [1]
189: 'SORT=DISPLAY' => array(
190: 'SORT'
191: )
192: );
193:
194: /**
195: * Attempts to return a concrete Horde_Imap_Client instance based on
196: * $driver.
197: *
198: * @param string $driver The type of concrete subclass to return.
199: * @param array $params Configuration parameters:
200: * <ul>
201: * <li>REQUIRED Parameters
202: * <ul>
203: * <li>password: (string) The IMAP user password.</li>
204: * <li>username: (string) The IMAP username.</li>
205: * </ul>
206: * </li>
207: * <li>Optional Parameters
208: * <ul>
209: * <li>
210: * cache: (array) If set, caches data from fetch(), search(), and
211: * thread() calls. Requires the horde/Cache package to be
212: * installed. The array can contain the following keys (see
213: * Horde_Imap_Client_Cache for default values):
214: * <ul>
215: * <li>
216: * cacheob: [REQUIRED] (Horde_Cache) The cache object to
217: * use.
218: * </li>
219: * <li>
220: * fetch_ignore: (array) A list of mailboxes to ignore when storing
221: * fetch data.
222: * </li>
223: * <li>
224: * fields: (array) The fetch criteria to cache. If not defined, all
225: * cacheable data is cached. The following is a list of
226: * criteria that can be cached:
227: * <ul>
228: * <li>Horde_Imap_Client::FETCH_ENVELOPE</li>
229: * <li>Horde_Imap_Client::FETCH_FLAGS
230: * <ul>
231: * <li>
232: * Only if server supports CONDSTORE extension
233: * </li>
234: * </ul>
235: * </li>
236: * <li>Horde_Imap_Client::FETCH_HEADERS
237: * <ul>
238: * <li>
239: * Only for queries that specifically request caching
240: * </li>
241: * </ul>
242: * </li>
243: * <li>Horde_Imap_Client::FETCH_IMAPDATE</li>
244: * <li>Horde_Imap_Client::FETCH_SIZE</li>
245: * <li>Horde_Imap_Client::FETCH_STRUCTURE</li>
246: * </ul>
247: * </li>
248: * <li>
249: * lifetime: (integer) Lifetime of the cache data (in seconds).
250: * </li>
251: * <li>
252: * slicesize: (integer) The slicesize to use.
253: * </li>
254: * </ul>
255: * </li>
256: * <li>
257: * capability_ignore: (array) A list of IMAP capabilites to ignore,
258: * even if they are supported on the server.
259: * DEFAULT: No supported capabilities are ignored.
260: * </li>
261: * <li>
262: * comparator: (string) The search comparator to use instead of the
263: * default IMAP server comparator. See
264: * Horde_Imap_Client_Base#setComparator() for format.
265: * DEFAULT: Use the server default
266: * </li>
267: * <li>
268: * debug: (string) If set, will output debug information to the stream
269: * provided. The value can be any PHP supported wrapper that
270: * can be opened via fopen().
271: * DEFAULT: No debug output
272: * </li>
273: * <li>
274: * encryptKey: (array) A callback to a function that returns the key
275: * used to encrypt the password. This function MUST be
276: * static.
277: * DEFAULT: No encryption
278: * </li>
279: * <li>
280: * hostspec: (string) The hostname or IP address of the server.
281: * DEFAULT: 'localhost'
282: * </li>
283: * <li>
284: * id: (array) Send ID information to the IMAP server (only if server
285: * supports the ID extension). An array with the keys as the
286: * fields to send and the values being the associated values. See
287: * RFC 2971 [3.3] for a list of defined standard field values.
288: * DEFAULT: No info sent to server
289: * </li>
290: * <li>
291: * lang: (array) A list of languages (in priority order) to be used to
292: * display human readable messages.
293: * DEFAULT: Messages output in IMAP server default language
294: * </li>
295: * <li>
296: * log: (array) A callback to a function that receives a single
297: * parameter: a Horde_Imap_Client_Exception object. This callback
298: * function MUST be static.
299: * DEFAULT: No logging
300: * </li>
301: * <li>
302: * port: (integer) The server port to which we will connect.
303: * DEFAULT: 143 (imap or imap w/TLS) or 993 (imaps)
304: * </li>
305: * <li>
306: * secure: (string) Use SSL or TLS to connect.
307: * VALUES:
308: * <ul>
309: * <li>false</li>
310: * <li>'ssl' (Auto-detect SSL version)</li>
311: * <li>'sslv2' (Force SSL version 2)</li>
312: * <li>'sslv3' (Force SSL version 3)</li>
313: * <li>'tls'</li>
314: * </ul>
315: * DEFAULT: No encryption</li>
316: * </li>
317: * <li>
318: * statuscache: (boolean) Cache STATUS responses?
319: * DEFAULT: False
320: * </li>
321: * <li>
322: * timeout: (integer) Connection timeout, in seconds.
323: * DEFAULT: 30 seconds
324: * </li>
325: * </ul>
326: * </li>
327: * </ul>
328: *
329: * @return Horde_Imap_Client_Base The newly created instance.
330: */
331: static public function factory($driver, $params = array())
332: {
333: $class = __CLASS__ . '_' . strtr(ucfirst(basename($driver)), '-', '_');
334:
335: // DEPRECATED driver names
336: switch ($class) {
337: case __CLASS__ . 'Cclient':
338: $class = __CLASS__ . 'Socket';
339: break;
340:
341: case __CLASS__ . 'Cclient_Pop3':
342: $class = __CLASS__ . 'Socket_Pop3';
343: break;
344: }
345:
346: if (class_exists($class)) {
347: return new $class($params);
348: }
349:
350: throw new RuntimeException('Driver ' . $driver . ' not found');
351: }
352:
353: }
354: