Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lisp / gnus / pop3.el
CommitLineData
eec82323
LMI
1;;; pop3.el --- Post Office Protocol (RFC 1460) interface
2
73b0cd50 3;; Copyright (C) 1996-2011 Free Software Foundation, Inc.
eec82323
LMI
4
5;; Author: Richard L. Pieri <ratinox@peorth.gweep.net>
dd5da9b8
DL
6;; Maintainer: FSF
7;; Keywords: mail
eec82323
LMI
8
9;; This file is part of GNU Emacs.
10
5e809f55 11;; GNU Emacs is free software: you can redistribute it and/or modify
eec82323 12;; it under the terms of the GNU General Public License as published by
5e809f55
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
eec82323
LMI
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
5e809f55 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
eec82323
LMI
23
24;;; Commentary:
25
26;; Most of the standard Post Office Protocol version 3 (RFC 1460) commands
27;; are implemented. The LIST command has not been implemented due to lack
28;; of actual usefulness.
29;; The optional POP3 command TOP has not been implemented.
30
31;; This program was inspired by Kyle E. Jones's vm-pop program.
32
33;;; Code:
34
ed96ace9 35(eval-when-compile (require 'cl))
eec82323 36(require 'mail-utils)
9efa445f 37(defvar parse-time-months)
eec82323 38
e62e7654 39(defgroup pop3 nil
62a3378e 40 "Post Office Protocol."
e62e7654
MB
41 :group 'mail
42 :group 'mail-source)
43
44(defcustom pop3-maildrop (or (user-login-name)
45 (getenv "LOGNAME")
46 (getenv "USER"))
47 "*POP3 maildrop."
bf247b6e 48 :version "22.1" ;; Oort Gnus
e62e7654
MB
49 :type 'string
50 :group 'pop3)
51
52(defcustom pop3-mailhost (or (getenv "MAILHOST") ;; nil -> mismatch
53 "pop3")
54 "*POP3 mailhost."
bf247b6e 55 :version "22.1" ;; Oort Gnus
e62e7654
MB
56 :type 'string
57 :group 'pop3)
58
59(defcustom pop3-port 110
60 "*POP3 port."
bf247b6e 61 :version "22.1" ;; Oort Gnus
e62e7654
MB
62 :type 'number
63 :group 'pop3)
64
65(defcustom pop3-password-required t
66 "*Non-nil if a password is required when connecting to POP server."
bf247b6e 67 :version "22.1" ;; Oort Gnus
e62e7654
MB
68 :type 'boolean
69 :group 'pop3)
70
71;; Should this be customizable?
eec82323
LMI
72(defvar pop3-password nil
73 "*Password to use when connecting to POP server.")
74
e62e7654 75(defcustom pop3-authentication-scheme 'pass
eec82323 76 "*POP3 authentication scheme.
996aa8c1
MB
77Defaults to `pass', for the standard USER/PASS authentication. The other
78valid value is 'apop'."
79 :type '(choice (const :tag "Normal user/password" pass)
e62e7654 80 (const :tag "APOP" apop))
996aa8c1 81 :version "22.1" ;; Oort Gnus
e62e7654
MB
82 :group 'pop3)
83
229b59da
G
84(defcustom pop3-stream-length 100
85 "How many messages should be requested at one time.
86The lower the number, the more latency-sensitive the fetching
87will be. If your pop3 server doesn't support streaming at all,
88set this to 1."
89 :type 'number
90 :version "24.1"
91 :group 'pop3)
92
e62e7654 93(defcustom pop3-leave-mail-on-server nil
8903a9c8
MB
94 "*Non-nil if the mail is to be left on the POP server after fetching.
95
996aa8c1
MB
96If `pop3-leave-mail-on-server' is non-nil the mail is to be left
97on the POP server after fetching. Note that POP servers maintain
98no state information between sessions, so what the client
99believes is there and what is actually there may not match up.
100If they do not, then you may get duplicate mails or the whole
101thing can fall apart and leave you with a corrupt mailbox."
b110774a
MB
102 ;; We can't use the UILD support from XEmacs mail-lib or cvs.m17n.org:
103 ;; http://thread.gmane.org/v9lld8fml4.fsf@marauder.physik.uni-ulm.de
104 ;; http://thread.gmane.org/b9yy8hzy9ej.fsf@jpl.org
105 ;; Any volunteer to re-implement this?
bf247b6e 106 :version "22.1" ;; Oort Gnus
e62e7654
MB
107 :type 'boolean
108 :group 'pop3)
3e7b210c 109
eec82323
LMI
110(defvar pop3-timestamp nil
111 "Timestamp returned when initially connected to the POP server.
112Used for APOP authentication.")
113
114(defvar pop3-read-point nil)
115(defvar pop3-debug nil)
116
e3e955fe
MB
117;; Borrowed from nnheader-accept-process-output in nnheader.el. See the
118;; comments there for explanations about the values.
119
120(eval-and-compile
121 (if (and (fboundp 'nnheader-accept-process-output)
122 (boundp 'nnheader-read-timeout))
123 (defalias 'pop3-accept-process-output 'nnheader-accept-process-output)
124 ;; Borrowed from `nnheader.el':
125 (defvar pop3-read-timeout
f5ec697d 126 (if (string-match "windows-nt\\|os/2\\|cygwin"
e3e955fe
MB
127 (symbol-name system-type))
128 1.0
129 0.01)
130 "How long pop3 should wait between checking for the end of output.
8903a9c8 131Shorter values mean quicker response, but are more CPU intensive.")
e3e955fe
MB
132 (defun pop3-accept-process-output (process)
133 (accept-process-output
134 process
135 (truncate pop3-read-timeout)
136 (truncate (* (- pop3-read-timeout
137 (truncate pop3-read-timeout))
138 1000))))))
6459e35e 139
e574f629
LMI
140;;;###autoload
141(defun pop3-movemail (file)
a2bb410e
LMI
142 "Transfer contents of a maildrop to the specified FILE.
143Use streaming commands."
eec82323 144 (let* ((process (pop3-open-server pop3-mailhost pop3-port))
a2bb410e
LMI
145 message-count message-total-size)
146 (pop3-logon process)
147 (with-current-buffer (process-buffer process)
148 (let ((size (pop3-stat process)))
149 (setq message-count (car size)
150 message-total-size (cadr size)))
d99a4591 151 (when (> message-count 0)
a2bb410e
LMI
152 (pop3-send-streaming-command
153 process "RETR" message-count message-total-size)
154 (pop3-write-to-file file)
155 (unless pop3-leave-mail-on-server
156 (pop3-send-streaming-command
ff3eb82e 157 process "DELE" message-count nil))))
3ff31c90
LMI
158 (pop3-quit process)
159 t))
a2bb410e
LMI
160
161(defun pop3-send-streaming-command (process command count total-size)
162 (erase-buffer)
163 (let ((i 1))
530b8957 164 (while (>= count i)
a2bb410e
LMI
165 (process-send-string process (format "%s %d\r\n" command i))
166 ;; Only do 100 messages at a time to avoid pipe stalls.
229b59da 167 (when (zerop (% i pop3-stream-length))
a2bb410e
LMI
168 (pop3-wait-for-messages process i total-size))
169 (incf i)))
170 (pop3-wait-for-messages process count total-size))
171
172(defun pop3-wait-for-messages (process count total-size)
173 (while (< (pop3-number-of-responses total-size) count)
174 (when total-size
175 (message "pop3 retrieved %dKB (%d%%)"
176 (truncate (/ (buffer-size) 1000))
177 (truncate (* (/ (* (buffer-size) 1.0)
178 total-size) 100))))
0eb04273 179 (pop3-accept-process-output process)))
a2bb410e
LMI
180
181(defun pop3-write-to-file (file)
182 (let ((pop-buffer (current-buffer))
183 (start (point-min))
184 beg end
185 temp-buffer)
186 (with-temp-buffer
187 (setq temp-buffer (current-buffer))
188 (with-current-buffer pop-buffer
189 (goto-char (point-min))
190 (while (re-search-forward "^\\+OK" nil t)
191 (forward-line 1)
192 (setq beg (point))
193 (when (re-search-forward "^\\.\r?\n" nil t)
194 (setq start (point))
195 (forward-line -1)
196 (setq end (point)))
197 (with-current-buffer temp-buffer
198 (goto-char (point-max))
199 (let ((hstart (point)))
200 (insert-buffer-substring pop-buffer beg end)
201 (pop3-clean-region hstart (point))
202 (goto-char (point-max))
203 (pop3-munge-message-separator hstart (point))
204 (goto-char (point-max))))))
205 (let ((coding-system-for-write 'binary))
206 (goto-char (point-min))
207 ;; Check whether something inserted a newline at the start and
208 ;; delete it.
209 (when (eolp)
210 (delete-char 1))
530b8957 211 (write-region (point-min) (point-max) file nil 'nomesg)))))
a2bb410e
LMI
212
213(defun pop3-number-of-responses (endp)
214 (let ((responses 0))
215 (save-excursion
216 (goto-char (point-min))
ed96ace9 217 (while (or (and (re-search-forward "^\\+OK" nil t)
a2bb410e
LMI
218 (or (not endp)
219 (re-search-forward "^\\.\r?\n" nil t)))
220 (re-search-forward "^-ERR " nil t))
221 (incf responses)))
222 responses))
223
224(defun pop3-logon (process)
225 (let ((pop3-password pop3-password))
eec82323
LMI
226 ;; for debugging only
227 (if pop3-debug (switch-to-buffer (process-buffer process)))
6748645f
LMI
228 ;; query for password
229 (if (and pop3-password-required (not pop3-password))
230 (setq pop3-password
23f87bed 231 (read-passwd (format "Password for %s: " pop3-maildrop))))
eec82323
LMI
232 (cond ((equal 'apop pop3-authentication-scheme)
233 (pop3-apop process pop3-maildrop))
234 ((equal 'pass pop3-authentication-scheme)
235 (pop3-user process pop3-maildrop)
236 (pop3-pass process))
a2bb410e
LMI
237 (t (error "Invalid POP3 authentication scheme")))))
238
619ac84f
SZ
239(defun pop3-get-message-count ()
240 "Return the number of messages in the maildrop."
241 (let* ((process (pop3-open-server pop3-mailhost pop3-port))
242 message-count
e62e7654 243 (pop3-password pop3-password))
619ac84f
SZ
244 ;; for debugging only
245 (if pop3-debug (switch-to-buffer (process-buffer process)))
246 ;; query for password
247 (if (and pop3-password-required (not pop3-password))
248 (setq pop3-password
23f87bed 249 (read-passwd (format "Password for %s: " pop3-maildrop))))
619ac84f
SZ
250 (cond ((equal 'apop pop3-authentication-scheme)
251 (pop3-apop process pop3-maildrop))
252 ((equal 'pass pop3-authentication-scheme)
253 (pop3-user process pop3-maildrop)
254 (pop3-pass process))
55535639 255 (t (error "Invalid POP3 authentication scheme")))
619ac84f
SZ
256 (setq message-count (car (pop3-stat process)))
257 (pop3-quit process)
258 message-count))
259
01c52d31
MB
260(autoload 'open-tls-stream "tls")
261(autoload 'starttls-open-stream "starttls")
262(autoload 'starttls-negotiate "starttls") ; avoid warning
263
264(defcustom pop3-stream-type nil
265 "*Transport security type for POP3 connexions.
266This may be either nil (plain connexion), `ssl' (use an
267SSL/TSL-secured stream) or `starttls' (use the starttls mechanism
268to turn on TLS security after opening the stream). However, if
269this is nil, `ssl' is assumed for connexions to port
270995 (pop3s)."
330f707b 271 :version "23.1" ;; No Gnus
01c52d31
MB
272 :group 'pop3
273 :type '(choice (const :tag "Plain" nil)
274 (const :tag "SSL/TLS" ssl)
275 (const starttls)))
276
c6faacb4
KY
277(eval-and-compile
278 (if (fboundp 'set-process-query-on-exit-flag)
279 (defalias 'pop3-set-process-query-on-exit-flag
280 'set-process-query-on-exit-flag)
281 (defalias 'pop3-set-process-query-on-exit-flag
282 'process-kill-without-query)))
283
eec82323 284(defun pop3-open-server (mailhost port)
dd5da9b8 285 "Open TCP connection to MAILHOST on PORT.
eec82323 286Returns the process associated with the connection."
4cac7481 287 (let ((coding-system-for-read 'binary)
6748645f 288 (coding-system-for-write 'binary)
4cac7481 289 process)
88ed5ce8
KY
290 (with-current-buffer
291 (get-buffer-create (concat " trace of POP session to "
292 mailhost))
6748645f
LMI
293 (erase-buffer)
294 (setq pop3-read-point (point-min))
01c52d31
MB
295 (setq process
296 (cond
297 ((or (eq pop3-stream-type 'ssl)
298 (and (not pop3-stream-type) (member port '(995 "pop3s"))))
299 ;; gnutls-cli, openssl don't accept service names
300 (if (or (equal port "pop3s")
301 (null port))
302 (setq port 995))
303 (let ((process (open-tls-stream "POP" (current-buffer)
304 mailhost port)))
305 (when process
306 ;; There's a load of info printed that needs deleting.
1428d46b
MB
307 (let ((again 't))
308 ;; repeat until
309 ;; - either we received the +OK line
310 ;; - or accept-process-output timed out without getting
311 ;; anything
312 (while (and again
313 (setq again (memq (process-status process)
314 '(open run))))
315 (setq again (pop3-accept-process-output process))
316 (goto-char (point-max))
317 (forward-line -1)
318 (cond ((looking-at "\\+OK")
319 (setq again nil)
320 (delete-region (point-min) (point)))
321 ((not again)
01c52d31 322 (pop3-quit process)
1428d46b 323 (error "POP SSL connexion failed")))))
01c52d31
MB
324 process)))
325 ((eq pop3-stream-type 'starttls)
326 ;; gnutls-cli, openssl don't accept service names
327 (if (equal port "pop3")
328 (setq port 110))
4b320a01
YK
329 ;; Delay STLS until server greeting is read (Bug#7438).
330 (starttls-open-stream "POP" (current-buffer)
331 mailhost (or port 110)))
c9fc72fa 332 (t
01c52d31 333 (open-network-stream "POP" (current-buffer) mailhost port))))
4cac7481
DL
334 (let ((response (pop3-read-response process t)))
335 (setq pop3-timestamp
336 (substring response (or (string-match "<" response) 0)
337 (+ 1 (or (string-match ">" response) -1)))))
4b320a01
YK
338 (when (eq pop3-stream-type 'starttls)
339 (pop3-send-command process "STLS")
340 (let ((response (pop3-read-response process t)))
341 (if (and response (string-match "+OK" response))
342 (starttls-negotiate process)
343 (pop3-quit process)
344 (error "POP server doesn't support starttls"))))
c6faacb4 345 (pop3-set-process-query-on-exit-flag process nil)
4cac7481 346 process)))
eec82323
LMI
347
348;; Support functions
349
eec82323 350(defun pop3-send-command (process command)
e62e7654
MB
351 (set-buffer (process-buffer process))
352 (goto-char (point-max))
353 ;; (if (= (aref command 0) ?P)
354 ;; (insert "PASS <omitted>\r\n")
355 ;; (insert command "\r\n"))
356 (setq pop3-read-point (point))
357 (goto-char (point-max))
358 (process-send-string process (concat command "\r\n")))
eec82323
LMI
359
360(defun pop3-read-response (process &optional return)
361 "Read the response from the server.
362Return the response string if optional second argument is non-nil."
363 (let ((case-fold-search nil)
364 match-end)
88ed5ce8 365 (with-current-buffer (process-buffer process)
eec82323 366 (goto-char pop3-read-point)
23f87bed
MB
367 (while (and (memq (process-status process) '(open run))
368 (not (search-forward "\r\n" nil t)))
8903a9c8 369 (pop3-accept-process-output process)
eec82323
LMI
370 (goto-char pop3-read-point))
371 (setq match-end (point))
372 (goto-char pop3-read-point)
373 (if (looking-at "-ERR")
26b4a51d 374 (error "%s" (buffer-substring (point) (- match-end 2)))
eec82323
LMI
375 (if (not (looking-at "+OK"))
376 (progn (setq pop3-read-point match-end) nil)
377 (setq pop3-read-point match-end)
378 (if return
379 (buffer-substring (point) match-end)
380 t)
381 )))))
382
eec82323
LMI
383(defun pop3-clean-region (start end)
384 (setq end (set-marker (make-marker) end))
385 (save-excursion
386 (goto-char start)
387 (while (and (< (point) end) (search-forward "\r\n" end t))
388 (replace-match "\n" t t))
389 (goto-char start)
390 (while (and (< (point) end) (re-search-forward "^\\." end t))
391 (replace-match "" t t)
392 (forward-char)))
393 (set-marker end nil))
394
daaeed87
DL
395;; Copied from message-make-date.
396(defun pop3-make-date (&optional now)
397 "Make a valid date header.
398If NOW, use that time instead."
399 (require 'parse-time)
400 (let* ((now (or now (current-time)))
401 (zone (nth 8 (decode-time now)))
402 (sign "+"))
403 (when (< zone 0)
404 (setq sign "-")
405 (setq zone (- zone)))
406 (concat
407 (format-time-string "%d" now)
408 ;; The month name of the %b spec is locale-specific. Pfff.
409 (format " %s "
410 (capitalize (car (rassoc (nth 4 (decode-time now))
411 parse-time-months))))
412 (format-time-string "%Y %H:%M:%S " now)
413 ;; We do all of this because XEmacs doesn't have the %z spec.
414 (format "%s%02d%02d" sign (/ zone 3600) (/ (% zone 3600) 60)))))
415
eec82323
LMI
416(defun pop3-munge-message-separator (start end)
417 "Check to see if a message separator exists. If not, generate one."
418 (save-excursion
419 (save-restriction
420 (narrow-to-region start end)
421 (goto-char (point-min))
422 (if (not (or (looking-at "From .?") ; Unix mail
423 (looking-at "\001\001\001\001\n") ; MMDF
424 (looking-at "BABYL OPTIONS:") ; Babyl
425 ))
ae496852
SZ
426 (let* ((from (mail-strip-quoted-names (mail-fetch-field "From")))
427 (tdate (mail-fetch-field "Date"))
428 (date (split-string (or (and tdate
429 (not (string= "" tdate))
430 tdate)
431 (pop3-make-date))
432 " "))
433 (From_))
eec82323
LMI
434 ;; sample date formats I have seen
435 ;; Date: Tue, 9 Jul 1996 09:04:21 -0400 (EDT)
436 ;; Date: 08 Jul 1996 23:22:24 -0400
437 ;; should be
438 ;; Tue Jul 9 09:04:21 1996
996aa8c1
MB
439
440 ;; Fixme: This should use timezone on the date field contents.
eec82323 441 (setq date
ae496852 442 (cond ((not date)
23f87bed 443 "Tue Jan 1 00:00:0 1900")
ae496852 444 ((string-match "[A-Z]" (nth 0 date))
eec82323
LMI
445 (format "%s %s %s %s %s"
446 (nth 0 date) (nth 2 date) (nth 1 date)
447 (nth 4 date) (nth 3 date)))
448 (t
449 ;; this really needs to be better but I don't feel
450 ;; like writing a date to day converter.
451 (format "Sun %s %s %s %s"
452 (nth 1 date) (nth 0 date)
453 (nth 3 date) (nth 2 date)))
454 ))
455 (setq From_ (format "\nFrom %s %s\n" from date))
456 (while (string-match "," From_)
457 (setq From_ (concat (substring From_ 0 (match-beginning 0))
458 (substring From_ (match-end 0)))))
459 (goto-char (point-min))
dd5da9b8 460 (insert From_)
daaeed87
DL
461 (if (search-forward "\n\n" nil t)
462 nil
463 (goto-char (point-max))
464 (insert "\n"))
a2bb410e 465 (let ((size (- (point-max) (point))))
dd5da9b8
DL
466 (forward-line -1)
467 (insert (format "Content-Length: %s\n" size)))
468 )))))
eec82323
LMI
469
470;; The Command Set
471
472;; AUTHORIZATION STATE
473
474(defun pop3-user (process user)
475 "Send USER information to POP3 server."
476 (pop3-send-command process (format "USER %s" user))
477 (let ((response (pop3-read-response process t)))
478 (if (not (and response (string-match "+OK" response)))
2c2b732f 479 (error "USER %s not valid" user))))
eec82323
LMI
480
481(defun pop3-pass (process)
482 "Send authentication information to the server."
6748645f
LMI
483 (pop3-send-command process (format "PASS %s" pop3-password))
484 (let ((response (pop3-read-response process t)))
485 (if (not (and response (string-match "+OK" response)))
486 (pop3-quit process))))
487
488(defun pop3-apop (process user)
489 "Send alternate authentication information to the server."
eec82323
LMI
490 (let ((pass pop3-password))
491 (if (and pop3-password-required (not pass))
492 (setq pass
23f87bed 493 (read-passwd (format "Password for %s: " pop3-maildrop))))
eec82323 494 (if pass
01c52d31 495 (let ((hash (md5 (concat pop3-timestamp pass) nil nil 'binary)))
6748645f 496 (pop3-send-command process (format "APOP %s %s" user hash))
eec82323
LMI
497 (let ((response (pop3-read-response process t)))
498 (if (not (and response (string-match "+OK" response)))
499 (pop3-quit process)))))
500 ))
501
6748645f
LMI
502;; TRANSACTION STATE
503
eec82323
LMI
504(defun pop3-stat (process)
505 "Return the number of messages in the maildrop and the maildrop's size."
506 (pop3-send-command process "STAT")
507 (let ((response (pop3-read-response process t)))
e9bd5782
MB
508 (list (string-to-number (nth 1 (split-string response " ")))
509 (string-to-number (nth 2 (split-string response " "))))
eec82323
LMI
510 ))
511
512(defun pop3-list (process &optional msg)
ec7995fa
KY
513 "If MSG is nil, return an alist of (MESSAGE-ID . SIZE) pairs.
514Otherwise, return the size of the message-id MSG"
c9fc72fa 515 (pop3-send-command process (if msg
ec7995fa
KY
516 (format "LIST %d" msg)
517 "LIST"))
518 (let ((response (pop3-read-response process t)))
519 (if msg
520 (string-to-number (nth 2 (split-string response " ")))
521 (let ((start pop3-read-point) end)
88ed5ce8 522 (with-current-buffer (process-buffer process)
ec7995fa
KY
523 (while (not (re-search-forward "^\\.\r\n" nil t))
524 (pop3-accept-process-output process)
525 (goto-char start))
526 (setq pop3-read-point (point-marker))
527 (goto-char (match-beginning 0))
528 (setq end (point-marker))
529 (mapcar #'(lambda (s) (let ((split (split-string s " ")))
530 (cons (string-to-number (nth 0 split))
531 (string-to-number (nth 1 split)))))
4def29e7 532 (split-string (buffer-substring start end) "\r\n" t)))))))
eec82323
LMI
533
534(defun pop3-retr (process msg crashbuf)
535 "Retrieve message-id MSG to buffer CRASHBUF."
536 (pop3-send-command process (format "RETR %s" msg))
537 (pop3-read-response process)
538 (let ((start pop3-read-point) end)
88ed5ce8 539 (with-current-buffer (process-buffer process)
eec82323 540 (while (not (re-search-forward "^\\.\r\n" nil t))
8903a9c8 541 (pop3-accept-process-output process)
eec82323
LMI
542 (goto-char start))
543 (setq pop3-read-point (point-marker))
e62e7654
MB
544 ;; this code does not seem to work for some POP servers...
545 ;; and I cannot figure out why not.
546 ;; (goto-char (match-beginning 0))
547 ;; (backward-char 2)
548 ;; (if (not (looking-at "\r\n"))
549 ;; (insert "\r\n"))
550 ;; (re-search-forward "\\.\r\n")
eec82323
LMI
551 (goto-char (match-beginning 0))
552 (setq end (point-marker))
553 (pop3-clean-region start end)
554 (pop3-munge-message-separator start end)
88ed5ce8 555 (with-current-buffer crashbuf
eec82323
LMI
556 (erase-buffer))
557 (copy-to-buffer crashbuf start end)
558 (delete-region start end)
559 )))
560
561(defun pop3-dele (process msg)
562 "Mark message-id MSG as deleted."
563 (pop3-send-command process (format "DELE %s" msg))
564 (pop3-read-response process))
565
566(defun pop3-noop (process msg)
567 "No-operation."
568 (pop3-send-command process "NOOP")
569 (pop3-read-response process))
570
571(defun pop3-last (process)
572 "Return highest accessed message-id number for the session."
573 (pop3-send-command process "LAST")
574 (let ((response (pop3-read-response process t)))
e9bd5782 575 (string-to-number (nth 1 (split-string response " ")))
eec82323
LMI
576 ))
577
578(defun pop3-rset (process)
579 "Remove all delete marks from current maildrop."
580 (pop3-send-command process "RSET")
581 (pop3-read-response process))
582
583;; UPDATE
584
585(defun pop3-quit (process)
586 "Close connection to POP3 server.
587Tell server to remove all messages marked as deleted, unlock the maildrop,
588and close the connection."
589 (pop3-send-command process "QUIT")
590 (pop3-read-response process t)
591 (if process
88ed5ce8 592 (with-current-buffer (process-buffer process)
eec82323
LMI
593 (goto-char (point-max))
594 (delete-process process))))
595\f
596;; Summary of POP3 (Post Office Protocol version 3) commands and responses
597
598;;; AUTHORIZATION STATE
599
600;; Initial TCP connection
601;; Arguments: none
602;; Restrictions: none
603;; Possible responses:
604;; +OK [POP3 server ready]
605
606;; USER name
607;; Arguments: a server specific user-id (required)
608;; Restrictions: authorization state [after unsuccessful USER or PASS
609;; Possible responses:
610;; +OK [valid user-id]
611;; -ERR [invalid user-id]
612
613;; PASS string
614;; Arguments: a server/user-id specific password (required)
615;; Restrictions: authorization state, after successful USER
616;; Possible responses:
617;; +OK [maildrop locked and ready]
618;; -ERR [invalid password]
619;; -ERR [unable to lock maildrop]
620
01c52d31
MB
621;; STLS (RFC 2595)
622;; Arguments: none
623;; Restrictions: Only permitted in AUTHORIZATION state.
624;; Possible responses:
625;; +OK
626;; -ERR
627
eec82323
LMI
628;;; TRANSACTION STATE
629
630;; STAT
631;; Arguments: none
632;; Restrictions: transaction state
633;; Possible responses:
634;; +OK nn mm [# of messages, size of maildrop]
635
636;; LIST [msg]
637;; Arguments: a message-id (optional)
638;; Restrictions: transaction state; msg must not be deleted
639;; Possible responses:
640;; +OK [scan listing follows]
641;; -ERR [no such message]
642
643;; RETR msg
644;; Arguments: a message-id (required)
645;; Restrictions: transaction state; msg must not be deleted
646;; Possible responses:
647;; +OK [message contents follow]
648;; -ERR [no such message]
649
650;; DELE msg
651;; Arguments: a message-id (required)
652;; Restrictions: transaction state; msg must not be deleted
653;; Possible responses:
654;; +OK [message deleted]
655;; -ERR [no such message]
656
657;; NOOP
658;; Arguments: none
659;; Restrictions: transaction state
660;; Possible responses:
661;; +OK
662
663;; LAST
664;; Arguments: none
665;; Restrictions: transaction state
666;; Possible responses:
667;; +OK nn [highest numbered message accessed]
668
669;; RSET
670;; Arguments: none
671;; Restrictions: transaction state
672;; Possible responses:
673;; +OK [all delete marks removed]
674
675;;; UPDATE STATE
676
677;; QUIT
678;; Arguments: none
679;; Restrictions: none
680;; Possible responses:
681;; +OK [TCP connection closed]
dd5da9b8
DL
682
683(provide 'pop3)
684
685;;; pop3.el ends here