Browse code
imap 1.0
jkf authored on 27/09/1999 20:21:57
Showing 5 changed files
Showing 5 changed files
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,11 @@ |
1 |
+1999-09-27 John Foderaro <jkf@tiger.franz.com> |
|
2 |
+version 1.0 |
|
3 |
+ * start ChangeLog. |
|
4 |
+ * imap.cl - the code for the imap and pop interface |
|
5 |
+ * imap.html - the documentation |
|
6 |
+ * t-imap.cl - the test suite |
|
7 |
+ * rfc1939.html - pop spec |
|
8 |
+ * rfc2060.txt - imap spec |
|
9 |
+ |
|
10 |
+ |
|
11 |
+ |
... | ... |
@@ -1,8 +1,8 @@ |
1 | 1 |
;; imap protocol |
2 | 2 |
;; (with hooks for pop too) |
3 | 3 |
|
4 |
-(defpackage :mailbox |
|
5 |
- (:nicknames :mb) |
|
4 |
+(defpackage :post-office |
|
5 |
+ (:nicknames :po) |
|
6 | 6 |
(:use :lisp :excl) |
7 | 7 |
(:export |
8 | 8 |
#:address-name |
... | ... |
@@ -11,7 +11,7 @@ |
11 | 11 |
#:address-host |
12 | 12 |
|
13 | 13 |
#:alter-flags |
14 |
- #:close-imap-connection |
|
14 |
+ #:close-connection |
|
15 | 15 |
#:close-mailbox |
16 | 16 |
#:copy-to-mailbox |
17 | 17 |
#:create-mailbox |
... | ... |
@@ -32,6 +32,8 @@ |
32 | 32 |
#:expunge-mailbox |
33 | 33 |
#:fetch-field |
34 | 34 |
#:fetch-letter |
35 |
+ #:fetch-parts |
|
36 |
+ #:*imap-version-number* |
|
35 | 37 |
#:mailbox-flags ; accessor |
36 | 38 |
#:mailbox-permanent-flags ; acc |
37 | 39 |
#:mailbox-list |
... | ... |
@@ -43,6 +45,7 @@ |
43 | 45 |
#:mailbox-separator ; accessor |
44 | 46 |
#:mailbox-uidvalidity |
45 | 47 |
#:make-imap-connection |
48 |
+ #:make-pop-connection |
|
46 | 49 |
#:noop |
47 | 50 |
#:rename-mailbox |
48 | 51 |
#:search-mailbox |
... | ... |
@@ -50,41 +53,26 @@ |
50 | 53 |
) |
51 | 54 |
) |
52 | 55 |
|
53 |
-(in-package :mailbox) |
|
54 |
- |
|
55 |
-; kinds of things that come back from the server |
|
56 |
-; <tag> OK random text |
|
57 |
-; <tag> OK [atom] random text |
|
58 |
-; <tag> OK [atom value] random text |
|
59 |
-; * <number> atom random text |
|
60 |
-; * LIST (atom ...) string string |
|
61 |
-; * STATUS mboxname (atom value .... ...) |
|
62 |
-; * CAPABILITY atom ... |
|
63 |
- |
|
64 |
-; our parsing will return |
|
65 |
-; tag |
|
66 |
-; a string or :untagged or :continue |
|
67 |
-; command |
|
68 |
-; the string like "OK" which describes what this response is saying |
|
69 |
-; args |
|
70 |
-; list of arguments. |
|
71 |
-; |
|
56 |
+(in-package :post-office) |
|
57 |
+ |
|
58 |
+ |
|
59 |
+(defparameter *imap-version-number* '(:major 1 :minor 0)) ; major.minor |
|
72 | 60 |
|
73 | 61 |
(defvar *debug-imap* nil) |
74 | 62 |
|
75 | 63 |
|
76 |
-(defclass mailbox () |
|
64 |
+(defclass post-office () |
|
77 | 65 |
((socket :initarg :socket |
78 |
- :accessor mailbox-socket) |
|
66 |
+ :accessor post-office-socket) |
|
79 | 67 |
|
80 | 68 |
(host :initarg :host |
81 |
- :accessor mailbox-host |
|
69 |
+ :accessor post-office-host |
|
82 | 70 |
:initform nil) |
83 | 71 |
(user :initarg :user |
84 |
- :accessor mailbox-user |
|
72 |
+ :accessor post-office-user |
|
85 | 73 |
:initform nil) |
86 | 74 |
|
87 |
- (state :accessor mailbox-state |
|
75 |
+ (state :accessor post-office-state |
|
88 | 76 |
:initarg :state |
89 | 77 |
:initform :unconnected) |
90 | 78 |
|
... | ... |
@@ -96,7 +84,7 @@ |
96 | 84 |
:accessor timeout) |
97 | 85 |
)) |
98 | 86 |
|
99 |
-(defclass imap-mailbox (mailbox) |
|
87 |
+(defclass imap-mailbox (post-office) |
|
100 | 88 |
((mailbox-name ; currently selected mailbox |
101 | 89 |
:accessor mailbox-name |
102 | 90 |
:initform nil) |
... | ... |
@@ -136,13 +124,15 @@ |
136 | 124 |
:accessor first-unseen |
137 | 125 |
:initform 0) |
138 | 126 |
|
139 |
- ;;; end list of values for the currently selected maibox |
|
127 |
+ ;;; end list of values for the currently selected mailbox |
|
140 | 128 |
) |
141 | 129 |
) |
142 | 130 |
|
143 | 131 |
|
144 |
-(defclass pop-mailbox (mailbox) |
|
145 |
- ()) |
|
132 |
+(defclass pop-mailbox (post-office) |
|
133 |
+ ((message-count ; how many in the mailbox |
|
134 |
+ :accessor mailbox-message-count |
|
135 |
+ :initform 0))) |
|
146 | 136 |
|
147 | 137 |
|
148 | 138 |
|
... | ... |
@@ -222,9 +212,9 @@ |
222 | 212 |
imap)) |
223 | 213 |
|
224 | 214 |
|
225 |
-(defmethod close-imap-connection ((mb imap-mailbox)) |
|
215 |
+(defmethod close-connection ((mb imap-mailbox)) |
|
226 | 216 |
|
227 |
- (let ((sock (mailbox-socket mb))) |
|
217 |
+ (let ((sock (post-office-socket mb))) |
|
228 | 218 |
(if* sock |
229 | 219 |
then (ignore-errors |
230 | 220 |
(send-command-get-results |
... | ... |
@@ -238,20 +228,62 @@ |
238 | 228 |
#'(lambda (mb command count extra) |
239 | 229 |
(check-for-success mb command count extra |
240 | 230 |
"logout"))))) |
241 |
- (setf (mailbox-socket mb) nil) |
|
231 |
+ (setf (post-office-socket mb) nil) |
|
232 |
+ (if* sock then (ignore-errors (close sock))) |
|
233 |
+ t)) |
|
234 |
+ |
|
235 |
+ |
|
236 |
+(defmethod close-connection ((pb pop-mailbox)) |
|
237 |
+ (let ((sock (post-office-socket pb))) |
|
238 |
+ (if* sock |
|
239 |
+ then (ignore-errors |
|
240 |
+ (send-pop-command-get-results |
|
241 |
+ pb |
|
242 |
+ "QUIT"))) |
|
243 |
+ (setf (post-office-socket pb) nil) |
|
242 | 244 |
(if* sock then (ignore-errors (close sock))) |
243 | 245 |
t)) |
244 | 246 |
|
245 | 247 |
|
248 |
+ |
|
249 |
+(defun make-pop-connection (host &key (port 110) |
|
250 |
+ user |
|
251 |
+ password |
|
252 |
+ (timeout 30)) |
|
253 |
+ (let* ((sock (socket:make-socket :remote-host host |
|
254 |
+ :remote-port port)) |
|
255 |
+ (pop (make-instance 'pop-mailbox |
|
256 |
+ :socket sock |
|
257 |
+ :host host |
|
258 |
+ :timeout timeout |
|
259 |
+ :state :unauthorized))) |
|
260 |
+ |
|
261 |
+ (multiple-value-bind (result) |
|
262 |
+ (get-and-parse-from-pop-server pop) |
|
263 |
+ (if* (not (eq :ok result)) |
|
264 |
+ then (error "unexpected line from server after connect"))) |
|
265 |
+ |
|
266 |
+ ; now login |
|
267 |
+ (send-pop-command-get-results pop (format nil "user ~a" user)) |
|
268 |
+ (send-pop-command-get-results pop (format nil "pass ~a" password)) |
|
269 |
+ |
|
270 |
+ (let ((res (send-pop-command-get-results pop "stat"))) |
|
271 |
+ (setf (mailbox-message-count pop) (car res))) |
|
272 |
+ |
|
273 |
+ |
|
274 |
+ |
|
275 |
+ pop)) |
|
276 |
+ |
|
277 |
+ |
|
246 | 278 |
(defmethod send-command-get-results ((mb imap-mailbox) |
247 | 279 |
command untagged-handler tagged-handler) |
248 | 280 |
;; send a command and retrieve results until we get the tagged |
249 | 281 |
;; response for the command we sent |
250 | 282 |
;; |
251 | 283 |
(let ((tag (get-next-tag))) |
252 |
- (format (mailbox-socket mb) |
|
284 |
+ (format (post-office-socket mb) |
|
253 | 285 |
"~a ~a~a" tag command *crlf*) |
254 |
- (force-output (mailbox-socket mb)) |
|
286 |
+ (force-output (post-office-socket mb)) |
|
255 | 287 |
|
256 | 288 |
(if* *debug-imap* |
257 | 289 |
then (format t |
... | ... |
@@ -284,7 +316,7 @@ |
284 | 316 |
(:recent (setf (mailbox-recent-messages mb) count)) |
285 | 317 |
(:flags (setf (mailbox-flags mb) (mapcar #'kwd-intern extra))) |
286 | 318 |
(:bye ; occurs when connection times out or mailbox lock is stolen |
287 |
- (ignore-errors (close (mailbox-socket mb))) |
|
319 |
+ (ignore-errors (close (post-office-socket mb))) |
|
288 | 320 |
(error "connection to the imap server was closed by the server")) |
289 | 321 |
(:no ; used when grabbing a lock from another process |
290 | 322 |
(warn "grabbing mailbox lock from another process")) |
... | ... |
@@ -304,6 +336,69 @@ |
304 | 336 |
|
305 | 337 |
) |
306 | 338 |
|
339 |
+ |
|
340 |
+ |
|
341 |
+(defun send-pop-command-get-results (pop command &optional extrap) |
|
342 |
+ ;; if extrap is true then we're expecting data to follow an +ok |
|
343 |
+ (format (post-office-socket pop) "~a~a" command *crlf*) |
|
344 |
+ (force-output (post-office-socket pop)) |
|
345 |
+ |
|
346 |
+ (if* *debug-imap* |
|
347 |
+ then (format t "~a~a" command *crlf*) |
|
348 |
+ (force-output t)) |
|
349 |
+ |
|
350 |
+ (multiple-value-bind (result parsed line) |
|
351 |
+ (get-and-parse-from-pop-server pop) |
|
352 |
+ (if* (not (eq result :ok)) |
|
353 |
+ then (error "error from pop server: ~a" line)) |
|
354 |
+ |
|
355 |
+ (if* extrap |
|
356 |
+ then ; get the rest of the data |
|
357 |
+ |
|
358 |
+ (let ((buf (get-line-buffer (+ (car parsed) 50))) |
|
359 |
+ (pos 0) |
|
360 |
+ ; states |
|
361 |
+ ; 1 - after lf |
|
362 |
+ ; 2 - seen dot at beginning of line |
|
363 |
+ ; 3 - seen regular char on line |
|
364 |
+ (state 1) |
|
365 |
+ (sock (post-office-socket pop))) |
|
366 |
+ (flet ((add-to-buffer (ch) |
|
367 |
+ (if* (>= pos (length buf)) |
|
368 |
+ then (error "missinfomation from pop") |
|
369 |
+ else (setf (schar buf pos) ch) |
|
370 |
+ (incf pos)))) |
|
371 |
+ (loop |
|
372 |
+ (let ((ch (read-char sock nil nil))) |
|
373 |
+ (if* (null ch) |
|
374 |
+ then (error "premature end of file from server")) |
|
375 |
+ (if* (eq ch #\return) |
|
376 |
+ thenret ; ignore crs |
|
377 |
+ else (case state |
|
378 |
+ (1 (if* (eq ch #\.) |
|
379 |
+ then (setq state 2) |
|
380 |
+ elseif (eq ch #\linefeed) |
|
381 |
+ then (add-to-buffer ch) |
|
382 |
+ ; state stays at 1 |
|
383 |
+ else (add-to-buffer ch) |
|
384 |
+ (setq state 3))) |
|
385 |
+ (2 ; seen first dot |
|
386 |
+ (if* (eq ch #\linefeed) |
|
387 |
+ then ; end of message |
|
388 |
+ (return) |
|
389 |
+ else (add-to-buffer ch) |
|
390 |
+ (setq state 3))) |
|
391 |
+ (3 ; normal reading |
|
392 |
+ (add-to-buffer ch) |
|
393 |
+ (if* (eq ch #\linefeed) |
|
394 |
+ then (setq state 1)))))))) |
|
395 |
+ (prog1 (subseq buf 0 pos) |
|
396 |
+ (free-line-buffer buf))) |
|
397 |
+ else parsed))) |
|
398 |
+ |
|
399 |
+ |
|
400 |
+ |
|
401 |
+ |
|
307 | 402 |
(defun convert-flags-plist (plist) |
308 | 403 |
;; scan the plist looking for "flags" indicators and |
309 | 404 |
;; turn value into a list of symbols rather than strings |
... | ... |
@@ -313,8 +408,8 @@ |
313 | 408 |
then (setf (cadr xx) (mapcar #'kwd-intern (cadr xx)))))) |
314 | 409 |
|
315 | 410 |
|
316 |
-(defun select-mailbox (mb name) |
|
317 |
- ;; select the given maibox |
|
411 |
+(defmethod select-mailbox ((mb imap-mailbox) name) |
|
412 |
+ ;; select the given mailbox |
|
318 | 413 |
(send-command-get-results mb |
319 | 414 |
(format nil "select ~a" name) |
320 | 415 |
#'handle-untagged-response |
... | ... |
@@ -327,8 +422,21 @@ |
327 | 422 |
) |
328 | 423 |
|
329 | 424 |
|
425 |
+(defmethod fetch-letter ((mb imap-mailbox) number &key uid) |
|
426 |
+ ;; return the whole letter |
|
427 |
+ (fetch-field number "body[]" |
|
428 |
+ (fetch-parts mb number "body[]" :uid uid) |
|
429 |
+ :uid uid)) |
|
330 | 430 |
|
331 |
-(defun fetch-letter (mb number parts &key uid) |
|
431 |
+ |
|
432 |
+(defmethod fetch-letter ((pb pop-mailbox) number &key uid) |
|
433 |
+ (declare (ignore uid)) |
|
434 |
+ (send-pop-command-get-results pb |
|
435 |
+ (format nil "RETR ~d" number) |
|
436 |
+ t ; extra stuff |
|
437 |
+ )) |
|
438 |
+ |
|
439 |
+(defmethod fetch-parts ((mb imap-mailbox) number parts &key uid) |
|
332 | 440 |
(let (res) |
333 | 441 |
(send-command-get-results |
334 | 442 |
mb |
... | ... |
@@ -394,15 +502,42 @@ |
394 | 502 |
|
395 | 503 |
|
396 | 504 |
|
397 |
-(defun delete-letter (mb messages &key (expunge t) uid) |
|
505 |
+(defmethod delete-letter ((mb imap-mailbox) messages &key (expunge t) uid) |
|
398 | 506 |
;; delete all the mesasges and do the expunge to make |
399 | 507 |
;; it permanent if expunge is true |
400 | 508 |
(alter-flags mb messages :add-flags :\\deleted :uid uid) |
401 | 509 |
(if* expunge then (expunge-mailbox mb))) |
510 |
+ |
|
511 |
+(defmethod delete-letter ((pb pop-mailbox) messages &key (expunge nil) uid) |
|
512 |
+ ;; delete all the messages. We can't expunge without quitting so |
|
513 |
+ ;; we don't expunge |
|
514 |
+ (declare (ignore expunge uid)) |
|
515 |
+ |
|
516 |
+ (if* (or (numberp messages) |
|
517 |
+ (and (consp messages) (eq :seq (car messages)))) |
|
518 |
+ then (setq messages (list messages))) |
|
519 |
+ |
|
520 |
+ (if* (not (consp messages)) |
|
521 |
+ then (error "expect a mesage number or list of messages, not ~s" |
|
522 |
+ messages)) |
|
523 |
+ |
|
524 |
+ (dolist (message messages) |
|
525 |
+ (if* (numberp message) |
|
526 |
+ then (send-pop-command-get-results pb |
|
527 |
+ (format nil "DELE ~d" message)) |
|
528 |
+ elseif (and (consp message) (eq :seq (car message))) |
|
529 |
+ then (do ((start (cadr message) (1+ start)) |
|
530 |
+ (end (caddr message))) |
|
531 |
+ ((> start end)) |
|
532 |
+ (send-pop-command-get-results pb |
|
533 |
+ (format nil "DELE ~d" start))) |
|
534 |
+ else (error "bad message number ~s" message)))) |
|
535 |
+ |
|
536 |
+ |
|
402 | 537 |
|
403 | 538 |
|
404 | 539 |
|
405 |
-(defun noop (mb) |
|
540 |
+(defmethod noop ((mb imap-mailbox)) |
|
406 | 541 |
;; just poke the server... keeping it awake and checking for |
407 | 542 |
;; new letters |
408 | 543 |
(send-command-get-results mb |
... | ... |
@@ -414,6 +549,13 @@ |
414 | 549 |
"noop")))) |
415 | 550 |
|
416 | 551 |
|
552 |
+(defmethod noop ((pb pop-mailbox)) |
|
553 |
+ ;; send the stat command instead so we can update the message count |
|
554 |
+ (let ((res (send-pop-command-get-results pb "stat"))) |
|
555 |
+ (setf (mailbox-message-count pb) (car res))) |
|
556 |
+ ) |
|
557 |
+ |
|
558 |
+ |
|
417 | 559 |
(defun check-for-success (mb command count extra command-string) |
418 | 560 |
(declare (ignore mb count extra)) |
419 | 561 |
(if* (not (eq command :ok)) |
... | ... |
@@ -423,7 +565,7 @@ |
423 | 565 |
|
424 | 566 |
|
425 | 567 |
|
426 |
-(defun mailbox-list (mb &key (reference "") (pattern "")) |
|
568 |
+(defmethod mailbox-list ((mb imap-mailbox) &key (reference "") (pattern "")) |
|
427 | 569 |
;; return a list of mailbox names with respect to a given |
428 | 570 |
(let (res) |
429 | 571 |
(send-command-get-results mb |
... | ... |
@@ -447,7 +589,7 @@ |
447 | 589 |
)) |
448 | 590 |
|
449 | 591 |
|
450 |
-(defun create-mailbox (mb mailbox-name) |
|
592 |
+(defmethod create-mailbox ((mb imap-mailbox) mailbox-name) |
|
451 | 593 |
;; create a mailbox name of the given name. |
452 | 594 |
;; use mailbox-separator if you want to create a hierarchy |
453 | 595 |
(send-command-get-results mb |
... | ... |
@@ -459,7 +601,7 @@ |
459 | 601 |
t) |
460 | 602 |
|
461 | 603 |
|
462 |
-(defun delete-mailbox (mb mailbox-name) |
|
604 |
+(defmethod delete-mailbox ((mb imap-mailbox) mailbox-name) |
|
463 | 605 |
;; create a mailbox name of the given name. |
464 | 606 |
;; use mailbox-separator if you want to create a hierarchy |
465 | 607 |
(send-command-get-results mb |
... | ... |
@@ -469,7 +611,7 @@ |
469 | 611 |
(check-for-success |
470 | 612 |
mb command count extra "delete")))) |
471 | 613 |
|
472 |
-(defun rename-mailbox (mb old-mailbox-name new-mailbox-name) |
|
614 |
+(defmethod rename-mailbox ((mb imap-mailbox) old-mailbox-name new-mailbox-name) |
|
473 | 615 |
;; create a mailbox name of the given name. |
474 | 616 |
;; use mailbox-separator if you want to create a hierarchy |
475 | 617 |
(send-command-get-results mb |
... | ... |
@@ -483,7 +625,9 @@ |
483 | 625 |
|
484 | 626 |
|
485 | 627 |
|
486 |
-(defun alter-flags (mb messages &key (flags nil flags-p) add-flags remove-flags |
|
628 |
+(defmethod alter-flags ((mb imap-mailbox) |
|
629 |
+ messages &key (flags nil flags-p) |
|
630 |
+ add-flags remove-flags |
|
487 | 631 |
silent uid) |
488 | 632 |
;; |
489 | 633 |
;; change the flags using the store command |
... | ... |
@@ -598,7 +742,7 @@ |
598 | 742 |
|
599 | 743 |
;; search command |
600 | 744 |
|
601 |
-(defun search-mailbox (mb search-expression &key uid) |
|
745 |
+(defmethod search-mailbox ((mb imap-mailbox) search-expression &key uid) |
|
602 | 746 |
(let (res) |
603 | 747 |
(send-command-get-results mb |
604 | 748 |
(format nil "~asearch ~a" |
... | ... |
@@ -816,6 +960,22 @@ |
816 | 960 |
)) |
817 | 961 |
|
818 | 962 |
|
963 |
+ |
|
964 |
+(defmethod get-and-parse-from-pop-server ((mb pop-mailbox)) |
|
965 |
+ ;; read the next line from the pop server |
|
966 |
+ ;; return the result of parsing it |
|
967 |
+ (multiple-value-bind (line count) |
|
968 |
+ (get-line-from-server mb) |
|
969 |
+ |
|
970 |
+ (if* *debug-imap* |
|
971 |
+ then (format t "from server: " count) |
|
972 |
+ (dotimes (i count)(write-char (schar line i))) |
|
973 |
+ (terpri)) |
|
974 |
+ |
|
975 |
+ (parse-pop-response line count))) |
|
976 |
+ |
|
977 |
+ |
|
978 |
+ |
|
819 | 979 |
;; Parse and return the data from each line |
820 | 980 |
;; values returned |
821 | 981 |
;; tag -- either a string or the symbol :untagged |
... | ... |
@@ -911,7 +1071,42 @@ |
911 | 1071 |
(values kind nil next)) |
912 | 1072 |
(t (error "bad sexpression"))))) |
913 | 1073 |
|
1074 |
+ |
|
1075 |
+(defun parse-pop-response (line end) |
|
1076 |
+ ;; return values: |
|
1077 |
+ ;; :ok or :error |
|
1078 |
+ ;; a list of rest of the tokens on the line |
|
1079 |
+ ;; the whole line after the +ok or -err |
|
1080 |
+ ;; |
|
1081 |
+ (let (res lineres result) |
|
1082 |
+ (multiple-value-bind (kind value next) |
|
1083 |
+ (get-next-token line 0 end) |
|
1084 |
+ |
|
1085 |
+ (case kind |
|
1086 |
+ (:string (setq result (if* (equal "+OK" value) |
|
1087 |
+ then :ok |
|
1088 |
+ else :error))) |
|
1089 |
+ (t (error "bad response from server: ~s" (subseq line 0 end)))) |
|
914 | 1090 |
|
1091 |
+ (setq lineres (subseq line next end)) |
|
1092 |
+ |
|
1093 |
+ (loop |
|
1094 |
+ (multiple-value-setq (kind value next) |
|
1095 |
+ (get-next-token line next end)) |
|
1096 |
+ |
|
1097 |
+ (case kind |
|
1098 |
+ (:eof (return)) |
|
1099 |
+ ((:string :number) (push value res)))) |
|
1100 |
+ |
|
1101 |
+ (values result (nreverse res) lineres)))) |
|
1102 |
+ |
|
1103 |
+ |
|
1104 |
+ |
|
1105 |
+ |
|
1106 |
+ |
|
1107 |
+ |
|
1108 |
+ |
|
1109 |
+ |
|
915 | 1110 |
|
916 | 1111 |
|
917 | 1112 |
(defparameter *char-to-kind* |
... | ... |
@@ -1074,7 +1269,7 @@ |
1074 | 1269 |
(let* ((buff (get-line-buffer 0)) |
1075 | 1270 |
(len (length buff)) |
1076 | 1271 |
(i 0) |
1077 |
- (p (mailbox-socket mailbox)) |
|
1272 |
+ (p (post-office-socket mailbox)) |
|
1078 | 1273 |
(ch nil) |
1079 | 1274 |
(whole-count) |
1080 | 1275 |
) |
... | ... |
@@ -1181,7 +1376,7 @@ |
1181 | 1376 |
;; like lisp likes). |
1182 | 1377 |
;; |
1183 | 1378 |
(let ((buff (get-line-buffer count)) |
1184 |
- (p (mailbox-socket mb)) |
|
1379 |
+ (p (post-office-socket mb)) |
|
1185 | 1380 |
(ind 0)) |
1186 | 1381 |
(mp:with-timeout ((timeout mb) |
1187 | 1382 |
(error "imap server timed out")) |
... | ... |
@@ -1,13 +1,13 @@ |
1 | 1 |
<html> |
2 | 2 |
|
3 | 3 |
<head> |
4 |
-<title>Allegro CL imap interface</title> |
|
4 |
+<title>Allegro CL imap and pop interface</title> |
|
5 | 5 |
<meta name="GENERATOR" content="Microsoft FrontPage 3.0"> |
6 | 6 |
</head> |
7 | 7 |
|
8 | 8 |
<body> |
9 | 9 |
|
10 |
-<h1 align="center">Allegro CL imap interface</h1> |
|
10 |
+<h1 align="center">Allegro CL imap and pop interface</h1> |
|
11 | 11 |
|
12 | 12 |
<p align="left">copyright (c) 1999 Franz Inc.</p> |
13 | 13 |
|
... | ... |
@@ -15,11 +15,14 @@ |
15 | 15 |
|
16 | 16 |
<p align="left"><strong>imap</strong> is a client-server protocol for processing |
17 | 17 |
electronic mail boxes. <strong>imap </strong>is the successor to the <strong>pop</strong> |
18 |
-protocol. It is not an upward compatible successor.</p> |
|
18 |
+protocol. It is <strong>not</strong> an upward compatible successor. |
|
19 |
+ The main focus of this document is the <strong>imap</strong> |
|
20 |
+protocol. Only one small section describes the functions in the <strong>pop</strong> |
|
21 |
+interface.</p> |
|
19 | 22 |
|
20 | 23 |
<p align="left">This document and interface is based on the Imap4rev1 protocol described |
21 | 24 |
in rfc2060. Where this document is describing the actions of the imap commands |
22 |
-it should be considered a secondary source of information about those command and rfc2060 |
|
25 |
+it should be considered a secondary source of information about those commands and rfc2060 |
|
23 | 26 |
should be considered the primary source.</p> |
24 | 27 |
|
25 | 28 |
<p align="left">The advantages of <strong>imap</strong> over <strong>pop</strong> are:</p> |
... | ... |
@@ -46,6 +49,13 @@ should be considered the primary source.</p> |
46 | 49 |
|
47 | 50 |
<p align="left"> </p> |
48 | 51 |
|
52 |
+<h1 align="left">Package</h1> |
|
53 |
+ |
|
54 |
+<p align="left">The functions in this interface are defined in the <strong>post-office</strong> |
|
55 |
+package which has a nickname <strong>po</strong>.</p> |
|
56 |
+ |
|
57 |
+<p align="left"> </p> |
|
58 |
+ |
|
49 | 59 |
<h1 align="left">Mailboxes</h1> |
50 | 60 |
|
51 | 61 |
<p align="left">Mailboxes are repositories for messages. Mailboxes are named |
... | ... |
@@ -144,7 +154,7 @@ select a mailbox using <strong>select-mailbox</strong> shortly after connecting. |
144 | 154 |
|
145 | 155 |
<p align="left"> </p> |
146 | 156 |
|
147 |
-<p align="left"><strong><font face="Courier New">(close-imap-connection mailbox)</font></strong></p> |
|
157 |
+<p align="left"><strong><font face="Courier New">(close-connection mailbox)</font></strong></p> |
|
148 | 158 |
|
149 | 159 |
<p align="left">This sends a <strong>logout</strong> command to the <strong>imap</strong> |
150 | 160 |
server and then closes the socket that's communicating with the <strong>imap</strong> |
... | ... |
@@ -324,20 +334,29 @@ string just as used in the call to <strong>fetch-letter</strong>.</p> |
324 | 334 |
|
325 | 335 |
<p align="left"> </p> |
326 | 336 |
|
327 |
-<p align="left"><font face="Courier New"><strong>(fetch-letter mailbox messages parts |
|
337 |
+<p align="left"><strong><font face="Courier New">(fetch-letter mailbox message &key |
|
338 |
+uid)</font></strong></p> |
|
339 |
+ |
|
340 |
+<p align="left">Return the complete message, headers and body, as one big string. |
|
341 |
+This is a combination of <strong>fetch-field</strong> and <strong>fetch-parts</strong> |
|
342 |
+where the part specification is "body[]".</p> |
|
343 |
+ |
|
344 |
+<p align="left"> </p> |
|
345 |
+ |
|
346 |
+<p align="left"><font face="Courier New"><strong>(fetch-parts mailbox messages parts |
|
328 | 347 |
&key uid)</strong></font></p> |
329 | 348 |
|
330 | 349 |
<p align="left">retrieves the specified <strong>parts</strong> of the specified <strong>messages. |
331 | 350 |
</strong>If <strong>uid</strong> is true then the <strong>messages</strong> |
332 | 351 |
are considered to be unique ids rather than message sequence numbers. |
333 | 352 |
The description of what can be specified for <strong>parts </strong>is |
334 |
-quite complex and has been moved to the section below "Fetching a Letter".</p> |
|
353 |
+quite complex and is described in the section below "Fetching a Letter".</p> |
|
335 | 354 |
|
336 | 355 |
<p align="left">The return value from this function is a structure that can be examined |
337 | 356 |
with <strong>fetch-field</strong>.</p> |
338 | 357 |
|
339 | 358 |
<p align="left">When the result returned includes an envelope value the following |
340 |
-functions can be used to extract the parts of the envelope:</p> |
|
359 |
+functions can be used to extract the components of the envelope:</p> |
|
341 | 360 |
|
342 | 361 |
<ul> |
343 | 362 |
<li><p align="left"><font face="Courier New"><strong>envelope-date</strong></font></p> |
... | ... |
@@ -443,7 +462,7 @@ next message.</p> |
443 | 462 |
|
444 | 463 |
<h1 align="left">Fetching a Letter</h1> |
445 | 464 |
|
446 |
-<p align="left">When using <strong>fetch-letter</strong> to access letters, you must |
|
465 |
+<p align="left">When using <strong>fetch-parts</strong> to access letters, you must |
|
447 | 466 |
specify the parts of the messages in which you're interested. There are a wide |
448 | 467 |
variety of specifiers, some redundant and overlapping, described in the imap specification |
449 | 468 |
in rfe2060. We'll describe the most common ones here. The specification |
... | ... |
@@ -454,7 +473,8 @@ the string, e.g. "(flags envelope)". </p> |
454 | 473 |
|
455 | 474 |
<ul> |
456 | 475 |
<li><p align="left"><strong>body[]</strong> - this returns the full message: headers and |
457 |
- body.</p> |
|
476 |
+ body. You can use <strong>fetch-letter</strong> if you only want this part and |
|
477 |
+ you want to avoid having to call <strong>fetch-field</strong>.</p> |
|
458 | 478 |
</li> |
459 | 479 |
<li><p align="left"><strong>body[text]</strong> - this returns just the the text of the body |
460 | 480 |
of the message, not the header.</p> |
... | ... |
@@ -474,7 +494,7 @@ the string, e.g. "(flags envelope)". </p> |
474 | 494 |
|
475 | 495 |
<p align="left"> </p> |
476 | 496 |
|
477 |
-<p align="left">The result of a <strong>fetch-letter</strong> is a data structure |
|
497 |
+<p align="left">The result of a <strong>fetch-parts</strong> is a data structure |
|
478 | 498 |
containing all of the requested information. The <strong>fetch-field</strong> |
479 | 499 |
function is then used to extract the particular information for the particular message.</p> |
480 | 500 |
|
... | ... |
@@ -606,7 +626,7 @@ these forms:</p> |
606 | 626 |
<p align="left"><strong>Connect to the imap server on the machine holding the email:</strong></p> |
607 | 627 |
<div align="left"> |
608 | 628 |
|
609 |
-<pre>user(2): (setq mb (mb:make-imap-connection "mailmachine.franz.com" |
|
629 |
+<pre>user(2): (setq mb (po:make-imap-connection "mailmachine.franz.com" |
|
610 | 630 |
:user "myacct" |
611 | 631 |
:password "mypasswd")) |
612 | 632 |
#<mailbox::imap-mailbox @ #x2064ca4a></pre> |
... | ... |
@@ -618,7 +638,7 @@ these forms:</p> |
618 | 638 |
<div align="left"> |
619 | 639 |
|
620 | 640 |
<pre> |
621 |
-user(3): (mb:select-mailbox mb "inbox") |
|
641 |
+user(3): (po:select-mailbox mb "inbox") |
|
622 | 642 |
t</pre> |
623 | 643 |
</div> |
624 | 644 |
|
... | ... |
@@ -628,16 +648,17 @@ t</pre> |
628 | 648 |
<div align="left"> |
629 | 649 |
|
630 | 650 |
<pre> |
631 |
-user(4): (mb:mailbox-message-count mb) |
|
651 |
+user(4): (po:mailbox-message-count mb) |
|
632 | 652 |
7</pre> |
633 | 653 |
</div> |
634 | 654 |
|
635 | 655 |
<p align="left"><strong>There are seven messages at the moment. Fetch the |
636 |
-whole 4th message</strong></p> |
|
656 |
+whole 4th message. We could call (po:fetch-letter mb 4) here instead and then not |
|
657 |
+have to call fetch-field later.</strong></p> |
|
637 | 658 |
<div align="left"> |
638 | 659 |
|
639 | 660 |
<pre> |
640 |
-user(5): (setq body (mb:fetch-letter mb 4 "body[]")) |
|
661 |
+user(5): (setq body (po:fetch-parts mb 4 "body[]")) |
|
641 | 662 |
((4 |
642 | 663 |
("BODY[]" "Return-Path: <jkfmail@tiger.franz.com> |
643 | 664 |
Received: from tiger.franz.com (jkf@tiger [192.132.95.103]) |
... | ... |
@@ -657,7 +678,7 @@ information we want we use fetch-field:</strong></p> |
657 | 678 |
<div align="left"> |
658 | 679 |
|
659 | 680 |
<pre> |
660 |
-user(6): (mb:fetch-field 4 "body[]" body) |
|
681 |
+user(6): (po:fetch-field 4 "body[]" body) |
|
661 | 682 |
"Return-Path: <jkfmail@tiger.franz.com> |
662 | 683 |
Received: from tiger.franz.com (jkf@tiger [192.132.95.103]) |
663 | 684 |
by tiger.franz.com (8.8.7/8.8.7) with SMTP id LAA20261 |
... | ... |
@@ -676,9 +697,9 @@ that message.</strong></p> |
676 | 697 |
<div align="left"> |
677 | 698 |
|
678 | 699 |
<pre> |
679 |
-user(7): (mb:search-mailbox mb '(:text "blitzfig")) |
|
700 |
+user(7): (po:search-mailbox mb '(:text "blitzfig")) |
|
680 | 701 |
(7) |
681 |
-user(8): (mb:fetch-field 7 "body[]" (mb:fetch-letter mb 7 "body[]")) |
|
702 |
+user(8): (po:fetch-field 7 "body[]" (po:fetch-letter mb 7 "body[]")) |
|
682 | 703 |
"Return-Path: <jkf@verada.com> |
683 | 704 |
Received: from main.verada.com (main.verada.com [208.164.216.3]) |
684 | 705 |
by tiger.franz.com (8.8.7/8.8.7) with ESMTP id NAA20541 |
... | ... |
@@ -697,16 +718,16 @@ ok? |
697 | 718 |
"</pre> |
698 | 719 |
</div> |
699 | 720 |
|
700 |
-<p align="left"><strong>We've been using message sequence numbers up to now. |
|
701 |
- The are the simplest to use but if you're concerned with keeping track of |
|
702 |
-messages when deletions are being done then using unique id's is useful. Here |
|
703 |
-we do the above search example using uids:</strong></p> |
|
721 |
+<p align="left"><strong>We've been using message sequence numbers up to now. |
|
722 |
+The are the simplest to use but if you're concerned with keeping track of messages when |
|
723 |
+deletions are being done then using unique id's is useful. Here we do the |
|
724 |
+above search example using uids:</strong></p> |
|
704 | 725 |
<div align="left"> |
705 | 726 |
|
706 | 727 |
<pre> |
707 |
-user(9): (mb:search-mailbox mb '(:text "blitzfig") :uid t) |
|
728 |
+user(9): (po:search-mailbox mb '(:text "blitzfig") :uid t) |
|
708 | 729 |
(68) |
709 |
-user(10): (mb:fetch-field 68 "body[]" (mb:fetch-letter mb 68 "body[]" :uid t) :uid t) |
|
730 |
+user(10): (po:fetch-field 68 "body[]" (po:fetch-letter mb 68 "body[]" :uid t) :uid t) |
|
710 | 731 |
"Return-Path: <jkf@verada.com> |
711 | 732 |
Received: from main.verada.com (main.verada.com [208.164.216.3]) |
712 | 733 |
by tiger.franz.com (8.8.7/8.8.7) with ESMTP id NAA20541 |
... | ... |
@@ -730,9 +751,9 @@ we have only six messages in the mailbox.</strong></p> |
730 | 751 |
<div align="left"> |
731 | 752 |
|
732 | 753 |
<pre> |
733 |
-user(11): (mb:delete-letter mb 68 :uid t) |
|
754 |
+user(11): (po:delete-letter mb 68 :uid t) |
|
734 | 755 |
(7) |
735 |
-user(12): (mb:mailbox-message-count mb) |
|
756 |
+user(12): (po:mailbox-message-count mb) |
|
736 | 757 |
6</pre> |
737 | 758 |
</div> |
738 | 759 |
|
... | ... |
@@ -744,9 +765,9 @@ do we issue the noop command, which does nothing on the server.</strong></p> |
744 | 765 |
<div align="left"> |
745 | 766 |
|
746 | 767 |
<pre> |
747 |
-user(13): (mb:noop mb) |
|
768 |
+user(13): (po:noop mb) |
|
748 | 769 |
nil |
749 |
-user(14): (mb:mailbox-message-count mb) |
|
770 |
+user(14): (po:mailbox-message-count mb) |
|
750 | 771 |
7</pre> |
751 | 772 |
</div> |
752 | 773 |
|
... | ... |
@@ -757,13 +778,13 @@ to specify a sequence of messages.</strong></p> |
757 | 778 |
<div align="left"> |
758 | 779 |
|
759 | 780 |
<pre> |
760 |
-user(15): (mb:create-mailbox mb "tempbox") |
|
781 |
+user(15): (po:create-mailbox mb "tempbox") |
|
761 | 782 |
t |
762 |
-user(18): (let ((count (mb:mailbox-message-count mb))) |
|
763 |
-(mb:copy-to-mailbox mb `(:seq 1 ,count) "tempbox") |
|
764 |
-(mb:delete-letter mb `(:seq 1 ,count))) |
|
783 |
+user(18): (let ((count (po:mailbox-message-count mb))) |
|
784 |
+(po:copy-to-mailbox mb `(:seq 1 ,count) "tempbox") |
|
785 |
+(po:delete-letter mb `(:seq 1 ,count))) |
|
765 | 786 |
(1 1 1 1 1 1 1) |
766 |
-user(19): (mb:mailbox-message-count mb) |
|
787 |
+user(19): (po:mailbox-message-count mb) |
|
767 | 788 |
0</pre> |
768 | 789 |
</div> |
769 | 790 |
|
... | ... |
@@ -773,9 +794,9 @@ messages are there.</strong></p> |
773 | 794 |
<div align="left"> |
774 | 795 |
|
775 | 796 |
<pre> |
776 |
-user(22): (mb:select-mailbox mb "tempbox") |
|
797 |
+user(22): (po:select-mailbox mb "tempbox") |
|
777 | 798 |
t |
778 |
-user(23): (mb:mailbox-message-count mb) |
|
799 |
+user(23): (po:mailbox-message-count mb) |
|
779 | 800 |
7</pre> |
780 | 801 |
</div> |
781 | 802 |
|
... | ... |
@@ -788,13 +809,82 @@ the lisp side in order to free up the resources still in use for the now dead co |
788 | 809 |
<div align="left"> |
789 | 810 |
|
790 | 811 |
<pre> |
791 |
-user(24): (mb:close-imap-connection mb) |
|
812 |
+user(24): (po:close-connection mb) |
|
792 | 813 |
t |
793 | 814 |
</pre> |
794 | 815 |
</div> |
795 | 816 |
|
796 | 817 |
<p align="left"> </p> |
797 | 818 |
|
819 |
+<h1>The Pop interface</h1> |
|
820 |
+ |
|
821 |
+<p>The <strong>pop</strong> protocol is a very simple means for retreiving messages from a |
|
822 |
+single mailbox. The functions in the interface are:</p> |
|
823 |
+ |
|
824 |
+<p> </p> |
|
825 |
+ |
|
826 |
+<p align="left"><font face="Courier New">(<strong>make-pop-connection host &key user |
|
827 |
+password port timeout)</strong></font></p> |
|
828 |
+ |
|
829 |
+<p align="left">This creates a connection to the <strong>pop</strong> server on machine <strong>host</strong> |
|
830 |
+and logs in as <strong>user </strong>with password <strong>password. </strong>The |
|
831 |
+<strong>port</strong> argument defaults to 110, which is the port on which the <strong>pop</strong> |
|
832 |
+server normally listens. The <strong>timeout</strong> argument defaults |
|
833 |
+to 30 (seconds) and this value is used to limit the amount of time this pop interface code |
|
834 |
+will wait for a response from the server before giving up. In certain |
|
835 |
+circumstances the server may get so busy that you see timeout errors signaled in this |
|
836 |
+code. In that case you should specify a larger timeout when connecting. </p> |
|
837 |
+ |
|
838 |
+<p>The value returned by this function is a <strong>mailbox</strong> object. You can |
|
839 |
+call <strong>mailbox-message-count</strong> on the <strong>mailbox</strong> object to |
|
840 |
+determine how many letters are currently stored in the mailbox.</p> |
|
841 |
+ |
|
842 |
+<p> </p> |
|
843 |
+ |
|
844 |
+<p><font face="Courier New"><strong>(close-connection mb)</strong></font></p> |
|
845 |
+ |
|
846 |
+<p>Disconnect from the pop server. All messages marked for deletion will be deleted.</p> |
|
847 |
+ |
|
848 |
+<p> </p> |
|
849 |
+ |
|
850 |
+<p><strong><font face="Courier New">(delete-letter mb messages)</font></strong></p> |
|
851 |
+ |
|
852 |
+<p>Mark the specified <strong>messages</strong> for deletion. <strong>mb </strong>is |
|
853 |
+the mailbox object returned by <strong>make-pop-connection</strong>. The messages |
|
854 |
+are only marked for deletion. They are not removed until a <strong>close-connection</strong> |
|
855 |
+is done. If the connection to the <strong>pop</strong> server is broken before a <strong>close-connection</strong> |
|
856 |
+is done, the messages will <strong>not</strong> be deleted and they will no longer be |
|
857 |
+marked for deletion either.</p> |
|
858 |
+ |
|
859 |
+<p><strong>messages</strong> can either be a message number, a list of the form <strong>(:seq |
|
860 |
+N M)</strong> meaning messages <strong>N </strong>through <strong>M </strong>or it can be |
|
861 |
+a list of message numbers and/or <strong>:seq </strong>specifiers. The |
|
862 |
+messages in a mailbox are numbered starting with one. Marking a message for deletion |
|
863 |
+does not affect the numbering of other messages in the mailbox.</p> |
|
864 |
+ |
|
865 |
+<p> </p> |
|
866 |
+ |
|
867 |
+<p><font face="Courier New"><strong>(fetch-letter mb message)</strong></font></p> |
|
868 |
+ |
|
869 |
+<p>Fetch from the pop server connection <strong>mb</strong> the letter numbered <strong>message</strong>. |
|
870 |
+ The letters in a mailbox are numbered starting with one. The entire |
|
871 |
+message, including the headers, is returned as a string. It is an |
|
872 |
+error to attempt to fetch a letter marked for deletion.</p> |
|
873 |
+ |
|
874 |
+<p> </p> |
|
875 |
+ |
|
876 |
+<p><font face="Courier New"><strong>(noop mb)</strong></font></p> |
|
877 |
+ |
|
878 |
+<p>This is the no-operation command. It is useful for letting the <strong>pop</strong> |
|
879 |
+server know that this connection should be kept alive (<strong>pop </strong>servers tend |
|
880 |
+to disconnect after a few minutes of inactivity). In order to make <strong>noop</strong> |
|
881 |
+have behavior similar to that of the <strong>imap</strong> version of <strong>noop</strong>, |
|
882 |
+we don't send a 'noop' command to the pop server, instead we send a 'stat' command. |
|
883 |
+ This means that after this command is completed the <strong>mailbox-message-count</strong> |
|
884 |
+will contain the current count of messages in the mailbox.</p> |
|
885 |
+ |
|
886 |
+<p> </p> |
|
887 |
+ |
|
798 | 888 |
<p> </p> |
799 | 889 |
</body> |
800 | 890 |
</html> |
... | ... |
@@ -2,10 +2,15 @@ |
2 | 2 |
(load (compile-file-if-needed "../smtp/smtp")) |
3 | 3 |
|
4 | 4 |
(defun test () |
5 |
- (setq *xx* (mb::make-imap-connection "tiger.franz.com" |
|
5 |
+ (setq *xx* (po::make-imap-connection "tiger.franz.com" |
|
6 | 6 |
:user "jkfmail" |
7 | 7 |
:password "jkf.imap" |
8 | 8 |
)) |
9 |
- (mb::select-mailbox *xx* "inbox")) |
|
9 |
+ (po::select-mailbox *xx* "inbox")) |
|
10 | 10 |
|
11 | 11 |
|
12 |
+(defun testp () |
|
13 |
+ (setq *xx* (po::make-pop-connection "tiger.franz.com" |
|
14 |
+ :user "jkfmail" |
|
15 |
+ :password "jkf.imap" |
|
16 |
+ ))) |
... | ... |
@@ -19,7 +19,7 @@ |
19 | 19 |
(defun test-connect () |
20 | 20 |
;; test connecting and disconnecting from the server |
21 | 21 |
|
22 |
- (let ((mb (mb:make-imap-connection *test-machine* |
|
22 |
+ (let ((mb (po:make-imap-connection *test-machine* |
|
23 | 23 |
:user *test-account* |
24 | 24 |
:password *test-password*))) |
25 | 25 |
(unwind-protect |
... | ... |
@@ -28,19 +28,19 @@ |
28 | 28 |
(test-t (not (null mb))) ; make sure we got a mailbox object |
29 | 29 |
|
30 | 30 |
; check that we've stored resonable values in the mb object |
31 |
- (test-equal "/" (mb:mailbox-separator mb)) |
|
31 |
+ (test-equal "/" (po:mailbox-separator mb)) |
|
32 | 32 |
|
33 |
- (test-t (mb::select-mailbox mb "inbox")) |
|
33 |
+ (test-t (po::select-mailbox mb "inbox")) |
|
34 | 34 |
|
35 |
- (test-t (> (mb:mailbox-uidvalidity mb) 0)) |
|
36 |
- (test-t (not (null (mb:mailbox-flags mb))))) |
|
35 |
+ (test-t (> (po:mailbox-uidvalidity mb) 0)) |
|
36 |
+ (test-t (not (null (po:mailbox-flags mb))))) |
|
37 | 37 |
|
38 |
- (test-t (mb:close-imap-connection mb))))) |
|
38 |
+ (test-t (po:close-connection mb))))) |
|
39 | 39 |
|
40 | 40 |
|
41 | 41 |
(defun test-sends () |
42 | 42 |
;; test sending and reading mail |
43 |
- (let ((mb (mb:make-imap-connection *test-machine* |
|
43 |
+ (let ((mb (po:make-imap-connection *test-machine* |
|
44 | 44 |
:user *test-account* |
45 | 45 |
:password *test-password*))) |
46 | 46 |
(unwind-protect |
... | ... |
@@ -48,18 +48,18 @@ |
48 | 48 |
(test-t (not (null mb))) ; make sure we got a mailbox object |
49 | 49 |
|
50 | 50 |
;; go through the mailboxes and delete all letters |
51 |
- (dolist (mblist (mb:mailbox-list mb :pattern "*")) |
|
52 |
- (if* (not (member :\\noselect (mb:mailbox-list-flags mblist))) |
|
53 |
- then (mb:select-mailbox mb (mb:mailbox-list-name mblist)) |
|
54 |
- (let ((count (mb:mailbox-message-count mb))) |
|
51 |
+ (dolist (mblist (po:mailbox-list mb :pattern "*")) |
|
52 |
+ (if* (not (member :\\noselect (po:mailbox-list-flags mblist))) |
|
53 |
+ then (po:select-mailbox mb (po:mailbox-list-name mblist)) |
|
54 |
+ (let ((count (po:mailbox-message-count mb))) |
|
55 | 55 |
; remove all old mail |
56 | 56 |
(if* (> count 0) |
57 |
- then (mb:alter-flags mb `(:seq 1 ,count) :add-flags :\\deleted) |
|
58 |
- (mb:expunge-mailbox mb) |
|
59 |
- (test-eql 0 (mb:mailbox-message-count mb))) |
|
57 |
+ then (po:alter-flags mb `(:seq 1 ,count) :add-flags :\\deleted) |
|
58 |
+ (po:expunge-mailbox mb) |
|
59 |
+ (test-eql 0 (po:mailbox-message-count mb))) |
|
60 | 60 |
; remove mailbox (except inbox) |
61 |
- (if* (not (equalp "inbox" (mb:mailbox-list-name mblist))) |
|
62 |
- then (mb:delete-mailbox mb (mb:mailbox-list-name mblist))) |
|
61 |
+ (if* (not (equalp "inbox" (po:mailbox-list-name mblist))) |
|
62 |
+ then (po:delete-mailbox mb (po:mailbox-list-name mblist))) |
|
63 | 63 |
|
64 | 64 |
))) |
65 | 65 |
|
... | ... |
@@ -72,15 +72,15 @@ |
72 | 72 |
(format nil "message number ~d" (1+ i)))) |
73 | 73 |
|
74 | 74 |
; test to see if imap figures out that the letters are there |
75 |
- (mb:select-mailbox mb "inbox") |
|
75 |
+ (po:select-mailbox mb "inbox") |
|
76 | 76 |
|
77 | 77 |
; wait a bit for the mail to be delivered |
78 | 78 |
(dotimes (i 5) |
79 |
- (if* (not (eql 5 (mb:mailbox-message-count mb))) |
|
79 |
+ (if* (not (eql 5 (po:mailbox-message-count mb))) |
|
80 | 80 |
then (sleep 1) |
81 |
- (mb: noop mb))) |
|
81 |
+ (po: noop mb))) |
|
82 | 82 |
|
83 |
- (test-eql 5 (mb:mailbox-message-count mb)) |
|
83 |
+ (test-eql 5 (po:mailbox-message-count mb)) |
|
84 | 84 |
|
85 | 85 |
; test the search facility |
86 | 86 |
; look for the message number we put in each message. |
... | ... |
@@ -88,23 +88,23 @@ |
88 | 88 |
(dotimes (i 5) |
89 | 89 |
(let ((mn (1+ i))) |
90 | 90 |
(test-equal (list mn) |
91 |
- (mb:search-mailbox mb |
|
91 |
+ (po:search-mailbox mb |
|
92 | 92 |
`(:body ,(format nil "~d" mn)))))) |
93 | 93 |
|
94 | 94 |
; test getting data from mail message |
95 |
- (let ((fetch-info (mb:fetch-letter mb |
|
95 |
+ (let ((fetch-info (po:fetch-parts mb |
|
96 | 96 |
1 |
97 | 97 |
"(envelope body[1])"))) |
98 |
- (let ((envelope (mb:fetch-field 1 "envelope" fetch-info)) |
|
99 |
- (body (mb:fetch-field 1 "body[1]" fetch-info))) |
|
100 |
- (test-equal "jkfmail" (mb:address-mailbox |
|
101 |
- (car (mb:envelope-from envelope)))) |
|
102 |
- (test-nil (mb:address-mailbox |
|
103 |
- (car (mb:envelope-to envelope)))) |
|
98 |
+ (let ((envelope (po:fetch-field 1 "envelope" fetch-info)) |
|
99 |
+ (body (po:fetch-field 1 "body[1]" fetch-info))) |
|
100 |
+ (test-equal "jkfmail" (po:address-mailbox |
|
101 |
+ (car (po:envelope-from envelope)))) |
|
102 |
+ (test-nil (po:address-mailbox |
|
103 |
+ (car (po:envelope-to envelope)))) |
|
104 | 104 |
|
105 | 105 |
(test-equal (format nil "message number 1~c" #\newline) |
106 | 106 |
body)))) |
107 |
- (test-t (mb:close-imap-connection mb))))) |
|
107 |
+ (test-t (po:close-connection mb))))) |
|
108 | 108 |
|
109 | 109 |
|
110 | 110 |
|
... | ... |
@@ -113,58 +113,96 @@ |
113 | 113 |
;; |
114 | 114 |
;; assume we have 5 messages in inbox at this time |
115 | 115 |
;; |
116 |
- (let ((mb (mb:make-imap-connection *test-machine* |
|
116 |
+ (let ((mb (po:make-imap-connection *test-machine* |
|
117 | 117 |
:user *test-account* |
118 | 118 |
:password *test-password*))) |
119 | 119 |
(unwind-protect |
120 | 120 |
(progn |
121 |
- (mb:select-mailbox mb "inbox") |
|
121 |
+ (po:select-mailbox mb "inbox") |
|
122 | 122 |
|
123 |
- (let ((flags (mb:fetch-field 3 |
|
123 |
+ (let ((flags (po:fetch-field 3 |
|
124 | 124 |
"flags" |
125 |
- (mb:fetch-letter |
|
125 |
+ (po:fetch-parts |
|
126 | 126 |
mb 3 "flags")))) |
127 | 127 |
(test-nil flags)) |
128 | 128 |
|
129 | 129 |
;; add flags |
130 |
- (let ((info (mb:alter-flags mb 3 :add-flags :\\deleted))) |
|
130 |
+ (let ((info (po:alter-flags mb 3 :add-flags :\\deleted))) |
|
131 | 131 |
(test-equal '(:\\deleted) |
132 |
- (mb:fetch-field 3 "flags" info))) |
|
132 |
+ (po:fetch-field 3 "flags" info))) |
|
133 | 133 |
|
134 | 134 |
; good bye message |
135 |
- (test-equal '(3) (mb:expunge-mailbox mb)) |
|
135 |
+ (test-equal '(3) (po:expunge-mailbox mb)) |
|
136 | 136 |
|
137 |
- (mb:alter-flags mb 4 :add-flags ':\\bbbb) |
|
137 |
+ (po:alter-flags mb 4 :add-flags ':\\bbbb) |
|
138 | 138 |
(test-equal '(:\\bbbb) |
139 |
- (mb:fetch-field 4 "flags" |
|
140 |
- (mb:fetch-letter mb 4 |
|
139 |
+ (po:fetch-field 4 "flags" |
|
140 |
+ (po:fetch-parts mb 4 |
|
141 | 141 |
"flags"))) |
142 | 142 |
|
143 | 143 |
|
144 | 144 |
) |
145 |
- (test-t (mb:close-imap-connection mb))))) |
|
145 |
+ (test-t (po:close-connection mb))))) |
|
146 | 146 |
|
147 | 147 |
(defun test-mailboxes () |
148 | 148 |
;; should be 4 messages now in inbox |
149 | 149 |
;; let's create 4 mailboxes, one for each letter |
150 |
- (let ((mb (mb:make-imap-connection *test-machine* |
|
150 |
+ (let ((mb (po:make-imap-connection *test-machine* |
|
151 | 151 |
:user *test-account* |
152 | 152 |
:password *test-password*))) |
153 | 153 |
(unwind-protect |
154 | 154 |
(progn |
155 |
- (mb:select-mailbox mb "inbox") |
|
155 |
+ (po:select-mailbox mb "inbox") |
|
156 | 156 |
(dotimes (i 4) |
157 | 157 |
(let ((mbname (format nil "temp/mb~d" i))) |
158 |
- (test-t (mb:create-mailbox mb mbname)) |
|
159 |
- (mb:copy-to-mailbox mb (1+ i) mbname))) |
|
158 |
+ (test-t (po:create-mailbox mb mbname)) |
|
159 |
+ (po:copy-to-mailbox mb (1+ i) mbname))) |
|
160 | 160 |
|
161 | 161 |
; now check that each new mailbox has one message |
162 | 162 |
(dotimes (i 4) |
163 | 163 |
(let ((mbname (format nil "temp/mb~d" i))) |
164 |
- (mb:select-mailbox mb mbname) |
|
165 |
- (test-eql 1 (mb:mailbox-message-count mb))))) |
|
166 |
- (test-t (mb:close-imap-connection mb))))) |
|
164 |
+ (po:select-mailbox mb mbname) |
|
165 |
+ (test-eql 1 (po:mailbox-message-count mb))))) |
|
166 |
+ (test-t (po:close-connection mb))))) |
|
167 |
+ |
|
168 |
+ |
|
169 |
+(defun test-pop () |
|
170 |
+ ;; test out the pop interface to the mailbox. |
|
167 | 171 |
|
172 |
+ (let ((pb (po:make-pop-connection *test-machine* |
|
173 |
+ :user *test-account* |
|
174 |
+ :password *test-password*))) |
|
175 |
+ ; still from before |
|
176 |
+ (test-eql 4 (po:mailbox-message-count pb)) |
|
177 |
+ |
|
178 |
+ (po:delete-letter pb '(:seq 2 3)) |
|
179 |
+ |
|
180 |
+ |
|
181 |
+ (test-eql 4 (and :second (po:mailbox-message-count pb))) |
|
182 |
+ |
|
183 |
+ (po:noop pb) |
|
184 |
+ |
|
185 |
+ (test-eql 2 (and :third (po:mailbox-message-count pb))) |
|
186 |
+ |
|
187 |
+ (po:fetch-letter mb 1) |
|
188 |
+ (test-err (po:fetch-letter mb 2)) |
|
189 |
+ (test-err (po:fetch-letter mb 3)) |
|
190 |
+ (po:fetch-letter mb 4) |
|
191 |
+ |
|
192 |
+ (po:close-connection pb) |
|
193 |
+ |
|
194 |
+ (setq pb (po:make-pop-connection *test-machine* |
|
195 |
+ :user *test-account* |
|
196 |
+ :password *test-password*)) |
|
197 |
+ |
|
198 |
+ (test-eql 2 (and :fourth (po:mailbox-message-count pb))) |
|
199 |
+ |
|
200 |
+ (po:fetch-letter pb 1) ; just make sure there's no error |
|
201 |
+ |
|
202 |
+ (po:close-connection pb))) |
|
203 |
+ |
|
204 |
+ |
|
205 |
+ |
|
168 | 206 |
(defun test-imap () |
169 | 207 |
(test-connect) |
170 | 208 |
|
... | ... |
@@ -173,6 +211,9 @@ |
173 | 211 |
(test-flags) |
174 | 212 |
|
175 | 213 |
(test-mailboxes) |
214 |
+ |
|
215 |
+ (test-pop) |
|
216 |
+ |
|
176 | 217 |
|
177 | 218 |
) |
178 | 219 |
|