+ (insert From_)
+ (if (search-forward "\n\n" nil t)
+ nil
+ (goto-char (point-max))
+ (insert "\n"))
+ (narrow-to-region (point) (point-max))
+ (let ((size (- (point-max) (point-min))))
+ (goto-char (point-min))
+ (widen)
+ (forward-line -1)
+ (insert (format "Content-Length: %s\n" size)))
+ )))))
+
+;; UIDL support
+
+(defun pop3-get-message-numbers (process)
+ "Get the list of message numbers and lengths to retrieve via PROCESS."
+ ;; we use the LIST comand first anyway to get the message lengths.
+ ;; then if we're leaving mail on the server, see if the UIDL command
+ ;; is implemented. if so, we use it to get the message number list.
+ (let* ((messages (pop3-list process))
+ (total (or (pop messages) 0))
+ (uidl (if pop3-leave-mail-on-server
+ (pop3-get-uidl process)))
+ out)
+ (while messages
+ ;; only retrieve messages matching our regexp or in the uidl list
+ (when (and
+ ;; remove elements not in the uidl, this assumes the uidl is short
+ (or (not (and pop3-leave-mail-on-server
+ (cdr (assoc pop3-mailhost pop3-uidl-support))))
+ (memq (caar messages) uidl))
+ (caar messages)
+ ;; don't download messages that are too large
+ (not (and pop3-maximum-message-size
+ (> (cdar messages) pop3-maximum-message-size)))
+ (not (and pop3-except-header-regexp
+ (string-match pop3-except-header-regexp
+ (pop3-top process (caar messages) 0)))))
+ (push (car messages) out))
+ (setq messages (cdr messages)))
+ (cons total (nreverse out))))
+
+(defun pop3-get-uidl (process)
+ "Use PROCESS to get a list of unread message numbers."
+ (let ((messages (pop3-uidl process))
+ (support (assoc pop3-mailhost pop3-uidl-support))
+ uidl)
+ (if support
+ (setcdr support (and messages t))
+ (push (cons pop3-mailhost (and messages t))
+ pop3-uidl-support))
+ (when messages
+ (save-excursion
+ (with-temp-buffer
+ (when (file-readable-p pop3-uidl-file-name)
+ (insert-file-contents pop3-uidl-file-name))
+ (goto-char (point-min))
+ (while (looking-at "\\([^ \n\t]+\\)")
+ (set (intern (match-string 1) pop3-uidl-obarray)
+ (cons nil t))
+ (forward-line 1))))
+ (dolist (message (cdr messages))
+ (if (setq uidl (intern-soft (cdr message) pop3-uidl-obarray))
+ (setcar (symbol-value uidl) (car message))
+ (set (intern (cdr message) pop3-uidl-obarray)
+ (cons (car message) nil))))
+ (pop3-get-unread-message-numbers))))
+
+(defun pop3-get-unread-message-numbers ()
+ "Return a sorted list of unread msg numbers to retrieve."
+ (let (nums)
+ (mapatoms (lambda (atom)
+ (if (not (cdr (symbol-value atom)))
+ (push (car (symbol-value atom)) nums)))
+ pop3-uidl-obarray)
+ (sort nums '<)))
+
+(defun pop3-save-uidls ()
+ "Save the updated UIDLs to disk for use next time."
+ (when (and pop3-leave-mail-on-server
+ ;; UIDL hash table is non-empty
+ (let ((len (length pop3-uidl-obarray)))
+ (while (< 0 len)
+ (setq len (if (symbolp (aref pop3-uidl-obarray (1- len)))
+ -1 (1- len))))
+ (minusp len)))
+ (when (file-readable-p pop3-uidl-file-name)
+ (copy-file pop3-uidl-file-name
+ (concat pop3-uidl-file-name ".old")
+ 'overwrite 'keeptime))
+ (save-excursion
+ (with-temp-file pop3-uidl-file-name
+ (mapatoms
+ (lambda (atom)
+ (when (car (symbol-value atom))
+ (insert (format "%s\n" atom))))
+ pop3-uidl-obarray)))
+ (fillarray pop3-uidl-obarray 0)))
+