(eval-when-compile (require 'cl))
(require 'nnheader)
+(require 'timezone)
(require 'message)
(require 'custom)
(require 'gnus-util)
(eval-and-compile
(autoload 'gnus-error "gnus-util")
- (autoload 'gnus-buffer-live-p "gnus-util"))
+ (autoload 'gnus-buffer-live-p "gnus-util")
+ (autoload 'gnus-encode-coding-string "gnus-ems"))
(defgroup nnmail nil
"Reading mail with Gnus."
:group 'nnmail-retrieve
:type 'string)
-(defcustom nnmail-movemail-args nil
- "*Extra arguments to give to `nnmail-movemail-program' to move mail from the inbox.
-The default is nil"
- :group 'nnmail-files
- :group 'nnmail-retrieve
- :type 'string)
-
(defcustom nnmail-pop-password-required nil
"*Non-nil if a password is required when reading mail using POP."
:group 'nnmail-retrieve
:group 'nnmail-split
:type '(repeat (cons :format "%v" symbol regexp)))
-(defcustom nnmail-delete-incoming nil
+(defcustom nnmail-delete-incoming t
"*If non-nil, the mail backends will delete incoming files after
splitting."
:group 'nnmail-retrieve
(const warn)
(const delete)))
-(defcustom nnmail-extra-headers nil
- "*Extra headers to parse."
- :group 'nnmail
- :type '(repeat symbol))
-
-(defcustom nnmail-split-header-length-limit 1024
- "Header lines longer than this limit are excluded from the split function."
- :group 'nnmail
- :type 'integer)
-
;;; Internal variables.
(defvar nnmail-split-history nil
(defun nnmail-request-post (&optional server)
(mail-send-and-exit nil))
-(defvar nnmail-file-coding-system 'binary
+(defvar nnmail-file-coding-system 'raw-text
"Coding system used in nnmail.")
-(defvar nnmail-file-coding-system-1
- (if (string-match "nt" system-configuration)
- 'raw-text-dos 'binary)
- "Another coding system used in nnmail.")
-
-(defvar nnmail-incoming-coding-system
- mm-text-coding-system
- "Coding system used in reading inbox")
-
(defun nnmail-find-file (file)
"Insert FILE in server buffer safely."
(set-buffer nntp-server-buffer)
- (delete-region (point-min) (point-max))
+ (erase-buffer)
(let ((format-alist nil)
(after-insert-file-functions nil))
(condition-case ()
- (let ((coding-system-for-read nnmail-file-coding-system)
- (auto-mode-alist (nnheader-auto-mode-alist))
- (pathname-coding-system nnmail-file-coding-system))
- (insert-file-contents file)
+ (let ((pathname-coding-system 'binary))
+ (insert-file-contents-as-coding-system
+ nnmail-file-coding-system file)
t)
(file-error nil))))
(concat dir group "/")
;; If not, we translate dots into slashes.
(concat dir
- (mm-encode-coding-string
+ (gnus-encode-coding-string
(nnheader-replace-chars-in-string group ?. ?/)
nnmail-pathname-coding-system)
"/")))
(or file "")))
+(defun nnmail-date-to-time (date)
+ "Convert DATE into time."
+ (condition-case ()
+ (let* ((d1 (timezone-parse-date date))
+ (t1 (timezone-parse-time (aref d1 3))))
+ (apply 'encode-time
+ (mapcar (lambda (el)
+ (and el (string-to-number el)))
+ (list
+ (aref t1 2) (aref t1 1) (aref t1 0)
+ (aref d1 2) (aref d1 1) (aref d1 0)
+ (number-to-string
+ (* 60 (timezone-zone-to-minute
+ (or (aref d1 4) (current-time-zone)))))))))
+ ;; If we get an error, then we just return a 0 time.
+ (error (list 0 0))))
+
+(defun nnmail-time-less (t1 t2)
+ "Say whether time T1 is less than time T2."
+ (or (< (car t1) (car t2))
+ (and (= (car t1) (car t2))
+ (< (nth 1 t1) (nth 1 t2)))))
+
+(defun nnmail-days-to-time (days)
+ "Convert DAYS into time."
+ (let* ((seconds (* 1.0 days 60 60 24))
+ (rest (expt 2 16))
+ (ms (condition-case nil (floor (/ seconds rest))
+ (range-error (expt 2 16)))))
+ (list ms (condition-case nil (round (- seconds (* ms rest)))
+ (range-error (expt 2 16))))))
+
+(defun nnmail-time-since (time)
+ "Return the time since TIME, which is either an internal time or a date."
+ (when (stringp time)
+ ;; Convert date strings to internal time.
+ (setq time (nnmail-date-to-time time)))
+ (let* ((current (current-time))
+ (rest (when (< (nth 1 current) (nth 1 time))
+ (expt 2 16))))
+ (list (- (+ (car current) (if rest -1 0)) (car time))
+ (- (+ (or rest 0) (nth 1 current)) (nth 1 time)))))
+
;; Function rewritten from rmail.el.
(defun nnmail-move-inbox (inbox)
"Move INBOX to `nnmail-crash-box'."
nnmail-movemail-program exec-directory)
nil errors nil inbox tofile)
(when nnmail-internal-password
- (list nnmail-internal-password))
- (when nnmail-movemail-args
- nnmail-movemail-args))))))
+ (list nnmail-internal-password)))))))
(push inbox nnmail-moved-inboxes)
(if (and (not (buffer-modified-p errors))
(zerop result))
"Save GROUP-ASSOC in ACTIVE-FILE."
(let ((coding-system-for-write nnmail-active-file-coding-system))
(when file-name
- (with-temp-file file-name
+ (nnheader-temp-write file-name
(nnmail-generate-active group-assoc)))))
(defun nnmail-generate-active (alist)
(when (and (or (bobp)
(save-excursion
(forward-line -1)
- (eq (char-after) ?\n)))
+ (= (following-char) ?\n)))
(save-excursion
(forward-line 1)
(while (looking-at ">From \\|From ")
(when (and (or (bobp)
(save-excursion
(forward-line -1)
- (eq (char-after) ?\n)))
+ (= (following-char) ?\n)))
(save-excursion
(forward-line 1)
(while (looking-at ">From \\|From ")
(save-excursion
;; Insert the incoming file.
(set-buffer (get-buffer-create " *nnmail incoming*"))
+ (buffer-disable-undo (current-buffer))
(erase-buffer)
- (let ((nnheader-file-coding-system nnmail-incoming-coding-system))
- (nnheader-insert-file-contents incoming))
+ (nnheader-insert-file-contents incoming)
(unless (zerop (buffer-size))
(goto-char (point-min))
(save-excursion (run-hooks 'nnmail-prepare-incoming-hook))
(goto-char (point-min))
(while (not (eobp))
(end-of-line)
- (if (> (current-column) nnmail-split-header-length-limit)
- (delete-region (point) (progn (end-of-line) (point)))
+ (if (> (current-column) 1024)
+ (gnus-delete-line)
(forward-line 1)))
;; Allow washing.
(goto-char (point-min))
(insert (format "Xref: %s" (system-name)))
(while group-alist
(insert (format " %s:%d"
- (mm-encode-coding-string
- (caar group-alist)
- nnmail-pathname-coding-system)
+ (gnus-encode-coding-string (caar group-alist)
+ nnmail-pathname-coding-system)
(cdar group-alist)))
(setq group-alist (cdr group-alist)))
(insert "\n"))))
(set-buffer
(setq nnmail-cache-buffer
(get-buffer-create " *nnmail message-id cache*")))
+ (buffer-disable-undo (current-buffer))
(when (file-exists-p nnmail-message-id-cache-file)
(nnheader-insert-file-contents nnmail-message-id-cache-file))
(set-buffer-modified-p nil)
;; Let the backend save the article (or not).
(cond
((not duplication)
+ (nnmail-cache-insert message-id)
(funcall func (setq group-art
- (nreverse (nnmail-article-group artnum-func))))
- (nnmail-cache-insert message-id))
+ (nreverse (nnmail-article-group artnum-func)))))
((eq action 'delete)
(setq group-art nil))
((eq action 'warn)
;; This is an ange-ftp group, and we don't have any dates.
nil)
((numberp days)
- (setq days (days-to-time days))
+ (setq days (nnmail-days-to-time days))
;; Compare the time with the current time.
- (condition-case ()
- (time-less-p days (time-since time))
- (error nil)))))))
+ (nnmail-time-less days (nnmail-time-since time)))))))
(defvar nnmail-read-passwd nil)
(defun nnmail-read-passwd (prompt &rest args)
(apply 'format prompt args)
prompt)))
(unless nnmail-read-passwd
- (if (load "passwd" t)
+ (if (functionp 'read-passwd)
(setq nnmail-read-passwd 'read-passwd)
- (unless (fboundp 'ange-ftp-read-passwd)
- (autoload 'ange-ftp-read-passwd "ange-ftp"))
- (setq nnmail-read-passwd 'ange-ftp-read-passwd)))
+ (if (load "passwd" t)
+ (setq nnmail-read-passwd 'read-passwd)
+ (unless (fboundp 'ange-ftp-read-passwd)
+ (autoload 'ange-ftp-read-passwd "ange-ftp"))
+ (setq nnmail-read-passwd 'ange-ftp-read-passwd))))
(funcall nnmail-read-passwd prompt)))
(defun nnmail-check-syntax ()
(defun nnmail-write-region (start end filename &optional append visit lockname)
"Do a `write-region', and then set the file modes."
- (let ((coding-system-for-write nnmail-file-coding-system)
- (pathname-coding-system 'binary))
- (write-region start end filename append visit lockname)
+ (let ((pathname-coding-system 'binary))
+ (write-region-as-coding-system
+ nnmail-file-coding-system start end filename append visit lockname)
(set-file-modes filename nnmail-default-file-modes)))
;;;
(goto-char (point-min))
(while (re-search-forward "[^ \t=]+" nil t)
(setq name (match-string 0))
- (if (not (eq (char-after) ?=))
+ (if (not (= (following-char) ?=))
;; Implied "yes".
(setq value "yes")
(forward-char 1)
- (if (not (eq (char-after) ?\"))
+ (if (not (= (following-char) ?\"))
(if (not (looking-at "[^ \t]"))
;; Implied "no".
(setq value "no")
(defun nnmail-pop3-movemail (inbox crashbox)
"Function to move mail from INBOX on a pop3 server to file CRASHBOX."
(let ((pop3-maildrop
- (substring inbox (match-end (string-match "^po:" inbox))))
- (pop3-password
- (or nnmail-pop-password
- (nnmail-read-passwd
- (format "Password for %s: " inbox)))))
+ (substring inbox (match-end (string-match "^po:" inbox)))))
(pop3-movemail crashbox)))
(defun nnmail-within-headers-p ()