X-Git-Url: http://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fmail-source.el;h=51b9c9115455994aaba23f4e1d9234a7c26c7305;hb=1c2ed0ce5abe2181e51f777171f8cd40a547e5a9;hp=422ef318a5789961f7b0d63bb8a0344d6a032331;hpb=72c34c3f8693f8f5da5785fbb0b504221d6c1b7f;p=gnus diff --git a/lisp/mail-source.el b/lisp/mail-source.el index 422ef318a..51b9c9115 100644 --- a/lisp/mail-source.el +++ b/lisp/mail-source.el @@ -1,7 +1,6 @@ ;;; mail-source.el --- functions for fetching mail -;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, -;; 2008, 2009, 2010 Free Software Foundation, Inc. +;; Copyright (C) 1999-2014 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Keywords: news, mail @@ -25,16 +24,12 @@ ;;; Code: -;; For Emacs < 22.2. -(eval-and-compile - (unless (fboundp 'declare-function) (defmacro declare-function (&rest r)))) - (require 'format-spec) (eval-when-compile (require 'cl) (require 'imap)) -(autoload 'auth-source-user-or-password "auth-source") -(autoload 'pop3-streaming-movemail "pop3") +(autoload 'auth-source-search "auth-source") +(autoload 'pop3-movemail "pop3") (autoload 'pop3-get-message-count "pop3") (autoload 'nnheader-cancel-timer "nnheader") (require 'mm-util) @@ -64,7 +59,7 @@ This variable is a list of mail source specifiers. See Info node `(gnus)Mail Source Specifiers'." :group 'mail-source - :version "23.1" ;; No Gnus + :version "24.4" :link '(custom-manual "(gnus)Mail Source Specifiers") :type `(choice (const :tag "None" nil) @@ -160,7 +155,18 @@ See Info node `(gnus)Mail Source Specifiers'." :value nil (const :tag "Clear" nil) (const starttls) - (const :tag "SSL/TLS" ssl))))) + (const :tag "SSL/TLS" ssl))) + (group :inline t + (const :format "" :value :leave) + (choice :format "\ +%{Leave mail on server%}:\n\t\t%[Value Menu%] %v" + :value nil + (const :tag "\ +Don't leave mails" nil) + (const :tag "\ +Leave all mails" t) + (number :tag "\ +Leave mails for this many days" :value 14))))) (cons :tag "Maildir (qmail, postfix...)" (const :format "" maildir) (checklist :tag "Options" :greedy t @@ -217,34 +223,6 @@ See Info node `(gnus)Mail Source Specifiers'." (const :format "" :value :dontexpunge) (boolean :tag "Dontexpunge")) - (group :inline t - (const :format "" :value :plugged) - (boolean :tag "Plugged")))) - (cons :tag "Webmail server" - (const :format "" webmail) - (checklist :tag "Options" :greedy t - (group :inline t - (const :format "" :value :subtype) - ;; Should be generated from - ;; `webmail-type-definition', but we - ;; can't require webmail without W3. - (choice :tag "Subtype" - :value hotmail - (const hotmail) - (const yahoo) - (const netaddress) - (const netscape) - (const my-deja))) - (group :inline t - (const :format "" :value :user) - (string :tag "User")) - (group :inline t - (const :format "" :value :password) - (string :tag "Password")) - (group :inline t - (const :format "" - :value :dontexpunge) - (boolean :tag "Dontexpunge")) (group :inline t (const :format "" :value :plugged) (boolean :tag "Plugged")))))))) @@ -361,6 +339,7 @@ Common keywords should be listed here.") (:prescript) (:prescript-delay) (:postscript) + ;; note server and port need to come before user and password (:server (getenv "MAILHOST")) (:port 110) (:user (or (user-login-name) (getenv "LOGNAME") (getenv "USER"))) @@ -368,12 +347,14 @@ Common keywords should be listed here.") (:function) (:password) (:authentication password) - (:stream nil)) + (:stream nil) + (:leave)) (maildir (:path (or (getenv "MAILDIR") "~/Maildir/")) (:subdirs ("cur" "new")) (:function)) (imap + ;; note server and port need to come before user and password (:server (getenv "MAILHOST")) (:port) (:stream) @@ -387,13 +368,7 @@ Common keywords should be listed here.") (:prescript) (:prescript-delay) (:postscript) - (:dontexpunge)) - (webmail - (:subtype hotmail) - (:user (or (user-login-name) (getenv "LOGNAME") (getenv "USER"))) - (:password) - (:dontexpunge) - (:authentication password))) + (:dontexpunge))) "Mapping from keywords to default values. All keywords that can be used must be listed here.")) @@ -402,8 +377,7 @@ All keywords that can be used must be listed here.")) (directory mail-source-fetch-directory) (pop mail-source-fetch-pop) (maildir mail-source-fetch-maildir) - (imap mail-source-fetch-imap) - (webmail mail-source-fetch-webmail)) + (imap mail-source-fetch-imap)) "A mapping from source type to fetcher function.") (defvar mail-source-password-cache nil) @@ -453,42 +427,66 @@ the `mail-source-keyword-map' variable." (put 'mail-source-bind 'lisp-indent-function 1) (put 'mail-source-bind 'edebug-form-spec '(sexp body)) -;; TODO: use the list format for auth-source-user-or-password modes (defun mail-source-set-1 (source) (let* ((type (pop source)) - (defaults (cdr (assq type mail-source-keyword-map))) - default value keyword auth-info user-auth pass-auth) + (defaults (cdr (assq type mail-source-keyword-map))) + (search '(:max 1)) + found default value keyword auth-info user-auth pass-auth) + + ;; append to the search the useful info from the source and the defaults: + ;; user, host, and port + + ;; the msname is the mail-source parameter + (dolist (msname '(:server :user :port)) + ;; the asname is the auth-source parameter + (let* ((asname (case msname + (:server :host) ; auth-source uses :host + (t msname))) + ;; this is the mail-source default + (msdef1 (or (plist-get source msname) + (nth 1 (assoc msname defaults)))) + ;; ...evaluated + (msdef (mail-source-value msdef1))) + (setq search (append (list asname + (if msdef msdef t)) + search)))) + ;; if the port is unknown yet, get it from the mail-source type + (unless (plist-get search :port) + (setq search (append (list :port (symbol-name type))))) + (while (setq default (pop defaults)) ;; for each default :SYMBOL, set SYMBOL to the plist value for :SYMBOL ;; using `mail-source-value' to evaluate the plist value (set (mail-source-strip-keyword (setq keyword (car default))) - ;; note the following reasons for this structure: - ;; 1) the auth-sources user and password override everything - ;; 2) it avoids macros, so it's cleaner - ;; 3) it falls through to the mail-sources and then default values - (cond - ((and - (eq keyword :user) - (setq user-auth - (nth 0 (auth-source-user-or-password - '("login" "password") - ;; this is "host" in auth-sources - (if (boundp 'server) (symbol-value 'server) "") - type)))) - user-auth) - ((and - (eq keyword :password) - (setq pass-auth - (nth 1 - (auth-source-user-or-password - '("login" "password") - ;; this is "host" in auth-sources - (if (boundp 'server) (symbol-value 'server) "") - type)))) - pass-auth) - (t (if (setq value (plist-get source keyword)) - (mail-source-value value) - (mail-source-value (cadr default))))))))) + ;; note the following reasons for this structure: + ;; 1) the auth-sources user and password override everything + ;; 2) it avoids macros, so it's cleaner + ;; 3) it falls through to the mail-sources and then default values + (cond + ((and + (eq keyword :user) + (setq user-auth (plist-get + ;; cache the search result in `found' + (or found + (setq found (nth 0 (apply 'auth-source-search + search)))) + :user))) + user-auth) + ((and + (eq keyword :password) + (setq pass-auth (plist-get + ;; cache the search result in `found' + (or found + (setq found (nth 0 (apply 'auth-source-search + search)))) + :secret))) + ;; maybe set the password to the return of the :secret function + (if (functionp pass-auth) + (setq pass-auth (funcall pass-auth)) + pass-auth)) + (t (if (setq value (plist-get source keyword)) + (mail-source-value value) + (mail-source-value (cadr default))))))))) (eval-and-compile (defun mail-source-bind-common-1 () @@ -536,6 +534,8 @@ See `mail-source-bind'." (t value))) +(autoload 'nnheader-message "nnheader") + (defun mail-source-fetch (source callback &optional method) "Fetch mail from SOURCE and call CALLBACK zero or more times. CALLBACK will be called with the name of the file where (some of) @@ -544,11 +544,16 @@ Return the number of files that were found." (mail-source-bind-common source (if (or mail-source-plugged plugged) (save-excursion - (nnheader-message 4 "%sReading incoming mail from %s..." - (if method - (format "%s: " method) - "") - (car source)) + ;; Special-case the `file' handler since it's so common and + ;; just adds noise. + (when (or (not (eq (car source) 'file)) + (mail-source-bind (file source) + (file-exists-p path))) + (nnheader-message 4 "%sReading incoming mail from %s..." + (if method + (format "%s: " method) + "") + (car source))) (let ((function (cadr (assq (car source) mail-source-fetcher-alist))) (found 0)) (unless function @@ -624,6 +629,10 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) 0) (funcall callback mail-source-crash-box info))) +(autoload 'gnus-float-time "gnus-util") + +(defvar mail-source-incoming-last-checked-time nil) + (defun mail-source-delete-crash-box () (when (file-exists-p mail-source-crash-box) ;; Delete or move the incoming mail out of the way. @@ -639,9 +648,16 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) (rename-file mail-source-crash-box incoming t) ;; remove old incoming files? (when (natnump mail-source-delete-incoming) - (mail-source-delete-old-incoming - mail-source-delete-incoming - mail-source-delete-old-incoming-confirm)))))) + ;; Don't check for old incoming files more than once per day to + ;; save a lot of file accesses. + (when (or (null mail-source-incoming-last-checked-time) + (> (gnus-float-time + (time-since mail-source-incoming-last-checked-time)) + (* 24 60 60))) + (setq mail-source-incoming-last-checked-time (current-time)) + (mail-source-delete-old-incoming + mail-source-delete-incoming + mail-source-delete-old-incoming-confirm))))))) (defun mail-source-movemail (from to) "Move FROM to TO using movemail." @@ -713,12 +729,6 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) ;; Return whether we moved successfully or not. to))) -(defun mail-source-movemail-and-remove (from to) - "Move FROM to TO using movemail, then remove FROM if empty." - (or (not (mail-source-movemail from to)) - (not (zerop (nth 7 (file-attributes from)))) - (delete-file from))) - (defun mail-source-fetch-with-program (program) (eq 0 (call-process shell-file-name nil nil nil shell-command-switch program))) @@ -795,6 +805,10 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) prescript-delay) (let ((from (format "%s:%s:%s" server user port)) (mail-source-string (format "pop:%s@%s" user server)) + (process-environment (if server + (cons (concat "MAILHOST=" server) + process-environment) + process-environment)) result) (when (eq authentication 'password) (setq password @@ -802,8 +816,6 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) (cdr (assoc from mail-source-password-cache)) (read-passwd (format "Password for %s at %s: " user server))))) - (when server - (setenv "MAILHOST" server)) (setq result (cond (program @@ -823,13 +835,12 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) (pop3-port port) (pop3-authentication-scheme (if (eq authentication 'apop) 'apop 'pass)) - (pop3-stream-type stream)) + (pop3-stream-type stream) + (pop3-leave-mail-on-server leave)) (if (or debug-on-quit debug-on-error) - (save-excursion (pop3-streaming-movemail - mail-source-crash-box)) + (save-excursion (pop3-movemail mail-source-crash-box)) (condition-case err - (save-excursion (pop3-streaming-movemail - mail-source-crash-box)) + (save-excursion (pop3-movemail mail-source-crash-box)) (error ;; We nix out the password in case the error ;; was because of a wrong password being given. @@ -864,6 +875,10 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) (mail-source-bind (pop source) (let ((from (format "%s:%s:%s" server user port)) (mail-source-string (format "pop:%s@%s" user server)) + (process-environment (if server + (cons (concat "MAILHOST=" server) + process-environment) + process-environment)) result) (when (eq authentication 'password) (setq password @@ -873,8 +888,6 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile) (format "Password for %s at %s: " user server)))) (unless (assoc from mail-source-password-cache) (push (cons from password) mail-source-password-cache))) - (when server - (setenv "MAILHOST" server)) (setq result (cond ;; No easy way to check whether mail is waiting for these. @@ -981,7 +994,7 @@ This only works when `display-time' is enabled." (if on (progn (require 'time) - ;; display-time-mail-function is an Emacs 21 feature. + ;; display-time-mail-function is an Emacs feature. (setq display-time-mail-function #'mail-source-new-mail-p) ;; Set up the main timer. (setq mail-source-report-new-mail-timer @@ -1011,6 +1024,7 @@ This only works when `display-time' is enabled." (dolist (file (directory-files (concat path subdir) t)) (when (and (not (file-directory-p file)) (not (if function + ;; `function' should return nil if successful. (funcall function file mail-source-crash-box) (let ((coding-system-for-write mm-text-coding-system) @@ -1029,7 +1043,8 @@ This only works when `display-time' is enabled." ;;; (insert "\n\n") ;; MMDF mail format (insert "\001\001\001\001\n")) - (delete-file file))))) + (delete-file file) + nil)))) (incf found (mail-source-callback callback file)) (mail-source-delete-crash-box))))) found))) @@ -1126,30 +1141,6 @@ This only works when `display-time' is enabled." ?s server ?P port ?u user)) found))) -(autoload 'webmail-fetch "webmail") - -(defun mail-source-fetch-webmail (source callback) - "Fetch for webmail source." - (mail-source-bind (webmail source) - (let ((mail-source-string (format "webmail:%s:%s" subtype user)) - (webmail-newmail-only dontexpunge) - (webmail-move-to-trash-can (not dontexpunge))) - (when (eq authentication 'password) - (setq password - (or password - (cdr (assoc (format "webmail:%s:%s" subtype user) - mail-source-password-cache)) - (read-passwd - (format "Password for %s at %s: " user subtype)))) - (when (and password - (not (assoc (format "webmail:%s:%s" subtype user) - mail-source-password-cache))) - (push (cons (format "webmail:%s:%s" subtype user) password) - mail-source-password-cache))) - (webmail-fetch mail-source-crash-box subtype user password) - (mail-source-callback callback (symbol-name subtype)) - (mail-source-delete-crash-box)))) - (provide 'mail-source) ;;; mail-source.el ends here