;; Author: Simon Josefsson <jas@pdc.kth.se>
;;
+;;; Code:
(require 'elmo-vars)
(require 'elmo-util)
(require 'elmo-date)
(require 'utf7)
(require 'elmo-mime)
-;;; Code:
(eval-when-compile (require 'cl))
(defvar elmo-imap4-disuse-server-flag-mailbox-regexp "^#mh" ; UW imapd
(capability current-mailbox read-only flags))
(luna-define-internal-accessors 'elmo-imap4-session))
+(defmacro elmo-imap4-session-capable-p (session capability)
+ `(memq ,capability (elmo-imap4-session-capability-internal ,session)))
+
;;; MIME-ELMO-IMAP Location
(eval-and-compile
(luna-define-class mime-elmo-imap-location
;;; Debug
(defmacro elmo-imap4-debug (message &rest args)
- (` (if elmo-imap4-debug
- (elmo-imap4-debug-1 (, message) (,@ args)))))
+ `(if elmo-imap4-debug
+ (elmo-imap4-debug-1 ,message ,@args)))
(defun elmo-imap4-debug-1 (message &rest args)
(with-current-buffer (get-buffer-create "*IMAP4 DEBUG*")
(defmacro elmo-imap4-response-continue-req-p (response)
"Returns non-nil if RESPONSE is '+' response."
- (` (assq 'continue-req (, response))))
+ `(assq 'continue-req ,response))
(defmacro elmo-imap4-response-ok-p (response)
"Returns non-nil if RESPONSE is an 'OK' response."
- (` (assq 'ok (, response))))
+ `(assq 'ok ,response))
(defmacro elmo-imap4-response-bye-p (response)
"Returns non-nil if RESPONSE is an 'BYE' response."
- (` (assq 'bye (, response))))
+ `(assq 'bye ,response))
(defmacro elmo-imap4-response-garbage-p (response)
"Returns non-nil if RESPONSE is an 'garbage' response."
- (` (assq 'garbage (, response))))
+ `(assq 'garbage ,response))
(defmacro elmo-imap4-response-value (response symbol)
"Get value of the SYMBOL from RESPONSE."
- (` (nth 1 (assq (, symbol) (, response)))))
+ `(nth 1 (assq ,symbol ,response)))
(defsubst elmo-imap4-response-value-all (response symbol)
"Get all value of the SYMBOL from RESPONSE."
(defmacro elmo-imap4-response-error-text (response)
"Returns text of NO, BAD, BYE response."
- (` (nth 1 (or (elmo-imap4-response-value (, response) 'no)
- (elmo-imap4-response-value (, response) 'bad)
- (elmo-imap4-response-value (, response) 'bye)))))
+ `(nth 1 (or (elmo-imap4-response-value ,response 'no)
+ (elmo-imap4-response-value ,response 'bad)
+ (elmo-imap4-response-value ,response 'bye))))
(defmacro elmo-imap4-response-bodydetail-text (response)
"Returns text of BODY[section]<partial>."
- (` (nth 3 (assq 'bodydetail (, response)))))
+ `(nth 3 (assq 'bodydetail ,response)))
;;; Session commands.
cmdstr
(elmo-imap4-format-quoted (nth 1 token)))))
((eq kind 'literal)
- (if (memq 'literal+
- (elmo-imap4-session-capability-internal
- session))
+ (if (elmo-imap4-session-capable-p session 'literal+)
;; rfc2088
(progn
(setq cmdstr (concat cmdstr
- (format "{%d+}" (nth 2 token))))
+ (format "{%d+}" (nth 2 token))
+ "\r\n"))
(process-send-string process cmdstr)
- (process-send-string process "\r\n")
(setq cmdstr nil))
(setq cmdstr (concat cmdstr
- (format "{%d}" (nth 2 token))))
+ (format "{%d}" (nth 2 token))
+ "\r\n"))
(process-send-string process cmdstr)
- (process-send-string process "\r\n")
(setq cmdstr nil)
(elmo-imap4-accept-continue-req session))
(cond ((stringp (nth 1 token))
(t
(error "Invalid argument")))
(setq command-args (cdr command-args)))
- (if cmdstr
- (process-send-string process cmdstr))
- (process-send-string process "\r\n")
+ (process-send-string process (concat cmdstr "\r\n"))
tag)))
(defun elmo-imap4-send-string (session string)
(let ((session (elmo-imap4-get-session folder))
(criteria (elmo-imap4-flag-to-imap-criteria flag)))
(if (elmo-imap4-session-flag-available-p session flag)
- (progn
- (elmo-imap4-session-select-mailbox
- session
- (elmo-imap4-folder-mailbox-internal folder))
- (elmo-imap4-response-value
- (elmo-imap4-send-command-wait
- session
- (format (if elmo-imap4-use-uid "uid search %s"
- "search %s") criteria))
- 'search))
+ (elmo-imap4-list folder criteria)
;; List flagged messages in the msgdb.
(elmo-msgdb-list-flagged (elmo-folder-msgdb folder) flag))))
(concat "(" (downcase (elmo-match-string 1 string)) ")"))))
(defun elmo-imap4-clear-login (session)
+ (when (elmo-imap4-session-capable-p session 'logindisabled)
+ (signal 'elmo-authenticate-error '(elmo-imap4-clear-login)))
(let ((elmo-imap4-debug-inhibit-logging t))
(or
(elmo-imap4-read-ok
;; Skip garbage output from process before greeting.
(while (and (memq (process-status process) '(open run))
(goto-char (point-max))
- (forward-line -1)
- (not (elmo-imap4-parse-greeting)))
+ (or (/= (forward-line -1) 0)
+ (not (elmo-imap4-parse-greeting))))
(accept-process-output process 1))
(erase-buffer)
(set-process-filter process 'elmo-imap4-arrival-filter)
(when (eq (elmo-network-stream-type-symbol
(elmo-network-session-stream-type-internal session))
'starttls)
- (or (memq 'starttls
- (elmo-imap4-session-capability-internal session))
+ (or (elmo-imap4-session-capable-p session 'starttls)
(signal 'elmo-open-error
'(elmo-imap4-starttls-error)))
(elmo-imap4-send-command-wait session "starttls")
(luna-define-method elmo-network-setup-session ((session
elmo-imap4-session))
(with-current-buffer (elmo-network-session-buffer session)
- (when (memq 'namespace (elmo-imap4-session-capability-internal session))
+ (when (elmo-imap4-session-capable-p session 'namespace)
(setq elmo-imap4-server-namespace
(elmo-imap4-response-value
(elmo-imap4-send-command-wait session "namespace")
(if (< (point-max) (+ (point) (string-to-number (match-string 1))))
(progn
(when elmo-imap4-literal-progress-reporter
- (elmo-progress-counter-set-total
- elmo-imap4-literal-progress-reporter
- (string-to-number (match-string 1)))
- (elmo-progress-notify 'elmo-retrieve-message
- :set (- (point-max) (point))))
+ (elmo-progress-notify
+ 'elmo-retrieve-message
+ :set (- (point-max) (point))
+ :total (string-to-number (match-string 1))))
nil)
(goto-char (+ (point) (string-to-number (match-string 1))))
(elmo-imap4-find-next-line))
(setq status
(cons
(let ((token (read (current-buffer))))
- (cond ((eq token 'MESSAGES)
- (list 'messages (read (current-buffer))))
- ((eq token 'RECENT)
- (list 'recent (read (current-buffer))))
- ((eq token 'UIDNEXT)
- (list 'uidnext (read (current-buffer))))
- ((eq token 'UIDVALIDITY)
- (and (looking-at " \\([0-9]+\\)")
- (prog1 (list 'uidvalidity (match-string 1))
- (goto-char (match-end 1)))))
- ((eq token 'UNSEEN)
- (list 'unseen (read (current-buffer))))
- (t
- (message
- "Unknown status data %s in mailbox %s ignored"
- token mailbox))))
+ (case (intern (upcase (symbol-name token)))
+ (MESSAGES
+ (list 'messages (read (current-buffer))))
+ (RECENT
+ (list 'recent (read (current-buffer))))
+ (UIDNEXT
+ (list 'uidnext (read (current-buffer))))
+ (UIDVALIDITY
+ (and (looking-at " \\([0-9]+\\)")
+ (prog1 (list 'uidvalidity (match-string 1))
+ (goto-char (match-end 1)))))
+ (UNSEEN
+ (list 'unseen (read (current-buffer))))
+ (t
+ (message
+ "Unknown status data %s in mailbox %s ignored"
+ token mailbox))))
status))
(skip-chars-forward " ")))
(and elmo-imap4-status-callback
(defmacro elmo-imap4-value (value)
- (` (if (eq (, value) 'NIL) nil
- (, value))))
+ `(if (eq ,value 'NIL)
+ nil
+ ,value))
(defmacro elmo-imap4-nth (pos list)
- (` (let ((value (nth (, pos) (, list))))
- (elmo-imap4-value value))))
+ `(let ((value (nth ,pos ,list)))
+ (elmo-imap4-value value)))
(defun elmo-imap4-parse-namespace ()
(list 'namespace
&optional
enable-killed)
(elmo-imap4-list folder
- (let ((killed
- (elmo-folder-killed-list-internal
- folder)))
- (if (and killed
- (eq (length killed) 1)
- (consp (car killed))
- (eq (car (car killed)) 1))
- (format "uid %d:*" (cdr (car killed)))
- "all"))))
+ (concat
+ (let ((killed
+ (elmo-folder-killed-list-internal
+ folder)))
+ (if (and killed
+ (eq (length killed) 1)
+ (consp (car killed))
+ (eq (car (car killed)) 1))
+ (format "uid %d:*" (cdr (car killed)))
+ "all"))
+ " undeleted")))
(luna-define-method elmo-folder-list-flagged-plugged
((folder elmo-imap4-folder) flag)
root)))
(setq root (concat root delim)))
(while (setq folder (car result))
- (when (string-match
- (concat "^\\(" (regexp-quote root) "[^" re-delim "]" "+\\)"
- re-delim)
- folder)
- (setq folder (match-string 1 folder)))
- (setq has-child-p nil
- result (delq
+ (setq has-child-p
+ (when (string-match
+ (concat "^\\(" (regexp-quote root) "[^" re-delim "]" "+\\)"
+ re-delim)
+ folder)
+ (setq folder (match-string 1 folder))))
+ (setq result (delq
nil
(mapcar (lambda (fld)
(if (string-match
t)
(luna-define-method elmo-folder-delete ((folder elmo-imap4-folder))
- (let ((msgs (and (elmo-folder-exists-p folder)
- (elmo-folder-list-messages folder))))
+ (let* ((exists (elmo-folder-exists-p folder))
+ (msgs (and exists
+ (elmo-folder-list-messages folder))))
(when (yes-or-no-p (format "%sDelete msgdb and substance of \"%s\"? "
(if (> (length msgs) 0)
(format "%d msg(s) exists. " (length msgs))
(let ((session (elmo-imap4-get-session folder)))
(when (elmo-imap4-folder-mailbox-internal folder)
(when msgs (elmo-folder-delete-messages-internal folder msgs))
- (elmo-imap4-send-command-wait session "close")
+ ;; close selected mailbox except one with \Noselect attribute
+ (when exists
+ (elmo-imap4-send-command-wait session "close"))
(elmo-imap4-send-command-wait
session
(list "delete "
(luna-define-method elmo-folder-delete-messages-plugged
((folder elmo-imap4-folder) numbers)
- (let ((session (elmo-imap4-get-session folder)))
+ (let ((session (elmo-imap4-get-session folder))
+ (expunge
+ (or (null (elmo-imap4-list folder "deleted"))
+ (y-or-n-p
+ "There's hidden deleted messages, expunge anyway?"))))
(elmo-imap4-session-select-mailbox
session
(elmo-imap4-folder-mailbox-internal folder))
(unless (elmo-imap4-set-flag folder numbers "\\Deleted")
(error "Failed to set deleted flag"))
- (elmo-imap4-send-command session "expunge")))
+ (when expunge
+ (elmo-imap4-send-command session "expunge"))
+ t))
(defmacro elmo-imap4-detect-search-charset (string)
- (` (with-temp-buffer
- (insert (, string))
- (detect-mime-charset-region (point-min) (point-max)))))
+ `(with-temp-buffer
+ (insert ,string)
+ (detect-mime-charset-region (point-min) (point-max))))
(defun elmo-imap4-search-internal-primitive (folder session filter from-msgs)
(let ((search-key (elmo-filter-key filter))
((string= "last" search-key)
(let ((numbers (or from-msgs (elmo-folder-list-messages folder))))
(nthcdr (max (- (length numbers)
- (string-to-int (elmo-filter-value filter)))
+ (string-to-number (elmo-filter-value filter)))
0)
numbers)))
((string= "first" search-key)
(let* ((numbers (or from-msgs (elmo-folder-list-messages folder)))
- (rest (nthcdr (string-to-int (elmo-filter-value filter) )
+ (rest (nthcdr (string-to-number (elmo-filter-value filter) )
numbers)))
(mapcar '(lambda (x) (delete x numbers)) rest)
numbers))
condition &optional numbers)
(if (elmo-folder-plugged-p folder)
(save-excursion
- (let ((session (elmo-imap4-get-session folder)))
+ (let ((session (elmo-imap4-get-session folder))
+ ret)
(message "Searching...")
(elmo-imap4-session-select-mailbox
session
(elmo-imap4-folder-mailbox-internal folder))
- (elmo-imap4-search-internal folder session condition numbers)
- (message "Searching...done")))
+ (setq ret (elmo-imap4-search-internal folder session condition numbers))
+ (message "Searching...done")
+ ret))
(luna-call-next-method)))
(luna-define-method elmo-folder-msgdb-create-plugged
(total 0)
print-length print-depth
rfc2060 set-list)
- (setq rfc2060 (memq 'imap4rev1
- (elmo-imap4-session-capability-internal
- session)))
+ (setq rfc2060 (elmo-imap4-session-capable-p session 'imap4rev1))
(elmo-with-progress-display (elmo-folder-msgdb-create (length numbers))
"Creating msgdb"
(elmo-imap4-session-select-mailbox
(eval-when-compile
(defmacro elmo-imap4-identical-system-p (folder1 folder2)
"Return t if FOLDER1 and FOLDER2 are in the same IMAP4 system."
- (` (and (string= (elmo-net-folder-server-internal (, folder1))
- (elmo-net-folder-server-internal (, folder2)))
- (eq (elmo-net-folder-port-internal (, folder1))
- (elmo-net-folder-port-internal (, folder2)))
- (string= (elmo-net-folder-user-internal (, folder1))
- (elmo-net-folder-user-internal (, folder2)))))))
+ `(and (string= (elmo-net-folder-server-internal ,folder1)
+ (elmo-net-folder-server-internal ,folder2))
+ (eq (elmo-net-folder-port-internal ,folder1)
+ (elmo-net-folder-port-internal ,folder2))
+ (string= (elmo-net-folder-user-internal ,folder1)
+ (elmo-net-folder-user-internal ,folder2)))))
(luna-define-method elmo-folder-next-message-number-plugged
((folder elmo-imap4-folder))
(setq elmo-imap4-fetch-callback nil)
(setq elmo-imap4-fetch-callback-data nil))
(elmo-with-progress-display (elmo-retrieve-message
- (or (elmo-message-field folder number :size)
- 0)
+ (elmo-message-field folder number :size)
elmo-imap4-literal-progress-reporter)
"Retrieving"
(setq response