+2003-03-23 Simon Josefsson <jas@extundo.com>
+
+ * GNUS-NEWS: Add IDNA. Add TLS. Fix USEFOR reference.
+
+2003-03-22 Frank Schmitt <ich@frank-schmitt.net>
+
+ * make.bat: Redone from scratch; supports both Emacs and XEmacs
+ now; correctly generate gnus-load.el; check for errors; use
+ makeinfo if available, infohack.el if it isn't; be less verbose
+ when copying files; copy files from etc/gnus and etc/smilies, too
+
+2003-03-22 Frank Schmitt <ich@frank-schmitt.net>
+
+ * make-x.bat: Removed, make.bat does its job now.
+
+2003-03-22 Frank Schmitt <ich@frank-schmitt.net>
+
+ * etc/gnus-tut.txt: Include Gnus FAQ from http://my.gnus.org.
+
2003-02-19 Reiner Steib <Reiner.Steib@gmx.de>
* GNUS-NEWS: Renamed `gnus-unsightly-citation-regexp' to
\f
* Changes in Oort Gnus
+** TLS wrapper shipped with Gnus
+
+TLS/SSL is now supported in IMAP and NNTP via tls.el and GNUTLS. The
+old TLS/SSL support via (external third party) ssl.el and OpenSSL
+still works.
+
+** New make.bat for compiling and installing Gnus under MS Windows
+
+Use make.bat if you want to install Gnus under MS Windows, the first
+argument to the batch-program should be the directory where xemacs.exe
+respectively emacs.exe is located, iff you want to install Gnus after
+compiling it, give make.bat /copy as the second parameter.
+
+Make.bat has been rewritten from scratch, it now features automatic
+recognition of XEmacs and GNU Emacs, generates gnus-load.el, checks if
+errors occur while compilation and generation of info files and reports
+them at the end of the build process. It now uses makeinfo if it is
+available and falls back to infohack.el otherwise. Make.bat should now
+install all files which are necessary to run Gnus and be generally a
+complete replacement for the "configure; make; make install" cycle used
+under Unix systems.
+
+The new make.bat makes make-x.bat superfluous, so it has been removed.
+
+** Support for non-ASCII domain names
+
+Message supports non-ASCII domain names in From:, To: and Cc: and will
+query you whether to perform encoding when you try to send a message.
+The variable `message-use-idna' controls this. Gnus will also decode
+non-ASCII domain names in From:, To: and Cc: when you view a message.
+The variable `gnus-use-idna' controls this.
+
** Better handling of Microsoft citation styles
Gnus now tries to recognize the mangled header block that some Microsoft
** Group names are treated as UTF-8 by default.
-This is supposedly what USEFOR wants to migrate to. See
+This is supposedly what USEFOR wanted to migrate to. See
`gnus-group-name-charset-group-alist' and
`gnus-group-name-charset-method-alist' for customization.
+2003-03-19 Simon Josefsson <jas@extundo.com>
+
+ * gnus-idna.el: Update.
+
2003-03-11 Teodor Zlatanov <tzz@lifelogs.com>
* hashcash.el (hashcash-version, hashcash-insert-payment): patch
;;; Commentary:
-;; This package implement crude support for internationalized
-;; (non-ASCII) domain names in Gnus. It is meant as a proof of
-;; concept.
+;; This package implement crude support for internationalized domain
+;; names in Gnus.
;; Theory of Operation:
;; using IDNA ToASCII() when you send mail using Message. The hook
;; used is message-send-hook.
;;
-;; For incoming articles, when QP in headers are decoded, it searches
-;; for "xn--" prefixes and decode them using IDNA ToUnicode(). The
-;; hook used is gnus-article-decode-hook.
+;; For incoming articles, when QP in headers are decoded (i.e., when
+;; gnus-article-decode-hook is invoked), it searches for "xn--"
+;; prefixes and decode them if they are found inside (heuristically
+;; determined) RHS in From:, To: and Cc:, using IDNA ToUnicode().
;; Usage:
-;; Simply put (require 'gnus-idna) in your ~/.gnus or ~/.emacs and it
-;; should work. You need to install GNU Libidn (0.1.11 or later) and
-;; make sure the idna.el installed by it is found by emacs.
+;; You need to install GNU Libidn (0.1.11 or later) and make sure the
+;; idna.el installed by it is found by emacs.
+
+;; If you use an older Gnus, you may need to put the following in your
+;; init scripts too, but keep in mind that most older Gnuses either
+;; doesn't have these hooks or are buggy in other regards so it
+;; doesn't work anyway. (The window of Gnus versions that this works
+;; on is a few weeks during the Oort CVS in winter 2003.) Update to a
+;; recent Gnus instead, then you don't have to do anything.
+
+;; (add-hook 'message-send-hook 'message-idna-to-ascii-rhs)
+;; (add-hook 'gnus-article-decode-hook 'gnus-idna-to-unicode-rhs 'append)
+
+;; Revision history:
+
+;; 2003-02-26 Initial release
+;;
+;; 2003-03-19 Cleanup. Fixes a bug that may corrupt outgoing mail if
+;; it contains From:, To: or Cc: headers in the body.
;;; Code:
(require 'gnus)
+(require 'gnus-util)
(require 'rfc822)
-(require 'idna)
-
-(eval-and-compile
- (cond
- ((fboundp 'replace-in-string)
- (defalias 'gnus-replace-in-string 'replace-in-string))
- ((fboundp 'replace-regexp-in-string)
- (defun gnus-replace-in-string (string regexp newtext &optional literal)
- (replace-regexp-in-string regexp newtext string nil literal)))
- (t
- (defun gnus-replace-in-string (string regexp newtext &optional literal)
- (let ((start 0) tail)
- (while (string-match regexp string start)
- (setq tail (- (length string) (match-end 0)))
- (setq string (replace-match newtext nil literal string))
- (setq start (- (length string) tail))))
- string))))
-
-(defun gnus-idna-to-ascii-rhs-1 (header)
- (save-excursion
- (save-restriction
- (let (address header-data new-header-data rhs ace)
+(autoload 'idna-to-ascii "idna")
+(autoload 'idna-to-unicode "idna")
+
+(defcustom message-use-idna 'ask
+ "Whether to encode non-ASCII in domain names into ASCII according to IDNA."
+ :type '(choice (const :tag "Ask" ask)
+ (const :tag "Never" nil)
+ (const :tag "Always" t)))
+
+(defun message-idna-inside-rhs-p ()
+ "Return t iff point is inside a RHS (heuristically).
+Only works properly if header contains mailbox-list or address-list.
+I.e., calling it on a Subject: header is useless."
+ (if (re-search-backward
+ "[\\\n\r\t ]" (save-excursion (search-backward "@" nil t)) t)
+ ;; whitespace between @ and point
+ nil
+ (let ((dquote 1) (paren 1))
+ (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote))
+ (incf dquote))
+ (while (save-excursion (re-search-backward "[^\\]\(" nil t paren))
+ (incf paren))
+ (and (= (% dquote 2) 1) (= (% paren 2) 1)))))
+
+(defun message-idna-to-ascii-rhs-1 (header)
+ "Interactively potentially IDNA encode domain names in HEADER."
+ (let (rhs ace start end startpos endpos)
+ (goto-char (point-min))
+ (setq start (re-search-forward (concat "^" header) nil t)
+ end (or (save-excursion (re-search-forward "^[ \t]" nil t))
+ (point-max)))
+ (when (and start end)
+ (while (re-search-forward "@\\([^ \t\r\n>]+\\)" end t)
+ (setq rhs (match-string-no-properties 1)
+ startpos (match-beginning 1)
+ endpos (match-end 1))
+ (when (save-match-data
+ (and (message-idna-inside-rhs-p)
+ (setq ace (idna-to-ascii rhs))
+ (not (string= rhs ace))
+ (if (eq message-use-idna 'ask)
+ (unwind-protect
+ (progn
+ (replace-highlight startpos endpos)
+ (y-or-n-p
+ (format "Replace with `%s'? " ace)))
+ (message "")
+ (replace-dehighlight))
+ message-use-idna)))
+ (replace-match (concat "@" ace)))))))
+
+;;;###autoload
+(defun message-idna-to-ascii-rhs ()
+ "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
+See `message-idna-encode'."
+ (interactive)
+ (when (condition-case nil (require 'idna) (file-error))
+ (save-excursion
+ (save-restriction
(message-narrow-to-head)
- (setq header-data (message-fetch-field header))
- (when header-data
- (dolist (element (message-tokenize-header header-data))
- (setq address (car (rfc822-addresses element)))
- (when (string-match "\\(.*\\)@\\([^@]+\\)" address)
- (setq ace (if (setq rhs (match-string 2 address))
- (idna-to-ascii rhs)))
- (push (if (string= rhs ace)
- element
- (gnus-replace-in-string
- element (regexp-quote rhs) ace t))
- new-header-data)))
- (message-remove-header header)
- (message-position-on-field header)
- (dolist (addr (reverse new-header-data))
- (insert addr ", "))
- (when new-header-data
- (delete-backward-char 2)))))))
-
-(defun gnus-idna-to-ascii-rhs ()
- (gnus-idna-to-ascii-rhs-1 "From")
- (gnus-idna-to-ascii-rhs-1 "To")
- (gnus-idna-to-ascii-rhs-1 "Cc"))
-
-(add-hook 'message-send-hook 'gnus-idna-to-ascii-rhs)
+ (message-idna-to-ascii-rhs-1 "From")
+ (message-idna-to-ascii-rhs-1 "To")
+ (message-idna-to-ascii-rhs-1 "Cc")))))
+;;;###autoload
(defun gnus-idna-to-unicode-rhs ()
- (let ((inhibit-point-motion-hooks t)
- buffer-read-only)
- (goto-char (point-min))
- (while (re-search-forward "xn--.*[ \t\n\r.,<>()@!]" nil t)
- ;(or (eobp) (forward-char))
- (let (ace unicode)
- (when (setq ace (match-string 0))
- (setq unicode (idna-to-unicode ace))
- (unless (string= ace unicode)
- (replace-match unicode)))))))
-
-(add-hook 'gnus-article-decode-hook 'gnus-idna-to-unicode-rhs 'append)
+ "Decode IDNA strings in RHS in From:, To: and Cc: headers in current buffer."
+ (when (condition-case nil (require 'idna) (file-error))
+ (let ((inhibit-point-motion-hooks t)
+ buffer-read-only)
+ (article-narrow-to-head)
+ (goto-char (point-min))
+ (while (re-search-forward "\\(xn--.*\\)[ \t\n\r,>]" nil t)
+ (let (ace unicode)
+ (when (save-match-data
+ (and (setq ace (match-string 1))
+ (save-excursion (and (re-search-backward "^[^ \t]" nil t)
+ (looking-at "From\\|To\\|Cc")))
+ (save-excursion (backward-char)
+ (message-idna-inside-rhs-p))
+ (setq unicode (idna-to-unicode ace))))
+ (unless (string= ace unicode)
+ (replace-match unicode nil nil nil 1))))))))
(provide 'gnus-idna)
is where to post the questions.
+From fschmitt Sat Mar 22 18:13:00 2003
+From: faq@my.gnus.org (Gnus FAQ team)
+Date: Sat Mar 22 18:13:00 2003
+Subject: Gnus FAQ
+Message-ID: <lars-doc8@eyesore.no>
+
+This is the text version of the Gnus FAQ, see http://my.gnus.org for
+the up to date version of this document, there you can also find a
+html version and various other formats.
+
+Frequently Asked Questions
+
+Table of Contents
+
+Introduction
+Frequently Asked Questions with Answers
+Glossary
+
+Abstract
+
+This is the new Gnus Frequently Asked Questions list. If you have a
+Web browser, the official hypertext version is at http://
+my.gnus.org/FAQ/ [http://my.gnus.org/FAQ/], the Docbook source is
+available from http://sourceforge.net [http://sourceforge.net/
+projects/gnus/].
+
+Please submit features and suggestions to the FAQ discussion list
+[mailto:faq-discuss@my.gnus.org]. The list is protected against
+junk mail with qconfirm [http://smarden.org/qconfirm/index.html].
+As a subscriber, your submissions will automatically pass. You can
+also subscribe to the list by sending a blank email to
+faq-discuss-subscribe@my.gnus.org
+[mailto:faq-discuss-subscribe@my.gnus.org] and browse the archive.
+
+Introduction
+
+This is the Gnus Frequently Asked Questions list.
+
+Gnus is a Usenet Newsreader and Electronic Mail User Agent
+implemented as a part of Emacs. It's been around in some form for
+almost a decade now, and has been distributed as a standard part of
+Emacs for much of that time. Gnus 5 is the latest (and greatest)
+incarnation. The original version was called GNUS, and was written
+by Masanobu UMEDA. When autumn crept up in '94, Lars Magne
+Ingebrigtsen grew bored and decided to rewrite Gnus.
+
+Its biggest strength is the fact that it is extremely customizable.
+It is somewhat intimidating at first glance, but most of the
+complexity can be ignored until you're ready to take advantage of
+it. If you receive a reasonable volume of e-mail (you're on various
+mailing lists), or you would like to read high-volume mailing lists
+but cannot keep up with them, or read high volume newsgroups or are
+just bored, then Gnus is what you want.
+
+This FAQ was maintained by Justin Sheehy until March 2002. He would
+like to thank Steve Baur and Per Abrahamsen for doing a wonderful
+job with this FAQ before him. We would like to do the same -
+thanks, Justin!
+
+If you have a Web browser, the official hypertext version is at:
+http://my.gnus.org/FAQ/ [http://my.gnus.org/FAQ/]. This version is
+much nicer than the unofficial hypertext versions that are archived
+at Utrecht, Oxford, Smart Pages, Ohio State, and other FAQ
+archives. See the resources question below if you want information
+on obtaining it in another format.
+
+The information contained here was compiled with the assistance of
+the Gnus development mailing list, and any errors or misprints are
+the my.gnus.org team's fault, sorry.
+
+Frequently Asked Questions with Answers
+
+1. Installation FAQ
+
+ 1.1. What is the latest version of Gnus?
+ 1.2. Where and how to get Gnus?
+ 1.3. What to do with the tarball now?
+ 1.4. Which version of Emacs do I need?
+ 1.5. How do I run Gnus on both Emacs and XEmacs?
+
+2. Startup / Group buffer
+
+ 2.1. Every time I start Gnus I get a message "Gnus auto-save
+ file exists. Do you want to read it?", what does this mean
+ and how to prevent it?
+ 2.2. Gnus doesn't remember which groups I'm subscribed to,
+ what's this?
+ 2.3. How to change the format of the lines in Group buffer?
+ 2.4. My group buffer becomes a bit crowded, is there a way to
+ sort my groups into categories so I can easier browse
+ through them?
+ 2.5. How to manually sort the groups in Group buffer? How to
+ sort the groups in a topic?
+
+3. Getting Messages
+
+ 3.1. I just installed Gnus, started it via M-x gnus but it only
+ says "nntp (news) open error", what to do?
+ 3.2. I'm working under Windows and have no idea what ~/.gnus
+ means.
+ 3.3. My news server requires authentication, how to store user
+ name and password on disk?
+ 3.4. Gnus seems to start up OK, but I can't find out how to
+ subscribe to a group.
+ 3.5. Gnus doesn't show all groups / Gnus says I'm not allowed
+ to post on this server as well as I am, what's that?
+ 3.6. I want Gnus to fetch news from several servers, is this
+ possible?
+ 3.7. And how about local spool files?
+ 3.8. OK, reading news works now, but I want to be able to read
+ my mail with Gnus, too. How to do it?
+ 3.9. And what about IMAP?
+ 3.10. At the office we use one of those MS Exchange servers,
+ can I use Gnus to read my mail from it?
+ 3.11. Can I tell Gnus not to delete the mails on the server it
+ retrieves via POP3?
+
+4. Reading messages
+
+ 4.1. When I enter a group, all read messages are gone. How to
+ view them again?
+ 4.2. How to tell Gnus to show an important message every time I
+ enter a group, even when it's read?
+ 4.3. How to view the headers of a message?
+ 4.4. How to view the raw unformatted message?
+ 4.5. How can I change the headers Gnus displays by default at
+ the top of the article buffer?
+ 4.6. I'd like Gnus NOT to render HTML-mails but show me the
+ text part if it's available. How to do it?
+ 4.7. Can I use some other browser than w3 to render my
+ HTML-mails?
+ 4.8. Is there anything I can do to make poorly formatted mails
+ more readable?
+ 4.9. Is there a way to automatically ignore posts by specific
+ authors or with specific words in the subject? And can I
+ highlight more interesting ones in some way?
+ 4.10. How can I disable threading in some (e.g. mail-) groups,
+ or set other variables specific for some groups?
+ 4.11. Can I highlight messages written by me and follow-ups to
+ those?
+ 4.12. The number of total messages in a group which Gnus
+ displays in group buffer is by far to high, especially in
+ mail groups. Is this a bug?
+ 4.13. I don't like the layout of summary and article buffer,
+ how to change it? Perhaps even a three pane display?
+ 4.14. I don't like the way the Summary buffer looks, how to
+ tweak it?
+ 4.15. How to split incoming mails in several groups?
+
+5. Composing messages
+
+ 5.1. What are the basic commands I need to know for sending
+ mail and postings?
+ 5.2. How to enable automatic word-wrap when composing messages?
+ 5.3. How to set stuff like From, Organization, Reply-To,
+ signature...?
+ 5.4. Can I set things like From, Signature etc group based on
+ the group I post too?
+ 5.5. Is there a spell-checker? Perhaps even on-the-fly
+ spell-checking?
+ 5.6. Can I set the dictionary based on the group I'm posting
+ to?
+ 5.7. Is there some kind of address-book, so I needn't remember
+ all those email addresses?
+ 5.8. Sometimes I see little images at the top of article
+ buffer. What's that and how can I send one with my
+ postings, too?
+ 5.9. Sometimes I accidentally hit r instead of f in newsgroups.
+ Can Gnus warn me, when I'm replying by mail in newsgroups?
+ 5.10. How to tell Gnus not to generate a sender header?
+ 5.11. I want gnus to locally store copies of my send mail and
+ news, how to do it?
+ 5.12. People tell me my Message-IDs are not correct, why aren't
+ they and how to fix it?
+
+6. Old messages
+
+ 6.1. How to import my old mail into Gnus?
+ 6.2. How to archive interesting messages?
+ 6.3. How to search for a specific message?
+ 6.4. How to get rid of old unwanted mail?
+ 6.5. I want that all read messages are expired (at least in
+ some groups). How to do it?
+ 6.6. I don't want expiration to delete my mails but to move
+ them to another group.
+
+7. Getting help
+
+ 7.1. How to find information and help inside Emacs?
+ 7.2. I can't find anything in the Gnus manual about X (e.g.
+ attachments, PGP, MIME...), is it not documented?
+ 7.3. Which websites should I know?
+ 7.4. Which mailing lists and newsgroups are there?
+ 7.5. Where to report bugs?
+ 7.6. I need real-time help, where to find it?
+
+8. Tuning Gnus
+
+ 8.1. Starting Gnus is really slow, how to speed it up?
+ 8.2. How to speed up the process of entering a group?
+ 8.3. Sending mail becomes slower and slower, what's up?
+
+1. Installation FAQ
+
+1.1. What is the latest version of Gnus?
+
+ As of this posting, the latest Gnus version is 5.8.8(which is
+ basically the same as Gnus 5.9 which is shipped with GNU Emacs).
+ This version is very stable and should be the choice for all
+ beginners. However 5.8.8 is quite old, so many people today use the
+ BETA version from CVS called Oort Gnus, which contains a huge
+ amount of new features. If you want to do this too, be aware that
+ it's beta and might have bugs and at worst case might eat your
+ mail.
+
+1.2. Where and how to get Gnus?
+
+ The latest released version of Gnus is included in Emacs 21 and
+ available through the package system of XEmacs 21.4, so the easiest
+ way is getting one of those. If you don't want or can't do this,
+ get the Gnus tarball from http://www.gnus.org/dist/gnus.tar.gz
+ [http://www.gnus.org/dist/gnus.tar.gz] or via anonymous FTP from
+ ftp://ftp.gnus.org/pub/gnus/gnus.tar.gz [ftp://ftp.gnus.org/pub/
+ gnus/gnus.tar.gz].
+
+1.3. What to do with the tarball now?
+
+ Untar it via tar xvzf gnus.tar.gz and do the common ./configure;
+ make; make install circle. (under MS-Windows either get the Cygwin
+ environment from http://www.cygwin.com [http://www.cygwin.com]
+ which allows you to do what's described above or unpack the tarball
+ with some packer (e.g. Winace from http://www.winace.com [http://
+ www.winace.com]) and use the batch-file make.bat included in the
+ tarball to install Gnus. If you don't want to (or aren't allowed
+ to) install Gnus system-wide, you can install it in your home
+ directory and add the following lines to your ~/.xemacs/init.el or
+ ~/.emacs:
+
+ (add-to-list 'load-path "/path/to/gnus/lisp")
+ (if (featurep 'xemacs)
+ (add-to-list 'Info-directory-list "/path/to/gnus/texi/")
+ (add-to-list 'Info-default-directory-list "/path/to/gnus/texi/"))
+
+
+ Make sure that you don't have any gnus related stuff before this
+ line, on MS Windows use something like "C:/path/to/lisp" (yes, "/
+ ").
+
+1.4. Which version of Emacs do I need?
+
+ Gnus 5.8.8 requires an emacs version that is greater than or equal
+ to Emacs 20.3 or XEmacs 20.1.
+
+1.5. How do I run Gnus on both Emacs and XEmacs?
+
+ You can't use the same copy of Gnus in both as the Lisp files are
+ byte-compiled to a format which is different depending on which
+ Emacs did the compilation. Get one copy of Gnus for Emacs and one
+ for XEmacs.
+
+2. Startup / Group buffer
+
+2.1. Every time I start Gnus I get a message "Gnus auto-save file
+ exists. Do you want to read it?", what does this mean and how to
+ prevent it?
+
+ This message means that the last time you used Gnus, it wasn't
+ properly exited and therefor couldn't write its informations to
+ disk (e.g. which messages you read), you are now asked if you want
+ to restore those informations from the auto-save file.
+
+ To prevent this message make sure you exit Gnus via q in group
+ buffer instead of just killing Emacs.
+
+2.2. Gnus doesn't remember which groups I'm subscribed to, what's this?
+
+ You get the message described in the q/a pair above while starting
+ Gnus, right? It's an other symptom for the same problem, so read
+ the answer above.
+
+2.3. How to change the format of the lines in Group buffer?
+
+ You've got to tweak the value of the variable
+ gnus-group-line-format. See the manual node "Group Line
+ Specification" for information on how to do this. An example for
+ this (guess from whose .gnus :-)):
+
+ (setq gnus-group-line-format "%P%M%S[%5t]%5y : %(%g%)\n")
+
+
+2.4. My group buffer becomes a bit crowded, is there a way to sort my
+ groups into categories so I can easier browse through them?
+
+ Gnus offers the topic mode, it allows you to sort your groups in,
+ well, topics, e.g. all groups dealing with Linux under the topic
+ linux, all dealing with music under the topic music and all dealing
+ with scottish music under the topic scottish which is a subtopic of
+ music.
+
+ To enter topic mode, just hit t while in Group buffer. Now you can
+ use T n to create a topic at point and T m to move a group to a
+ specific topic. For more commands see the manual or the menu. You
+ might want to include the %P specifier at the beginning of your
+ gnus-group-line-format variable to have the groups nicely indented.
+
+2.5. How to manually sort the groups in Group buffer? How to sort the
+ groups in a topic?
+
+ Move point over the group you want to move and hit C-k, now move
+ point to the place where you want the group to be and hit C-y.
+
+3. Getting Messages
+
+3.1. I just installed Gnus, started it via M-x gnus but it only says
+ "nntp (news) open error", what to do?
+
+ You've got to tell Gnus where to fetch the news from. Read the
+ documentation for information on how to do this. As a first start,
+ put those lines in ~/.gnus:
+
+ (setq gnus-select-method '(nntp "news.yourprovider.net"))
+ (setq user-mail-address "you@yourprovider.net")
+ (setq user-full-name "Your Name")
+
+
+3.2. I'm working under Windows and have no idea what ~/.gnus means.
+
+ The ~/ means the home directory where Gnus and Emacs look for the
+ configuration files. However, you don't really need to know what
+ this means, it suffices that Emacs knows what it means :-) You can
+ type C-x C-f ~/.gnus RET (yes, with the forward slash, even on
+ Windows), and Emacs will open the right file for you. (It will most
+ likely be new, and thus empty.) However, I'd discourage you from
+ doing so, since the directory Emacs chooses will most certainly not
+ be what you want, so let's do it the correct way. The first thing
+ you've got to do is to create a suitable directory (no blanks in
+ directory name please) e.g. c:\myhome. Then you must set the
+ environment variable HOME to this directory. To do this under Win9x
+ or Me include the line
+
+ SET HOME=C:\myhome
+
+
+ in your autoexec.bat and reboot. Under NT, 2000 and XP, hit
+ Winkey+Pause/Break to enter system options (if it doesn't work, go
+ to Control Panel -> System). There you'll find the possibility to
+ set environment variables, create a new one with name HOME and
+ value C:\myhome, a reboot is not necessary.
+
+ Now to create ~/.gnus, say C-x C-f ~/.gnus RET C-x C-s. in Emacs.
+
+3.3. My news server requires authentication, how to store user name and
+ password on disk?
+
+ Create a file ~/.authinfo which includes for each server a line
+ like this
+
+ machine news.yourprovider.net login YourUserName password YourPassword
+
+ . Make sure that the file isn't readable to others if you work on a
+ OS which is capable of doing so. (Under Unix say
+
+ chmod 600 ~/.authinfo
+
+ in a shell.)
+
+3.4. Gnus seems to start up OK, but I can't find out how to subscribe to
+ a group.
+
+ If you know the name of the group say U name.of.group RET in group
+ buffer (use the tab-completion Luke). Otherwise hit ^ in group
+ buffer, this brings you to the server buffer. Now place point (the
+ cursor) over the server which carries the group you want, hit RET,
+ move point to the group you want to subscribe to and say u to
+ subscribe to it.
+
+3.5. Gnus doesn't show all groups / Gnus says I'm not allowed to post on
+ this server as well as I am, what's that?
+
+ Some providers allow restricted anonymous access and full access
+ only after authorization. To make Gnus send authinfo to those
+ servers append
+
+ force yes
+
+ to the line for those servers in ~/.authinfo.
+
+3.6. I want Gnus to fetch news from several servers, is this possible?
+
+ Of course. You can specify more sources for articles in the
+ variable gnus-secondary-select-methods. Add something like this in
+ ~/.gnus:
+
+ (add-to-list 'gnus-secondary-select-methods '(nntp "news.yourSecondProvider.net"))
+ (add-to-list 'gnus-secondary-select-methods '(nntp "news.yourThirdProvider.net"))
+
+
+3.7. And how about local spool files?
+
+ No problem, this is just one more select method called nnspool, so
+ you want this:
+
+ (add-to-list 'gnus-secondary-select-methods '(nnspool ""))
+
+
+ Or this if you don't want an NNTP Server as primary news source:
+
+ (setq gnus-select-method '(nnspool ""))
+
+
+ Gnus will look for the spool file in /usr/spool/news, if you want
+ something different, change the line above to something like this:
+
+ (add-to-list 'gnus-secondary-select-methods
+ '(nnspool "" (nnspool-directory "/usr/local/myspoolddir")))
+
+
+ This sets the spool directory for this server only. You might have
+ to specify more stuff like the program used to post articles, see
+ the Gnus manual on how to do this.
+
+3.8. OK, reading news works now, but I want to be able to read my mail
+ with Gnus, too. How to do it?
+
+ That's a bit harder since there are many possible sources for mail,
+ many possible ways for storing mail and many different ways for
+ sending mail. The most common cases are these: 1: You want to read
+ your mail from a pop3 server and send them directly to a SMTP
+ Server 2: Some program like fetchmail retrieves your mail and
+ stores it on disk from where Gnus shall read it. Outgoing mail is
+ sent by Sendmail, Postfix or some other MTA. Sometimes, you even
+ need a combination of the above cases.
+
+ However, the first thing to do is to tell Gnus in which way it
+ should store the mail, in Gnus terminology which back end to use.
+ Gnus supports many different back ends, the most commonly used one
+ is nnml. It stores every mail in one file and is therefor quite
+ fast. However you might prefer a one file per group approach if
+ your file system has problems with many small files, the nnfolder
+ back end is then probably the choice for you. To use nnml add the
+ following to ~/.gnus:
+
+ (add-to-list 'gnus-secondary-select-methods '(nnml ""))
+
+
+ As you might have guessed, if you want nnfolder, it's
+
+ (add-to-list 'gnus-secondary-select-methods '(nnfolder ""))
+
+
+ Now we need to tell Gnus, where to get it's mail from. If it's a
+ POP3 server, then you need something like this:
+
+ (eval-after-load "mail-source"
+ '(add-to-list 'mail-sources '(pop :server "pop.YourProvider.net"
+ :user "yourUserName"
+ :password "yourPassword"))
+
+
+ Make sure ~/.gnus isn't readable to others if you store your
+ password there. If you want to read your mail from a traditional
+ spool file on your local machine, it's
+
+ (eval-after-load "mail-source"
+ '(add-to-list 'mail-sources '(file :path "/path/to/spool/file"))
+
+
+ If it's a Maildir, with one file per message as used by postfix,
+ Qmail and (optionally) fetchmail it's
+
+ (eval-after-load "mail-source"
+ '(add-to-list 'mail-sources '(maildir :path "/path/to/Maildir/"
+ :subdirs ("cur" "new")))
+
+
+ And finally if you want to read your mail from several files in one
+ directory, for example because procmail already split your mail,
+ it's
+
+ (eval-after-load "mail-source"
+ '(add-to-list 'mail-sources '(directory :path "/path/to/procmail-dir/"
+ :suffix ".prcml"))
+
+
+ Where :suffix ".prcml" tells Gnus only to use files with the suffix
+ .prcml.
+
+ OK, now you only need to tell Gnus how to send mail. If you want to
+ send mail via sendmail (or whichever MTA is playing the role of
+ sendmail on your system), you don't need to do anything. However,
+ if you want to send your mail to an SMTP Server you need the
+ following in your ~/.gnus
+
+ (setq send-mail-function 'smtpmail-send-it)
+ (setq message-send-mail-function 'smtpmail-send-it)
+ (setq smtpmail-default-smtp-server "smtp.yourProvider.net")
+
+
+3.9. And what about IMAP?
+
+ There are two ways of using IMAP with Gnus. The first one is to use
+ IMAP like POP3, that means Gnus fetches the mail from the IMAP
+ server and stores it on disk. If you want to do this (you don't
+ really want to do this) add the following to ~/.gnus
+
+ (add-to-list 'mail-sources '(imap :server "mail.mycorp.com"
+ :user "username"
+ :pass "password"
+ :stream network
+ :authentication login
+ :mailbox "INBOX"
+ :fetchflag "\\Seen"))
+
+
+ You might have to tweak the values for stream and/or
+ authentification, see the Gnus manual node "Mail Source Specifiers"
+ for possible values.
+
+ If you want to use IMAP the way it's intended, you've got to follow
+ a different approach. You've got to add the nnimap back end to your
+ select method and give the information about the server there.
+
+ (add-to-list 'gnus-secondary-select-methods
+ '(nnimap "Give the baby a name"
+ (nnimap-address "imap.yourProvider.net")
+ (nnimap-port 143)
+ (nnimap-list-pattern "archive.*")))
+
+
+ Again, you might have to specify how to authenticate to the server
+ if Gnus can't guess the correct way, see the Manual Node "IMAP" for
+ detailed information.
+
+3.10. At the office we use one of those MS Exchange servers, can I use
+ Gnus to read my mail from it?
+
+ Offer your administrator a pair of new running shoes for activating
+ IMAP on the server and follow the instructions above.
+
+3.11. Can I tell Gnus not to delete the mails on the server it retrieves
+ via POP3?
+
+ First of all, that's not the way POP3 is intended to work, if you
+ have the possibility, you should use the IMAP Protocol if you want
+ your messages to stay on the server. Nevertheless there might be
+ situations where you need the feature, but sadly Gnus itself has no
+ predefined functionality to do so.
+
+ However this is Gnus county so there are possibilities to achieve
+ what you want. The easiest way is to get an external program which
+ retrieves copies of the mail and stores them on disk, so Gnus can
+ read it from there. On Unix systems you could use e.g. fetchmail
+ for this, on MS Windows you can use Hamster, an excellent local
+ news and mail server.
+
+ The other solution would be, to replace the method Gnus uses to get
+ mail from POP3 servers by one which is capable of leaving the mail
+ on the server. If you use XEmacs, get the package mail-lib, it
+ includes an enhanced pop3.el, look in the file, there's
+ documentation on how to tell Gnus to use it and not to delete the
+ retrieved mail. For GNU Emacs look for the file epop3.el which can
+ do the same (If you know the home of this file, please send me an
+ e-mail). You can also tell Gnus to use an external program (e.g.
+ fetchmail) to fetch your mail, see the info node "Mail Source
+ Specifiers" in the Gnus manual on how to do it.
+
+4. Reading messages
+
+4.1. When I enter a group, all read messages are gone. How to view them
+ again?
+
+ If you enter the group by saying RET in summary buffer with point
+ over the group, only unread and ticked messages are loaded. Say C-u
+ RET instead to load all available messages. If you want only the
+ e.g. 300 newest say C-u 300 RET
+
+ Loading only unread messages can be annoying if you have threaded
+ view enabled, say
+
+ (setq gnus-fetch-old-headers 'some)
+
+
+ in ~/.gnus to load enough old articles to prevent teared threads,
+ replace 'some with t to load all articles (Warning: Both settings
+ enlarge the amount of data which is fetched when you enter a group
+ and slow down the process of entering a group).
+
+ If you use Oort Gnus, you can say /o N In summary buffer to load
+ the last N messages, this feature is not available in 5.8.8
+
+ If you don't want all old messages, but the parent of the message
+ you're just reading, you can say ^, if you want to retrieve the
+ whole thread the message you're just reading belongs to, A T is
+ your friend.
+
+4.2. How to tell Gnus to show an important message every time I enter a
+ group, even when it's read?
+
+ You can tick important messages. To do this hit u while point is in
+ summary buffer over the message. When you want to remove the mark,
+ hit either d (this deletes the tick mark and set's unread mark) or
+ M c (which deletes all marks for the message).
+
+4.3. How to view the headers of a message?
+
+ Say t to show all headers, one more t hides them again.
+
+4.4. How to view the raw unformatted message?
+
+ Say C-u g to show the raw message g returns to normal view.
+
+4.5. How can I change the headers Gnus displays by default at the top of
+ the article buffer?
+
+ The variable gnus-visible-headers controls which headers are shown,
+ its value is a regular expression, header lines which match it are
+ shown. So if you want author, subject, date, and if the header
+ exists, Followup-To and MUA / NUA say this in ~/.gnus:
+
+ (setq gnus-visible-headers
+ "^\\(From:\\|Subject:\\|Date:\\|Followup-To:\\|X-Newsreader:\\|User-Agent:\\|X-Mailer:\\)")
+
+
+4.6. I'd like Gnus NOT to render HTML-mails but show me the text part if
+ it's available. How to do it?
+
+ Say
+
+ (eval-after-load "mm-decode"
+ '(progn
+ (add-to-list 'mm-discouraged-alternatives "text/html")
+ (add-to-list 'mm-discouraged-alternatives "text/richtext")))
+
+
+ in ~/.gnus. If you don't want HTML rendered, even if there's no
+ text alternative add
+
+ (setq mm-automatic-display (remove "text/html" mm-automatic-display))
+
+
+ too.
+
+4.7. Can I use some other browser than w3 to render my HTML-mails?
+
+ Only if you use Oort Gnus. In this case you've got the choice
+ between w3, w3m, links, lynx and html2text, which one is used can
+ be specified in the variable mm-text-html-renderer, so if you want
+ links to render your mail say
+
+ (setq mm-text-html-renderer 'links)
+
+
+4.8. Is there anything I can do to make poorly formatted mails more
+ readable?
+
+ Gnus offers you several functions to "wash" incoming mail, you can
+ find them if you browse through the menu, item Article->Washing.
+ The most interesting ones are probably "Wrap long lines" ( W w ),
+ "Decode ROT13" ( W r ) and "Outlook Deuglify" which repairs the
+ dumb quoting used by many users of Microsoft products ( W k ) sadly
+ the last one is only available in Oort Gnus.
+
+4.9. Is there a way to automatically ignore posts by specific authors or
+ with specific words in the subject? And can I highlight more
+ interesting ones in some way?
+
+ You want Scoring. Scoring means, that you define rules which assign
+ each message an integer value. Depending on the value the message
+ is highlighted in summary buffer (if it's high, say +2000) or
+ automatically marked read (if the value is low, say -800) or some
+ other action happens.
+
+ There are basically three ways of setting up rules which assign the
+ scoring-value to messages. The first and easiest way is to set up
+ rules based on the article you are just reading. Say you're reading
+ a message by a guy who always writes nonsense and you want to
+ ignore his messages in the future. Hit L, to set up a rule which
+ lowers the score. Now Gnus asks you which the criteria for lowering
+ the Score shall be. Hit ? twice to see all possibilities, we want a
+ which means the author (the from header). Now Gnus wants to know
+ which kind of matching we want. Hit either e for an exact match or
+ s for substring-match and delete afterwards everything but the name
+ to score down all authors with the given name no matter which email
+ address is used. Now you need to tell Gnus when to apply the rule
+ and how long it should last, hit e.g. p to apply the rule now and
+ let it last forever. If you want to raise the score instead of
+ lowering it say I instead of L.
+
+ You can also set up rules by hand. To do this say V f in summary
+ buffer. Then you are asked for the name of the score file, it's
+ name.of.group.SCORE for rules valid in only one group or all.Score
+ for rules valid in all groups. See the Gnus manual for the exact
+ syntax, basically it's one big list whose elements are lists again.
+ the first element of those lists is the header to score on, then
+ one more list with what to match, which score to assign, when to
+ expire the rule and how to do the matching. If you find me very
+ interesting, you could e.g. add the following to your all.Score:
+
+ (("references" ("hschmi22.userfqdn.rz-online.de" 500 nil s))
+ ("message-id" ("hschmi22.userfqdn.rz-online.de" 999 nil s)))
+
+
+ This would add 999 to the score of messages written by me and 500
+ to the score of messages which are a (possibly indirect) answer to
+ a message written by me. Of course nobody with a sane mind would do
+ this :-)
+
+ The third alternative is adaptive scoring. This means Gnus watches
+ you and tries to find out what you find interesting and what
+ annoying and sets up rules which reflect this. Adaptive scoring can
+ be a huge help when reading high traffic groups. If you want to
+ activate adaptive scoring say
+
+ (setq gnus-use-adaptive-scoring t)
+
+
+ in ~/.gnus.
+
+4.10. How can I disable threading in some (e.g. mail-) groups, or set
+ other variables specific for some groups?
+
+ While in group buffer move point over the group and hit G c, this
+ opens a buffer where you can set options for the group. At the
+ bottom of the buffer you'll find an item that allows you to set
+ variables locally for the group. To disable threading enter
+ gnus-show-threads as name of variable and nil as value. Hit button
+ done at the top of the buffer when you're ready.
+
+4.11. Can I highlight messages written by me and follow-ups to those?
+
+ Stop those "Can I ..." questions, the answer is always yes in Gnus
+ Country :-). It's a three step process: First we make faces
+ (specifications of how summary-line shall look like) for those
+ postings, then we'll give them some special score and finally we'll
+ tell Gnus to use the new faces. You can find detailed instructions
+ on how to do it on my.gnus.org [http://my.gnus.org/Members/dzimmerm
+ /HowTo%2C2002-07-25%2C1027619165012198456/view]
+
+4.12. The number of total messages in a group which Gnus displays in
+ group buffer is by far to high, especially in mail groups. Is this
+ a bug?
+
+ No, that's a matter of design of Gnus, fixing this would mean
+ reimplementation of major parts of Gnus' back ends. Gnus thinks
+ "highest-article-number - lowest-article-number =
+ total-number-of-articles". This works OK for Usenet groups, but if
+ you delete and move many messages in mail groups, this fails. To
+ cure the symptom, enter the group via C-u RET (this makes Gnus get
+ all messages), then hit M P b to mark all messages and then say B m
+ name.of.group to move all messages to the group they have been in
+ before, they get new message numbers in this process and the count
+ is right again (until you delete and move your mail to other groups
+ again).
+
+4.13. I don't like the layout of summary and article buffer, how to
+ change it? Perhaps even a three pane display?
+
+ You can control the windows configuration by calling the function
+ gnus-add-configuration. The syntax is a bit complicated but
+ explained very well in the manual node "Window Layout". Some
+ popular examples:
+
+ Instead 25% summary 75% article buffer 35% summary and 65% article
+ (the 1.0 for article means "take the remaining space"):
+
+ (gnus-add-configuration '(article (vertical 1.0 (summary .35 point) (article 1.0))))
+
+
+ A three pane layout, Group buffer on the left, summary buffer
+ top-right, article buffer bottom-right:
+
+ (gnus-add-configuration
+ '(article
+ (horizontal 1.0
+ (vertical 25
+ (group 1.0))
+ (vertical 1.0
+ (summary 0.25 point)
+ (article 1.0)))))
+ (gnus-add-configuration
+ '(summary
+ (horizontal 1.0
+ (vertical 25
+ (group 1.0))
+ (vertical 1.0
+ (summary 1.0 point)))))
+
+
+4.14. I don't like the way the Summary buffer looks, how to tweak it?
+
+ You've got to play around with the variable
+ gnus-summary-line-format. It's value is a string of symbols which
+ stand for things like author, date, subject etc. A list of the
+ available specifiers can be found in the manual node "Summary
+ Buffer Lines" and the often forgotten node "Formatting Variables"
+ and it's sub-nodes. There you'll find useful things like
+ positioning the cursor and tabulators which allow you a summary in
+ table form, but sadly hard tabulators are broken in 5.8.8.
+
+ Oort Gnus offers you some very nice new specifiers, e.g. %B which
+ draws a thread-tree and %&user-date which gives you a date where
+ the details are dependent of the articles age. Here's an example
+ which uses both, DON'T TRY TO USE IT WITH 5.8.8!
+
+ (setq gnus-summary-line-format ":%U%R %B %s %-60=|%4L |%-20,20f |%&user-date; \n")
+
+
+ resulting in:
+
+ :O Re: [Richard Stallman] rfc2047.el | 13 |Lars Magne Ingebrigt |Sat 23:06
+ :O Re: Revival of the ding-patches list | 13 |Lars Magne Ingebrigt |Sat 23:12
+ :R > Re: Find correct list of articles for a gro| 25 |Lars Magne Ingebrigt |Sat 23:16
+ :O \-> ... | 21 |Kai Grossjohann | 0:01
+ :R > Re: Cry for help: deuglify.el - moving stuf| 28 |Lars Magne Ingebrigt |Sat 23:34
+ :O \-> ... | 115 |Raymond Scholz | 1:24
+ :O \-> ... | 19 |Lars Magne Ingebrigt |15:33
+ :O Slow mailing list | 13 |Lars Magne Ingebrigt |Sat 23:49
+ :O Re: `@' mark not documented | 13 |Lars Magne Ingebrigt |Sat 23:50
+ :R > Re: Gnus still doesn't count messages prope| 23 |Lars Magne Ingebrigt |Sat 23:57
+ :O \-> ... | 18 |Kai Grossjohann | 0:35
+ :O \-> ... | 13 |Lars Magne Ingebrigt | 0:56
+
+
+4.15. How to split incoming mails in several groups?
+
+ Gnus offers two possibilities for splitting mail, the easy
+ nnmail-split-methods and the more powerful Fancy Mail Splitting.
+ I'll only talk about the first one, refer to the manual, node
+ "Fancy Mail Splitting" for the latter.
+
+ The value of nnmail-split-methods is a list, each element is a list
+ which stands for a splitting rule. Each rule has the form "group
+ where matching articles should go to", "regular expression which
+ has to be matched", the first rule which matches wins. The last
+ rule must always be a general rule (regular expression .*) which
+ denotes where articles should go which don't match any other rule.
+ If the folder doesn't exist yet, it will be created as soon as an
+ article lands there. By default the mail will be send to all groups
+ whose rules match. If you don't want that (you probably don't
+ want), say
+
+ (setq nnmail-crosspost nil)
+
+
+ in ~/.gnus.
+
+ An example might be better than thousand words, so here's my
+ nnmail-split-methods. Note that I send duplicates in a special
+ group and that the default group is spam, since I filter all mails
+ out which are from some list I'm subscribed to or which are
+ addressed directly to me before. Those rules kill about 80% of the
+ Spam which reaches me (Email addresses are changed to prevent
+ spammers from using them):
+
+ (setq nnmail-split-methods
+ '(("duplicates" "^Gnus-Warning:.*duplicate")
+ ("XEmacs-NT" "^\\(To:\\|CC:\\).*localpart@xemacs.bla.*")
+ ("Gnus-Tut" "^\\(To:\\|CC:\\).*localpart@socha.bla.*")
+ ("tcsh" "^\\(To:\\|CC:\\).*localpart@mx.gw.bla.*")
+ ("BAfH" "^\\(To:\\|CC:\\).*localpart@.*uni-muenchen.bla.*")
+ ("Hamster-src" "^\\(CC:\\|To:\\).*hamster-sourcen@yahoogroups.\\(de\\|com\\).*")
+ ("Tagesschau" "^From: tagesschau <localpart@www.tagesschau.bla>$")
+ ("Replies" "^\\(CC:\\|To:\\).*localpart@Frank-Schmitt.bla.*")
+ ("EK" "^From:.*\\(localpart@privateprovider.bla\\|localpart@workplace.bla\\).*")
+ ("Spam" "^Content-Type:.*\\(ks_c_5601-1987\\|EUC-KR\\|big5\\|iso-2022-jp\\).*")
+ ("Spam" "^Subject:.*\\(This really work\\|XINGA\\|ADV:\\|XXX\\|adult\\|sex\\).*")
+ ("Spam" "^Subject:.*\\(\=\?ks_c_5601-1987\?\\|\=\?euc-kr\?\\|\=\?big5\?\\).*")
+ ("Spam" "^X-Mailer:\\(.*BulkMailer.*\\|.*MIME::Lite.*\\|\\)")
+ ("Spam" "^X-Mailer:\\(.*CyberCreek Avalanche\\|.*http\:\/\/GetResponse\.com\\)")
+ ("Spam" "^From:.*\\(verizon\.net\\|prontomail\.com\\|money\\|ConsumerDirect\\).*")
+ ("Spam" "^Delivered-To: GMX delivery to spamtrap@gmx.bla$")
+ ("Spam" "^Received: from link2buy.com")
+ ("Spam" "^CC: .*azzrael@t-online.bla")
+ ("Spam" "^X-Mailer-Version: 1.50 BETA")
+ ("Uni" "^\\(CC:\\|To:\\).*localpart@uni-koblenz.bla.*")
+ ("Inbox" "^\\(CC:\\|To:\\).*\\(my\ name\\|address@one.bla\\|adress@two.bla\\)")
+ ("Spam" "")))
+
+
+5. Composing messages
+
+5.1. What are the basic commands I need to know for sending mail and
+ postings?
+
+ To start composing a new mail hit m either in Group or Summary
+ buffer, for a posting, it's either a in Group buffer and filling
+ the Newsgroups header manually or a in the Summary buffer of the
+ group where the posting shall be send to. Replying by mail is r if
+ you don't want to cite the author, or import the cited text
+ manually and R to cite the text of the original message. For a
+ follow up to a newsgroup, it's f and F (analog to r and R.
+
+ Enter new headers above the line saying "--text follows this
+ line--", enter the text below the line. When ready hit C-c C-c, to
+ send the message, if you want to finish it later hit C-c C-d to
+ save it in the drafts group, where you can start editing it again
+ by saying D e.
+
+5.2. How to enable automatic word-wrap when composing messages?
+
+ Say
+
+ (add-hook 'message-mode-hook
+ (lambda ()
+ (setq fill-column 72)
+ (turn-on-auto-fill)))
+
+
+ in ~/.gnus. You can reformat a paragraph by hitting M-q (as usual)
+
+5.3. How to set stuff like From, Organization, Reply-To, signature...?
+
+ There are other ways, but you should use posting styles for this.
+ (See below why). This example should make the syntax clear:
+
+ (setq gnus-posting-styles
+ '((".*"
+ (name "Frank Schmitt")
+ (address "me@there.bla")
+ (organization "Hamme net, kren mer och nimmi")
+ (signature-file "~/.signature")
+ ("X-SampleHeader" "foobar")
+ (eval (setq some-variable "Foo bar")))))
+
+
+ The ".*" means that this settings are the default ones (see below),
+ valid values for the first element of the following lists are
+ signature, signature-file, organization, address, name or body. The
+ attribute name can also be a string. In that case, this will be
+ used as a header name, and the value will be inserted in the
+ headers of the article; if the value is `nil', the header name will
+ be removed. You can also say (eval (foo bar)), then the function
+ foo will be evaluated with argument bar and the result will be
+ thrown away.
+
+5.4. Can I set things like From, Signature etc group based on the group
+ I post too?
+
+ That's the strength of posting styles. Before, we used ".*" to set
+ the default for all groups. You can use a regexp like "^gmane" and
+ the following settings are only applied to postings you send to the
+ gmane hierarchy, use ".*binaries" instead and they will be applied
+ to postings send to groups containing the string binaries in their
+ name etc.
+
+ You can instead of specifying a regexp specify a function which is
+ evaluated, only if it returns true, the corresponding settings take
+ effect. Two interesting candidates for this are message-news-p
+ which returns t if the current Group is a newsgroup and the
+ corresponding message-mail-p.
+
+ Note that all forms that match are applied, that means in the
+ example below, when I post to gmane.mail.spam.spamassassin.general,
+ the settings under ".*" are applied and the settings under
+ message-news-p and those under "^gmane" and those under "^gmane\
+ \.mail\\.spam\\.spamassassin\\.general$". Because of this put
+ general settings at the top and specific ones at the bottom.
+
+ (setq gnus-posting-styles
+ '((".*" ;;default
+ (name "Frank Schmitt")
+ (organization "Hamme net, kren mer och nimmi")
+ (signature-file "~/.signature") )
+ ((message-news-p) ;;Usenet news?
+ (address "mySpamTrap@Frank-Schmitt.bla")
+ ("Reply-To" "hereRealRepliesOnlyPlease@Frank-Schmitt.bla") )
+ ((message-mail-p) ;;mail?
+ (address "usedForMails@Frank-Schmitt.bla") )
+ ("^gmane" ;;this is mail, too in fact
+ (address "usedForMails@Frank-Schmitt.net")
+ ("Reply-To" nil) )
+ ("^gmane.mail.spam.spamassassin.general$"
+ (eval (setq mail-envelope-from "Azzrael@rz-online.de"))
+ (address "Azzrael@rz-online.de")) ))
+
+
+5.5. Is there a spell-checker? Perhaps even on-the-fly spell-checking?
+
+ You can use ispell.el to spell-check stuff in Emacs. So the first
+ thing to do is to make sure that you've got either ispell [http://
+ fmg-www.cs.ucla.edu/fmg-members/geoff/ispell.html] or aspell [http:
+ //aspell.sourceforge.net/] installed and in your Path. Then you
+ need ispell.el [http://www.kdstevens.com/~stevens/ispell-page.html]
+ and for on-the-fly spell-checking flyspell.el [http://
+ www-sop.inria.fr/mimosa/personnel/Manuel.Serrano/flyspell/
+ flyspell.html]. Ispell.el is shipped with Gnus Emacs and available
+ through the Emacs package system, flyspell.el is shipped with Emacs
+ and part of XEmacs text-modes package which is available through
+ the package system, so there should be no need to install them
+ manually.
+
+ Ispell.el assumes you use ispell, if you choose aspell say
+
+ (setq ispell-program-name "aspell")
+
+ in your Emacs configuration file.
+
+ If you want your outgoing messages to be spell-checked, say
+
+ (add-hook 'message-send-hook 'ispell-message)
+
+ In your ~/.gnus, if you prefer on-the-fly spell-checking say
+
+ (add-hook 'message-mode-hook (lambda () (flyspell-mode 1)))
+
+5.6. Can I set the dictionary based on the group I'm posting to?
+
+ Yes, say something like
+
+ (add-hook 'gnus-select-group-hook
+ (lambda ()
+ (cond
+ ((string-match
+ "^de\\." (gnus-group-real-name gnus-newsgroup-name))
+ (ispell-change-dictionary "deutsch8"))
+ (t
+ (ispell-change-dictionary "english")))))
+
+
+ in ~/.gnus. Change "^de\\." and "deutsch8" to something that suits
+ your needs.
+
+5.7. Is there some kind of address-book, so I needn't remember all those
+ email addresses?
+
+ There's an very basic solution for this, mail aliases. You can
+ store your mail addresses in a ~/.mailrc file using a simple alias
+ syntax:
+
+ alias al "Al <al@english-heritage.bla>"
+
+
+ Then typing your alias (followed by a space or punctuation
+ character) on a To: or Cc: line in the message buffer will cause
+ gnus to insert the full address for you. See the node "Mail
+ Aliases" in Message (not Gnus) manual for details.
+
+ However, what you really want is the Insidious Big Brother Database
+ bbdb. Get it through the XEmacs package system or from bbdb's
+ homepage [http://bbdb.sourceforge.net/]. Now place the following in
+ ~/.gnus, to activate bbdb for Gnus:
+
+ (require 'bbdb)
+ (bbdb-initialize 'gnus 'message)
+
+
+ Now you probably want some general bbdb configuration, place them
+ in ~/.emacs:
+
+ (require 'bbdb)
+ ;;If you don't live in Northern America, you should disable the
+ ;;syntax check for telephone numbers by saying
+ (setq bbdb-north-american-phone-numbers-p nil)
+ ;;Tell bbdb about your email address:
+ (setq bbdb-user-mail-names
+ (regexp-opt '("Your.Email@here.bla"
+ "Your.other@mail.there.bla")))
+ ;;cycling while completing email addresses
+ (setq bbdb-complete-name-allow-cycling t)
+ ;;No popup-buffers
+ (setq bbdb-use-pop-up nil)
+
+
+ Now you should be ready to go. Say M-x bbdb RET RET to open a bbdb
+ buffer showing all entries. Say c to create a new entry, b to
+ search your BBDB and C-o to add a new field to an entry. If you
+ want to add a sender to the BBDB you can also just hit `:' on the
+ posting in the summary buffer and you are done. When you now
+ compose a new mail, hit TAB to cycle through know recipients.
+
+5.8. Sometimes I see little images at the top of article buffer. What's
+ that and how can I send one with my postings, too?
+
+ Those images are called X-Faces. They are 48*48 pixel b/w pictures,
+ encoded in a header line. If you want to include one in your posts,
+ you've got to convert some image to a X-Face. So fire up some image
+ manipulation program (say Gimp), open the image you want to
+ include, cut out the relevant part, reduce color depth to 1 bit,
+ resize to 48*48 and save as bitmap. Now you should get the compface
+ package from this site [ftp://ftp.cs.indiana.edu:/pub/faces/]. and
+ create the actual X-face by saying
+
+ cat file.xbm | xbm2ikon |compface > file.face
+ cat ./file.face | sed 's/\\/\\\\/g' | sed 's/\"/\\\"/g' > ./file.face.quoted
+
+
+ if you can't use compface, there's an online X-face converter at
+ http://www.dairiki.org/xface/ [http://www.dairiki.org/xface/]. If
+ you use MS Windows, you could also use the WinFace program from
+ http://www.xs4all.nl/~walterln/winface/ [http://www.xs4all.nl/
+ ~walterln/winface/]. Now you only have to tell Gnus to include the
+ X-face in your postings by saying
+
+ (setq message-default-headers
+ (with-temp-buffer
+ (insert "X-Face: ")
+ (insert-file-contents "~/.xemacs/xface")
+ (buffer-string)))
+
+
+ in ~/.gnus.
+
+5.9. Sometimes I accidentally hit r instead of f in newsgroups. Can Gnus
+ warn me, when I'm replying by mail in newsgroups?
+
+ Put this in ~/.gnus:
+
+ (defadvice gnus-summary-reply (around reply-in-news activate)
+ (interactive)
+ (when (or (not (gnus-news-group-p gnus-newsgroup-name))
+ (y-or-n-p "Really reply? "))
+ ad-do-it))
+
+
+ In Oort you can use
+
+ (setq gnus-confirm-mail-reply-to-news t)
+
+
+ instead to achieve the same result.
+
+5.10. How to tell Gnus not to generate a sender header?
+
+ Say
+
+ (eval-after-load "message"
+ '(add-to-list 'message-syntax-checks '(sender . disabled)))
+
+
+ in ~/.gnus. (This is the default behaviour in Oort Gnus.)
+
+5.11. I want gnus to locally store copies of my send mail and news, how
+ to do it?
+
+ You must set the variable gnus-message-archive-group to do this.
+ You can set it to a string giving the name of the group where the
+ copies shall go or like in the example below use a function which
+ is evaluated and which returns the group to use.
+
+ (setq gnus-message-archive-group
+ '((if (message-news-p)
+ "nnml:Send-News"
+ "nnml:Send-Mail")))
+
+
+5.12. People tell me my Message-IDs are not correct, why aren't they and
+ how to fix it?
+
+ The message-ID is an unique identifier for messages you send. To
+ make it unique, Gnus need to know which machine name to put after
+ the "@". If the name of the machine where Gnus is running isn't
+ suitable (it probably isn't at most private machines) you can tell
+ Gnus what to use by saying:
+
+ (defun message-make-message-id()
+ (concat "<"(message-unique-id)"@yourmachine.yourdomain.tld>"))
+
+
+ in ~/.gnus. If you have no idea what to insert for
+ "yourmachine.yourdomain.tld", you've got several choices. You can
+ either ask your provider if he allows you to use something like
+ yourUserName.userfqdn.provider.net, or you can use
+ somethingUnique.yourdomain.tld if you own the domain
+ yourdomain.tld, or you can register at a service which gives
+ private users a FQDN for free, e.g. http://www.stura.tu-freiberg.de
+ /~dlx/addfqdn.html [http://www.stura.tu-freiberg.de/~dlx/
+ addfqdn.html]. (Sorry but this website is in German, if you know of
+ an English one offering the same, drop me a note).
+
+ Finally you can tell Gnus not to generate a Message-ID for News at
+ all (and letting the server do the job) by saying
+
+ (setq message-required-news-headers
+ (remove' Message-ID message-required-news-headers))
+
+
+ you can also tell Gnus not to generate Message-IDs for mail by
+ saying
+
+ (setq message-required-mail-headers
+ (remove' Message-ID message-required-mail-headers))
+
+
+ , however some mail servers don't generate proper Message-IDs, too,
+ so test if your Mail Server behaves correctly by sending yourself a
+ Mail and looking at the Message-ID.
+
+6. Old messages
+
+6.1. How to import my old mail into Gnus?
+
+ The easiest way is to tell your old mail program to export the
+ messages in mbox format. Most Unix mailers are able to do this, if
+ you come from the MS Windows world, you may find tools at http://
+ mbx2mbox.sourceforge.net/ [http://mbx2mbox.sourceforge.net/].
+
+ Now you've got to import this mbox file into Gnus. To do this,
+ create a nndoc group based on the mbox file by saying G f /path/
+ file.mbox RET in Group buffer. You now have read-only access to
+ your mail. If you want to import the messages to your normal Gnus
+ mail groups hierarchy, enter the nndoc group you've just created by
+ saying C-u RET (thus making sure all messages are retrieved), mark
+ all messages by saying M P b and either copy them to the desired
+ group by saying B c name.of.group RET or send them through
+ nnmail-split-methods (respool them) by saying B r.
+
+6.2. How to archive interesting messages?
+
+ If you stumble across an interesting message, say in gnu.emacs.gnus
+ and want to archive it there are several solutions. The first and
+ easiest is to save it to a file by saying O f. However, wouldn't it
+ be much more convenient to have more direct access to the archived
+ message from Gnus? If you say yes, put this snippet by Frank Haun
+ <pille3003@fhaun.de> in ~/.gnus:
+
+ (defun my-archive-article (&optional n)
+ "Copies one or more article(s) to a corresponding `nnml:' group, e.g.
+ `gnus.ding' goes to `nnml:1.gnus.ding'. And `nnml:List-gnus.ding' goes
+ to `nnml:1.List-gnus-ding'.
+
+ Use process marks or mark a region in the summary buffer to archive
+ more then one article."
+ (interactive "P")
+ (let ((archive-name
+ (format
+ "nnml:1.%s"
+ (if (featurep 'xemacs)
+ (replace-in-string gnus-newsgroup-name "^.*:" "")
+ (replace-regexp-in-string "^.*:" "" gnus-newsgroup-name)))))
+ (gnus-summary-copy-article n archive-name)))
+
+
+ You can now say M-x my-archive-article in summary buffer to archive
+ the article under the cursor in a nnml group. (Change nnml to your
+ preferred back end)
+
+ Of course you can also make sure the cache is enabled by saying
+
+ (setq gnus-use-cache t)
+
+
+ then you only have to set either the tick or the dormant mark for
+ articles you want to keep, setting the read mark will remove them
+ from cache.
+
+6.3. How to search for a specific message?
+
+ There are several ways for this, too. For a posting from a Usenet
+ group the easiest solution is probably to ask groups.google.com
+ [http://groups.google.com] (in Oort Gnus you can search
+ groups.google.com with G W), if you found the posting there, tell
+ Google to display the raw message, look for the message-id, and say
+ M-^ the@message.id RET in a summary buffer.
+
+ Another idea which works for both mail and news groups is to enter
+ the group where the message you are searching is and use the
+ standard Emacs search C-s, it's smart enough to look at articles in
+ collapsed threads, too. If you want to search bodies, too try M-s
+ instead. Further on there are the gnus-summary-limit-to-foo
+ functions, which can help you, too.
+
+ Of course you can also use grep to search through your local mail,
+ but this is both slow for big archives and inconvenient since you
+ are not displaying the found mail in Gnus. Here comes nnir into
+ action. Nnir is a front end to search engines like swish-e or
+ swish++ and others. You index your mail with one of those search
+ engines and with the help of nnir you can search trough the indexed
+ mail and generate a temporary group with all messages which met
+ your search criteria. If this sound cool to you get nnir.el from
+ ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/ [ftp://
+ ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/] or ftp://
+ ftp.is.informatik.uni-duisburg.de/pub/src/emacs/ [ftp://
+ ftp.is.informatik.uni-duisburg.de/pub/src/emacs/]. Instructions on
+ how to use it are at the top of the file.
+
+6.4. How to get rid of old unwanted mail?
+
+ You can of course just mark the mail you don't need anymore by
+ saying # with point over the mail and then say B DEL to get rid of
+ them forever. You could also instead of actually deleting them,
+ send them to a junk-group by saying B m nnml:trash-bin which you
+ clear from time to time, but both are not the intended way in Gnus.
+
+ In Gnus, we let mail expire like news expires on a news server.
+ That means you tell Gnus the message is expirable (you tell Gnus "I
+ don't need this mail anymore") by saying E with point over the mail
+ in summary buffer. Now when you leave the group, Gnus looks at all
+ messages which you marked as expirable before and if they are old
+ enough (default is older than a week) they are deleted.
+
+6.5. I want that all read messages are expired (at least in some
+ groups). How to do it?
+
+ If you want all read messages to be expired (e.g. in mailing lists
+ where there's an online archive), you've got two choices:
+ auto-expire and total-expire. Auto-expire means, that every article
+ which has no marks set and is selected for reading is marked as
+ expirable, Gnus hits E for you every time you read a message.
+ Total-expire follows a slightly different approach, here all
+ article where the read mark is set are expirable.
+
+ To activate auto-expire, include auto-expire in the Group
+ parameters for the group. (Hit G c in summary buffer with point
+ over the group to change group parameters). For total-expire add
+ total-expire to the group-parameters.
+
+ Which method you choose is merely a matter of taste: Auto-expire is
+ faster, but it doesn't play together with Adaptive Scoring, so if
+ you want to use this feature, you should use total-expire.
+
+ If you want a message to be excluded from expiration in a group
+ where total or auto expire is active, set either tick (hit u) or
+ dormant mark (hit u), when you use auto-expire, you can also set
+ the read mark (hit d).
+
+6.6. I don't want expiration to delete my mails but to move them to
+ another group.
+
+ Say something like this in ~/.gnus:
+
+ (setq nnmail-expiry-target "nnml:expired")
+
+
+ (If you want to change the value of nnmail-expiry-target on a per
+ group basis see the question "How can I disable threading in some
+ (e.g. mail-) groups, or set other variables specific for some
+ groups?")
+
+7. Getting help
+
+7.1. How to find information and help inside Emacs?
+
+ The first stop should be the Gnus manual (Say C-h i d m Gnus RET to
+ start the Gnus manual, then walk through the menus or do a
+ full-text search with s). Then there are the general Emacs help
+ commands starting with C-h, type C-h ? ? to get a list of all
+ available help commands and their meaning. Finally M-x
+ apropos-command lets you search through all available functions and
+ M-x apropos searches the bound variables.
+
+7.2. I can't find anything in the Gnus manual about X (e.g. attachments,
+ PGP, MIME...), is it not documented?
+
+ There's not only the Gnus manual but also the manuals for message,
+ emacs-mime, sieve and (only in Oort Gnus) pgg. Those packages are
+ distributed with Gnus and used by Gnus but aren't really part of
+ core Gnus, so they are documented in different info files, you
+ should have a look in those manuals, too.
+
+7.3. Which websites should I know?
+
+ The two most important ones are the official Gnus website [http://
+ www.gnus.org]. and it's sister site my.gnus.org (MGO) [http://
+ my.gnus.org], hosting an archive of lisp snippets, howtos, a (not
+ really finished) tutorial and this FAQ.
+
+ Tell me about other sites which are interesting.
+
+7.4. Which mailing lists and newsgroups are there?
+
+ There's the newsgroup gnu.emacs.gnus (pull it from e.g.
+ news.gnus.org) which deals with general questions and the ding
+ mailing list (ding@gnus.org) dealing with development of Gnus. You
+ can read the ding list via NNTP, too under the name gnus.ding from
+ news.gnus.org.
+
+ If you want to stay in the big8, news.software.newssreaders is also
+ read by some Gnus users (but chances for qualified help are much
+ better in the above groups) and if you speak German, there's
+ de.comm.software.gnus.
+
+7.5. Where to report bugs?
+
+ Say M-x gnus-bug, this will start a message to the gnus bug mailing
+ list [mailto:bugs@gnus.org] including information about your
+ environment which make it easier to help you.
+
+7.6. I need real-time help, where to find it?
+
+ Point your IRC client to irc.my.gnus.org channel #mygnus. Don't be
+ afraid if people there speak German, they are willing and capable
+ of switching to English when people from outside Germany enter.
+
+8. Tuning Gnus
+
+8.1. Starting Gnus is really slow, how to speed it up?
+
+ The reason for this could be the way Gnus reads it's active file,
+ see the node "The Active File" in the Gnus manual for things you
+ might try to speed the process up. An other idea would be to byte
+ compile your ~/.gnus (say M-x byte-compile-file RET ~/.gnus RET to
+ do it). Finally, if you have require statements in your .gnus, you
+ could replace them with eval-after-load, which loads the stuff not
+ at startup time, but when it's needed. Say you've got this in your
+ ~/.gnus:
+
+ (require 'message)
+ (add-to-list 'message-syntax-checks '(sender . disabled))
+
+
+ then as soon as you start Gnus, message.el is loaded. If you
+ replace it with
+
+ (eval-after-load "message"
+ '(add-to-list 'message-syntax-checks '(sender . disabled)))
+
+
+ it's loaded when it's needed.
+
+8.2. How to speed up the process of entering a group?
+
+ A speed killer is setting the variable gnus-fetch-old-headers to
+ anything different from nil, so don't do this if speed is an issue.
+ To speed up building of summary say
+
+ (gnus-compile)
+
+
+ at the bottom of your ~/.gnus, this will make gnus byte-compile
+ things like gnus-summary-line-format. then you could increase the
+ value of gc-cons-threshold by saying something like
+
+ (setq gc-cons-threshold 3500000)
+
+
+ in ~/.emacs. If you don't care about width of CJK characters or use
+ Oort Gnus together with a recent GNU Emacs, you should say
+
+ (setq gnus-use-correct-string-widths nil)
+
+
+ in ~/.gnus (thanks to Jesper harder for the last two suggestions).
+ Finally if this also doesn't help, you might want to jump in the
+ cold water and try Oort Gnus, there some work has been done to
+ speed up summary generation. Read and remember the warnings about
+ Oort at the top of this FAQ.
+
+8.3. Sending mail becomes slower and slower, what's up?
+
+ The reason could be that you told Gnus to archive the messages you
+ wrote by setting gnus-message-archive-group. Try to use a nnml
+ group instead of an archive group, this should bring you back to
+ normal speed.
+
+Glossary
+
+~/.gnus
+
+ When the term ~/.gnus is used it just means your Gnus
+ configuration file. You might as well call it ~/.gnus.el or
+ specify another name.
+
+Back End
+
+ In Gnus terminology a back end is a virtual server, a layer
+ between core Gnus and the real NNTP-, POP3-, IMAP- or
+ whatever-server which offers Gnus a standardized interface to
+ functions like "get message", "get Headers" etc.
+
+Emacs
+
+ When the term Emacs is used in this FAQ, it means either GNU
+ Emacs or XEmacs.
+
+Message
+
+ In this FAQ message means a either a mail or a posting to a
+ Usenet Newsgroup or to some other fancy back end, no matter of
+ which kind it is.
+
+MUA
+
+ MUA is an acronym for Mail User Agent, it's the program you use
+ to read and write e-mails.
+
+NUA
+
+ NUA is an acronym for News User Agent, it's the program you use
+ to read and write Usenet news.
+
+2003-03-31 20:08:19 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+ * gnus.el: Oort Gnus v0.17 is released.
+
+2003-03-31 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus-start.el (gnus-unload): Removed.
+
+ * pop3.el (pop3-read-response): Use
+ nnheader-accept-process-output.
+ (pop3-retr): Ditto.
+
+ * mm-view.el (mm-text-html-renderer-alist): Add -nolist to Lynx.
+ (mm-text-html-washer-alist): Ditto.
+
+2003-03-31 Simon Josefsson <jas@extundo.com>
+
+ * imap.el (imap-gssapi-program): Also try GNU SASL.
+ (imap-gssapi-open): Accept GNU SASL greeting.
+ (imap-read-timeout): New.
+ (imap-wait-for-tag): Use it.
+
+2003-03-31 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * nntp.el (nntp-accept-process-output): Use new function.
+
+ * nnheader.el (nnheader-read-timeout): New variable.
+ (nnheader-accept-process-output): New function.
+
+ * nntp.el (nntp-read-timeout): Removed.
+
+ * gnus-sum.el (gnus-summary-prepare-threads): Add comment.
+
+2003-03-30 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * gnus-cache.el (gnus-cache-braid-nov): Revoke last change.
+
+2003-03-30 Simon Josefsson <jas@extundo.com>
+
+ * message.el (message-idna-inside-rhs-p): Narrow to header before
+ searching.
+
+ * gnus-art.el (article-decode-idna-rhs): More restrictive regexp.
+
+2003-03-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * nnmail.el (nnmail-process-mmdf-mail-format): Indent.
+
+2003-03-28 Vasily Korytov <deskpot@myrealbox.com>
+
+ * message.el (message-make-in-reply-to): Use
+ mail-extract-address-components to dentermine sender's
+ name/address.
+
+2003-03-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * nndoc.el (nndoc-type-alist): Move mime-parts further ahead.
+
+ * gnus-registry.el (gnus-registry-translate-to-alist): Make a
+ valid lambda.
+ (gnus-registry-translate-from-alist): Ditto.
+
+ * gnus-start.el (gnus-gnus-to-quick-newsrc-format): Bind
+ print-length to nil.
+
+ * gnus-sum.el (gnus-summary-highlight-line-0): Indent.
+
+ * gnus-fun.el (gnus-fun-ppm-change-string): New function.
+ (gnus-grab-cam-face): Use it.
+
+2003-03-28 Paul Jarc <prj@po.cwru.edu>
+
+ * nnmaildir.el (nnmaildir-request-set-mark,
+ nnmaildir-close-group): Allow each mark directory in a group to
+ have its own inode for mark files, to accommodate AFS.
+
+2003-03-28 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnus-start.el (gnus-read-newsrc-el-hook): new hook called by gnus-read-newsrc-el-file
+ (gnus-read-newsrc-el-file): call the gnus-read-newsrc-el-hook
+
+ * gnus-registry.el (gnus-registry-translate-to-alist)
+ (gnus-registry-translate-from-alist, alist-to-hashtable)
+ (hashtable-to-alist): new functions
+ (gnus-register-spool-action): add a spool item to the registry
+
+ * gnus.el (gnus-variable-list): added gnus-registry-alist to the
+ list of saved variables
+ (gnus-registry-alist): new variable
+
+2003-03-27 Simon Josefsson <jas@extundo.com>
+
+ * gnus-art.el (article-decode-group-name): Be correct instead of
+ smart.
+
+2003-03-27 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * lpath.el: Bind url-current-object for FSF Emacs; bind
+ gnus-agent-expire-current-dirs for XEmacs; fbind open-ssl-stream
+ for both Emacsen.
+
+2003-03-27 Jesper Harder <harder@ifa.au.dk>
+
+ * gnus-sum.el (gnus-article-loose-mime)
+ (gnus-article-emulate-mime): Move to gnus-article-mime customize
+ group.
+
+ * gnus-msg.el (gnus-mailing-list-groups): Fix customize type and
+ doc string.
+
+2003-03-26 Kevin Ryde <user42@zip.com.au>
+
+ * gnus-sum.el (gnus-summary-find-for-reselect): Renamed from
+ gnus-summary-find-uncancelled, skip temporary articles inserted by
+ "refer" functions.
+
+2003-03-26 Vasily Korytov <deskpot@myrealbox.com>
+
+ * smiley.el (smiley-buffer): New function.
+
+2003-03-26 Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+ * gnus-agent.el (gnus-agent-fetch-selected-article): Replaced
+ gnus-summary-update-line (which updated the article's face) with
+ gnus-summary-update-download-mark (which updates the article's
+ face by calling gnus-summary-update-line AND updates the download
+ mark to show that the article was fetched).
+
+2003-03-23 Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+ * gnus-agent.el (gnus-agent-expire-unagentized-dirs): Provides
+ option of deleting agent directories for groups/servers that are
+ not currently agentized.
+ (gnus-agent-expire): Use gnus-agent-expire-unagentized-dirs.
+
+ * gnus-int.el (gnus-open-server): Report backend errors in
+ condition handler.
+
+2003-03-23 Simon Josefsson <jas@extundo.com>
+
+ * message.el (message-idna-to-ascii-rhs-1): Don't continue outside
+ header.
+
+ * rfc2047.el (rfc2047-header-encoding-alist): Make Followup-To
+ same as Newsgroups.
+
+ * nntp.el (nntp-open-connection-function): Mention
+ nntp-open-tls-stream.
+ (nntp-open-tls-stream): New function.
+
+ * tls.el: New file.
+
+ * nnimap.el (nnimap-server-port, nnimap-stream): Say TLS/SSL
+ instead of SSL.
+ (nnimap-stream): Add other streams, link to imap variables.
+ (nnimap-authenticator): Add other authenticator, link to imap
+ variables.
+
+ * imap.el: Autoload open-tls-stream.
+ (imap-streams): Add tls in front of ssl.
+ (imap-stream-alist): Add tls.
+ (imap-default-tls-port): New variable.
+ (imap-tls-p, imap-tls-open): New functions.
+
+2003-03-22 ShengHuo ZHU <zsh@cs.rochester.edu>
+
+ * mm-url.el (mm-url-insert-file-contents): parse url only if
+ results is a list.
+
+2003-03-22 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * mail-source.el (mail-source-fetch-imap): Revert.
+
+2003-03-22 Svend Tollak Munkejord <stm@bacchus.pvv.org>
+
+ * deuglify.el (gnus-outlook-repair-attribution-outlook): Use a
+ less strict regexp.
+
+2003-03-22 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * mail-source.el (mail-source-fetch-imap): Use buffer name for
+ more imap function.
+
+2003-03-21 Simon Josefsson <jas@extundo.com>
+
+ * gnus-art.el (article-decode-group-name): Replace Newsgroups and
+ Followup-To data inline.
+
+2003-03-21 Jesper Harder <harder@ifa.au.dk>
+
+ * gnus-art.el (gnus-treat-display-xface): Don't enable if
+ icontopbm isn't available.
+
+2003-03-21 Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+ * gnus-int.el (gnus-open-server): Catch errors in backend's
+ open-server method. Returns nil rather than crashing startup.
+
+ * gnus-sum.el (eval-when-compile): Modified to resolve
+ compile-time warnings.
+
+ * gnus-uu.el (gnus-uu-mark-series): Added informative msg.
+ Reports length of series so that the user can compare N with a
+ subject that should, if the entire series is present, contain
+ '(.../N)'.
+ (gnus-uu-delete-work-dir): Avoid hanging when O/S forbids deletion
+ of temp file (Win-XP may leave the temp file locked when the
+ uudecode process fails).
+
+2003-03-20 ShengHuo ZHU <zsh@cs.rochester.edu>
+
+ * message.el (message-split-line): Ignore error.
+
+ * lpath.el (split-line): Avoid split-line warning message.
+
+2003-03-20 Kim F. Storm <storm@cua.dk>
+
+ * message.el (message-split-line): New function.
+ (message-mode-map): Remap split-line to message-split-line.
+
+2003-03-20 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * message.el (message-make-overlay): Defalias it to make-overlay.
+ (message-delete-overlay): Defalias it to delete-overlay.
+ (message-overlay-put): Defalias it to overlay-put.
+ (message-idna-to-ascii-rhs-1): Use them.
+
+ * messagexmas.el (message-xmas-redefine): Defalias some overlay
+ functions to extent functions.
+
+2003-03-20 Reiner Steib <Reiner.Steib@gmx.de>
+
+ * message.el (message-check-news-header-syntax): Fixed regexp.
+
+2003-03-20 ShengHuo ZHU <zsh@cs.rochester.edu>
+
+ * rfc2231.el (rfc2231-decode-encoded-string): Downcase charset.
+
+ * mm-url.el (mm-url-insert): Move url-current-object stuff into
+ mm-url-insert-file-contents.
+
+ * nnrss.el (nnrss-fetch): Fetch the local stuff.
+ (nnrss-check-group): Use it.
+
+2003-03-20 Mark A. Hershberger <mah@everybody.org>
+
+ * nnrss.el: Primitive XML Name-space support. This means that RSS
+ feeds like Kevin Burton's[1] can now be read in Gnus.
+
+ Implemented support for Mark Pilgrim's RSS Autodiscovery.[2] This
+ means that if you want to read the RSS feed for example.com, all
+ you have to do is hit "G R http://www.example.com/ RET" and
+ nnrss.el will find and the feed listed on the site or (if you have
+ loaded xml-rpc.el) look it up on syndic8.com.
+
+ Marked the message as HTML (by adding a Content-Type header) so
+ that Gnus will render it as html if the user wants that.
+
+ Implemented the ability to save nnrss-group-alist so that any new
+ feeds the you subscribe to will be found the next time you start
+ up.
+
+ Implemented support for RSS 2.0 elements (author, pubDate).
+
+ Prefer for <content:encoded> over <description> where both
+ elements exist.
+
+ * mm-url.el (mm-url-insert): Set url-current-object.
+
+ * gnus-group.el (gnus-group-make-rss-group): New function.
+
+2003-03-20 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * message.el (message-idna-to-ascii-rhs-1): Don't use replace-*
+ for highlight overlays.
+
+2003-03-20 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * gnus-cache.el (gnus-cache-braid-nov): Test if a line looks like
+ a NOV.
+
+2003-03-20 Simon Josefsson <jas@extundo.com>
+
+ * message.el (message-use-idna): Disable if UTF-8 unavailable.
+ (message-idna-to-ascii-rhs): Use it.
+
+ * gnus-art.el (gnus-use-idna): Disable if UTF-8 unavailable.
+
+2003-03-19 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * spam.el (spam-group-ham-mark-p, spam-group-spam-mark-p)
+ (spam-group-ham-marks, spam-group-spam-marks): new functions
+ (spam-spam-marks, spam-ham-marks): removed in favor of the
+ spam-marks and ham-marks parameters
+ (spam-generic-register-routine, spam-ham-move-routine): use the
+ new spam-group-{spam,ham}-mark-p functions
+
+ * gnus.el (spam-marks, ham-marks): new group parameters with
+ default values same as the old spam-spam-marks and spam-ham-marks
+
+2003-03-19 Simon Josefsson <jas@extundo.com>
+
+ * gnus-art.el (gnus-article-decode-hook): Add IDNA.
+ (gnus-use-idna): New variable.
+ (article-decode-idna-rhs): New function.
+
+ * message.el (message-use-idna): New variable.
+ (message-mode-field-menu): Add entry for IDNA.
+ (message-idna-inside-rhs-p, message-idna-to-ascii-rhs-1)
+ (message-idna-to-ascii-rhs): New function.
+ (message-generate-headers): Invoke IDNA code.
+
+2003-03-19 Paul Jarc <prj@po.cwru.edu>
+
+ * nnmaildir.el (nnmaildir--system-name): New function.
+ (nnmaildir-request-accept-article): Use it.
+
+2003-03-19 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * gnus-util.el (gnus-byte-compile): Make it work silently as the
+ gnus-compile function does.
+
+ * gnus-sum.el (gnus-summary-highlight-line-0): Revoke the last
+ bogus change.
+
+2003-03-19 Jesper Harder <harder@ifa.au.dk>
+
+ * mm-util.el (mm-mule-charset-to-mime-charset): Test if
+ sort-coding-systems is defined.
+
+2003-03-18 Paul Jarc <prj@po.cwru.edu>
+
+ * nnmaildir.el (nnmaildir-open-server,
+ nnmaildir-request-scan,
+ nnmaildir-request-create-group,
+ nnmaildir-request-delete-group): Replace create-directory with
+ target-prefix.
+
+2003-03-18 Jesper Harder <harder@ifa.au.dk>
+
+ * mm-bodies.el (mm-decode-coding-region-safely): Don't use
+ find-charset-region which is slooow in XEmacs.
+
+2003-03-18 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * gnus-sum.el (gnus-summary-highlight-line-0): Silence the byte-
+ compiler under XEmacs.
+
+2003-03-18 Jesper Harder <harder@ifa.au.dk>
+
+ * gnus-art.el (gnus-treat-highlight-signature): Make the default
+ work for multipart/signed where the message text isn't `last'.
+
+2003-03-18 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * mm-view.el (mm-setup-w3m): Set w3m-display-inline-images to
+ the value of mm-inline-text-html-with-images.
+ (mm-inline-text-html-render-with-w3m): Don't bind
+ w3m-display-inline-images.
+
+ * gnus-art.el (gnus-article-wash-html-with-w3m): Don't bind
+ w3m-display-inline-images.
+
+ * lpath.el: Bind w3m-display-inline-images; bind mm-w3m-mode-map
+ regardless of an Emacs flavor.
+
+2003-03-18 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus.el (gnus-version-number): Bump.
+
2003-03-18 00:38:22 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
* gnus.el: Oort Gnus v0.16 is released.
* lpath.el (featurep): Bind mm-w3m-mode-map.
-2003-03-12 Paul Jarc <prj@po.cwru.edu>
+2003-03-17 Paul Jarc <prj@po.cwru.edu>
* nnmail.el (nnmail-cache-primary-mail-backend): Not all
'respool-able backends define a global nnchoke-get-new-mail
(gnus-with-article-buffer
(article-goto-body)
(if (re-search-forward
- (concat "^[" cite-marks " \t]*----* ?[^-]+ [^-]+ ?----*\n"
+ (concat "^[" cite-marks " \t]*--* ?[^-]+ [^-]+ ?--*\\s *\n"
"[^\n:]+:[ \t]*\\([^\n]+\\)\n"
"\\([^\n:]+:[ \t]*[^\n]+\n\\)+")
nil t)
(list gnus-current-article))
(setq gnus-newsgroup-undownloaded
(delq gnus-current-article gnus-newsgroup-undownloaded))
- (gnus-summary-update-line gnus-current-article)))))
+ (gnus-summary-update-download-mark gnus-current-article)))))
;;;
;;; Internal functions
;; gnus-command-method, initialized overview buffer, and to have
;; provided a non-nil active
- (if (eq 'DISABLE (gnus-agent-find-parameter group 'agent-enable-expiration))
- (gnus-message 5 "Expiry skipping over %s" group)
- (gnus-message 5 "Expiring articles in %s" group)
- (gnus-agent-load-alist group)
- (let* ((info (gnus-get-info group))
- (alist gnus-agent-article-alist)
- (dir (concat
- (gnus-agent-directory)
- (gnus-agent-group-path group)
- "/"))
- (day (- (time-to-days (current-time))
- (gnus-agent-find-parameter group 'agent-days-until-old)))
- (specials (if (and alist
- (not force))
- ;; This could be a bit of a problem. I need to
- ;; keep the last article to avoid refetching
- ;; headers when using nntp in the backend. At
- ;; the same time, if someone uses a backend
- ;; that supports article moving then I may have
- ;; to remove the last article to complete the
- ;; move. Right now, I'm going to assume that
- ;; FORCE overrides specials.
- (list (caar (last alist)))))
- (unreads ;; Articles that are excluded from the
- ;; expiration process
- (cond (gnus-agent-expire-all
- ;; All articles are marked read by global decree
- nil)
- ((eq articles t)
- ;; All articles are marked read by function
- ;; parameter
- nil)
- ((not articles)
- ;; Unread articles are marked protected from
- ;; expiration Don't call
- ;; gnus-list-of-unread-articles as it returns
- ;; articles that have not been fetched into the
- ;; agent.
- (ignore-errors
- (gnus-agent-unread-articles group)))
- (t
- ;; All articles EXCEPT those named by the caller
- ;; are protected from expiration
- (gnus-sorted-difference
- (gnus-uncompress-range
- (cons (caar alist)
- (caar (last alist))))
- (sort articles '<)))))
- (marked ;; More articles that are exluded from the
- ;; expiration process
- (cond (gnus-agent-expire-all
- ;; All articles are unmarked by global decree
- nil)
- ((eq articles t)
- ;; All articles are unmarked by function
- ;; parameter
- nil)
- (articles
- ;; All articles may as well be unmarked as the
- ;; unreads list already names the articles we are
- ;; going to keep
- nil)
- (t
- ;; Ticked and/or dormant articles are excluded
- ;; from expiration
- (nconc
- (gnus-uncompress-range
- (cdr (assq 'tick (gnus-info-marks info))))
- (gnus-uncompress-range
- (cdr (assq 'dormant
- (gnus-info-marks info))))))))
- (nov-file (concat dir ".overview"))
- (cnt 0)
- (completed -1)
- dlist
- type)
-
- ;; The normal article alist contains elements that look like
- ;; (article# . fetch_date) I need to combine other
- ;; information with this list. For example, a flag indicating
- ;; that a particular article MUST BE KEPT. To do this, I'm
- ;; going to transform the elements to look like (article#
- ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse
- ;; the process to generate the expired article alist.
-
- ;; Convert the alist elements to (article# fetch_date nil
- ;; nil).
- (setq dlist (mapcar (lambda (e)
- (list (car e) (cdr e) nil nil)) alist))
-
- ;; Convert the keep lists to elements that look like (article#
- ;; nil keep_flag nil) then append it to the expanded dlist
- ;; These statements are sorted by ascending precidence of the
- ;; keep_flag.
- (setq dlist (nconc dlist
- (mapcar (lambda (e)
- (list e nil 'unread nil))
- unreads)))
- (setq dlist (nconc dlist
- (mapcar (lambda (e)
- (list e nil 'marked nil))
- marked)))
- (setq dlist (nconc dlist
- (mapcar (lambda (e)
- (list e nil 'special nil))
- specials)))
-
- (set-buffer overview)
- (erase-buffer)
- (buffer-disable-undo)
- (when (file-exists-p nov-file)
- (gnus-message 7 "gnus-agent-expire: Loading overview...")
- (nnheader-insert-file-contents nov-file)
- (goto-char (point-min))
-
- (let (p)
- (while (< (setq p (point)) (point-max))
- (condition-case nil
- ;; If I successfully read an integer (the plus zero
- ;; ensures a numeric type), prepend a marker entry
- ;; to the list
- (push (list (+ 0 (read (current-buffer))) nil nil
- (set-marker (make-marker) p))
- dlist)
- (error
- (gnus-message 1 "gnus-agent-expire: read error \
+ (let ((dir (concat
+ (gnus-agent-directory)
+ (gnus-agent-group-path group)
+ "/")))
+ (when (boundp 'gnus-agent-expire-current-dirs)
+ (set 'gnus-agent-expire-current-dirs
+ (cons dir
+ (symbol-value 'gnus-agent-expire-current-dirs))))
+
+ (if (eq 'DISABLE (gnus-agent-find-parameter group
+ 'agent-enable-expiration))
+ (gnus-message 5 "Expiry skipping over %s" group)
+ (gnus-message 5 "Expiring articles in %s" group)
+ (gnus-agent-load-alist group)
+ (let* ((info (gnus-get-info group))
+ (alist gnus-agent-article-alist)
+ (day (- (time-to-days (current-time))
+ (gnus-agent-find-parameter group 'agent-days-until-old)))
+ (specials (if (and alist
+ (not force))
+ ;; This could be a bit of a problem. I need to
+ ;; keep the last article to avoid refetching
+ ;; headers when using nntp in the backend. At
+ ;; the same time, if someone uses a backend
+ ;; that supports article moving then I may have
+ ;; to remove the last article to complete the
+ ;; move. Right now, I'm going to assume that
+ ;; FORCE overrides specials.
+ (list (caar (last alist)))))
+ (unreads ;; Articles that are excluded from the
+ ;; expiration process
+ (cond (gnus-agent-expire-all
+ ;; All articles are marked read by global decree
+ nil)
+ ((eq articles t)
+ ;; All articles are marked read by function
+ ;; parameter
+ nil)
+ ((not articles)
+ ;; Unread articles are marked protected from
+ ;; expiration Don't call
+ ;; gnus-list-of-unread-articles as it returns
+ ;; articles that have not been fetched into the
+ ;; agent.
+ (ignore-errors
+ (gnus-agent-unread-articles group)))
+ (t
+ ;; All articles EXCEPT those named by the caller
+ ;; are protected from expiration
+ (gnus-sorted-difference
+ (gnus-uncompress-range
+ (cons (caar alist)
+ (caar (last alist))))
+ (sort articles '<)))))
+ (marked ;; More articles that are exluded from the
+ ;; expiration process
+ (cond (gnus-agent-expire-all
+ ;; All articles are unmarked by global decree
+ nil)
+ ((eq articles t)
+ ;; All articles are unmarked by function
+ ;; parameter
+ nil)
+ (articles
+ ;; All articles may as well be unmarked as the
+ ;; unreads list already names the articles we are
+ ;; going to keep
+ nil)
+ (t
+ ;; Ticked and/or dormant articles are excluded
+ ;; from expiration
+ (nconc
+ (gnus-uncompress-range
+ (cdr (assq 'tick (gnus-info-marks info))))
+ (gnus-uncompress-range
+ (cdr (assq 'dormant
+ (gnus-info-marks info))))))))
+ (nov-file (concat dir ".overview"))
+ (cnt 0)
+ (completed -1)
+ dlist
+ type)
+
+ ;; The normal article alist contains elements that look like
+ ;; (article# . fetch_date) I need to combine other
+ ;; information with this list. For example, a flag indicating
+ ;; that a particular article MUST BE KEPT. To do this, I'm
+ ;; going to transform the elements to look like (article#
+ ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse
+ ;; the process to generate the expired article alist.
+
+ ;; Convert the alist elements to (article# fetch_date nil
+ ;; nil).
+ (setq dlist (mapcar (lambda (e)
+ (list (car e) (cdr e) nil nil)) alist))
+
+ ;; Convert the keep lists to elements that look like (article#
+ ;; nil keep_flag nil) then append it to the expanded dlist
+ ;; These statements are sorted by ascending precidence of the
+ ;; keep_flag.
+ (setq dlist (nconc dlist
+ (mapcar (lambda (e)
+ (list e nil 'unread nil))
+ unreads)))
+ (setq dlist (nconc dlist
+ (mapcar (lambda (e)
+ (list e nil 'marked nil))
+ marked)))
+ (setq dlist (nconc dlist
+ (mapcar (lambda (e)
+ (list e nil 'special nil))
+ specials)))
+
+ (set-buffer overview)
+ (erase-buffer)
+ (buffer-disable-undo)
+ (when (file-exists-p nov-file)
+ (gnus-message 7 "gnus-agent-expire: Loading overview...")
+ (nnheader-insert-file-contents nov-file)
+ (goto-char (point-min))
+
+ (let (p)
+ (while (< (setq p (point)) (point-max))
+ (condition-case nil
+ ;; If I successfully read an integer (the plus zero
+ ;; ensures a numeric type), prepend a marker entry
+ ;; to the list
+ (push (list (+ 0 (read (current-buffer))) nil nil
+ (set-marker (make-marker) p))
+ dlist)
+ (error
+ (gnus-message 1 "gnus-agent-expire: read error \
occurred when reading expression at %s in %s. Skipping to next \
line." (point) nov-file)))
- ;; Whether I succeeded, or failed, it doesn't matter.
- ;; Move to the next line then try again.
- (forward-line 1)))
- (gnus-message
- 7 "gnus-agent-expire: Loading overview... Done"))
- (set-buffer-modified-p nil)
-
- ;; At this point, all of the information is in dlist. The
- ;; only problem is that much of it is spread across multiple
- ;; entries. Sort then MERGE!!
- (gnus-message 7 "gnus-agent-expire: Sorting entries... ")
- ;; If two entries have the same article-number then sort by
- ;; ascending keep_flag.
- (let ((special 0)
- (marked 1)
- (unread 2))
- (setq dlist
- (sort dlist
- (lambda (a b)
- (cond ((< (nth 0 a) (nth 0 b))
- t)
- ((> (nth 0 a) (nth 0 b))
- nil)
- (t
- (let ((a (or (symbol-value (nth 2 a))
- 3))
- (b (or (symbol-value (nth 2 b))
- 3)))
- (<= a b))))))))
- (gnus-message 7 "gnus-agent-expire: Sorting entries... Done")
- (gnus-message 7 "gnus-agent-expire: Merging entries... ")
- (let ((dlist dlist))
- (while (cdr dlist) ; I'm not at the end-of-list
- (if (eq (caar dlist) (caadr dlist))
- (let ((first (cdr (car dlist)))
- (secnd (cdr (cadr dlist))))
- (setcar first (or (car first)
- (car secnd))) ; fetch_date
- (setq first (cdr first)
- secnd (cdr secnd))
- (setcar first (or (car first)
- (car secnd))) ; Keep_flag
- (setq first (cdr first)
- secnd (cdr secnd))
- (setcar first (or (car first)
- (car secnd))) ; NOV_entry_marker
-
- (setcdr dlist (cddr dlist)))
- (setq dlist (cdr dlist)))))
- (gnus-message 7 "gnus-agent-expire: Merging entries... Done")
-
- (let* ((len (float (length dlist)))
- (alist (list nil))
- (tail-alist alist))
- (while dlist
- (let ((new-completed (truncate (* 100.0
- (/ (setq cnt (1+ cnt))
- len)))))
- (when (> new-completed completed)
- (setq completed new-completed)
- (gnus-message 7 "%3d%% completed..." completed)))
- (let* ((entry (car dlist))
- (article-number (nth 0 entry))
- (fetch-date (nth 1 entry))
- (keep (nth 2 entry))
- (marker (nth 3 entry)))
-
- (cond
- ;; Kept articles are unread, marked, or special.
- (keep
- (gnus-agent-message 10
- "gnus-agent-expire: Article %d: Kept %s article."
- article-number keep)
- (when fetch-date
- (unless (file-exists-p
- (concat dir (number-to-string
- article-number)))
- (setf (nth 1 entry) nil)
- (gnus-agent-message 3 "gnus-agent-expire cleared \
+ ;; Whether I succeeded, or failed, it doesn't matter.
+ ;; Move to the next line then try again.
+ (forward-line 1)))
+
+ (gnus-message
+ 7 "gnus-agent-expire: Loading overview... Done"))
+ (set-buffer-modified-p nil)
+
+ ;; At this point, all of the information is in dlist. The
+ ;; only problem is that much of it is spread across multiple
+ ;; entries. Sort then MERGE!!
+ (gnus-message 7 "gnus-agent-expire: Sorting entries... ")
+ ;; If two entries have the same article-number then sort by
+ ;; ascending keep_flag.
+ (let ((special 0)
+ (marked 1)
+ (unread 2))
+ (setq dlist
+ (sort dlist
+ (lambda (a b)
+ (cond ((< (nth 0 a) (nth 0 b))
+ t)
+ ((> (nth 0 a) (nth 0 b))
+ nil)
+ (t
+ (let ((a (or (symbol-value (nth 2 a))
+ 3))
+ (b (or (symbol-value (nth 2 b))
+ 3)))
+ (<= a b))))))))
+ (gnus-message 7 "gnus-agent-expire: Sorting entries... Done")
+ (gnus-message 7 "gnus-agent-expire: Merging entries... ")
+ (let ((dlist dlist))
+ (while (cdr dlist) ; I'm not at the end-of-list
+ (if (eq (caar dlist) (caadr dlist))
+ (let ((first (cdr (car dlist)))
+ (secnd (cdr (cadr dlist))))
+ (setcar first (or (car first)
+ (car secnd))) ; fetch_date
+ (setq first (cdr first)
+ secnd (cdr secnd))
+ (setcar first (or (car first)
+ (car secnd))) ; Keep_flag
+ (setq first (cdr first)
+ secnd (cdr secnd))
+ (setcar first (or (car first)
+ (car secnd))) ; NOV_entry_marker
+
+ (setcdr dlist (cddr dlist)))
+ (setq dlist (cdr dlist)))))
+ (gnus-message 7 "gnus-agent-expire: Merging entries... Done")
+
+ (let* ((len (float (length dlist)))
+ (alist (list nil))
+ (tail-alist alist))
+ (while dlist
+ (let ((new-completed (truncate (* 100.0
+ (/ (setq cnt (1+ cnt))
+ len)))))
+ (when (> new-completed completed)
+ (setq completed new-completed)
+ (gnus-message 7 "%3d%% completed..." completed)))
+ (let* ((entry (car dlist))
+ (article-number (nth 0 entry))
+ (fetch-date (nth 1 entry))
+ (keep (nth 2 entry))
+ (marker (nth 3 entry)))
+
+ (cond
+ ;; Kept articles are unread, marked, or special.
+ (keep
+ (gnus-agent-message 10
+ "gnus-agent-expire: Article %d: Kept %s article."
+ article-number keep)
+ (when fetch-date
+ (unless (file-exists-p
+ (concat dir (number-to-string
+ article-number)))
+ (setf (nth 1 entry) nil)
+ (gnus-agent-message 3 "gnus-agent-expire cleared \
download flag on article %d as the cached article file is missing."
- (caar dlist)))
- (unless marker
- (gnus-message 1 "gnus-agent-expire detected a \
+ (caar dlist)))
+ (unless marker
+ (gnus-message 1 "gnus-agent-expire detected a \
missing NOV entry. Run gnus-agent-regenerate-group to restore it.")))
- (gnus-agent-append-to-list
- tail-alist
- (cons article-number fetch-date)))
-
- ;; The following articles are READ, UNMARKED, and
- ;; ORDINARY. See if they can be EXPIRED!!!
- ((setq type
- (cond
- ((not (integerp fetch-date))
- 'read) ;; never fetched article (may expire
- ;; right now)
- ((not (file-exists-p
- (concat dir (number-to-string
- article-number))))
- (setf (nth 1 entry) nil)
- 'externally-expired) ;; Can't find the cached
- ;; article. Handle case
- ;; as though this article
- ;; was never fetched.
-
- ;; We now have the arrival day, so we see
- ;; whether it's old enough to be expired.
- ((< fetch-date day)
- 'expired)
- (force
- 'forced)))
-
- ;; I found some reason to expire this entry.
-
- (let ((actions nil))
- (when (memq type '(forced expired))
- (ignore-errors ; Just being paranoid.
- (delete-file (concat dir (number-to-string
- article-number)))
- (push "expired cached article" actions))
- (setf (nth 1 entry) nil)
- )
-
- (when marker
- (push "NOV entry removed" actions)
- (goto-char marker)
- (gnus-delete-line))
-
- ;; If considering all articles is set, I can only
- ;; expire article IDs that are no longer in the
- ;; active range.
- (if (and gnus-agent-consider-all-articles
- (>= article-number (car active)))
- ;; I have to keep this ID in the alist
- (gnus-agent-append-to-list
- tail-alist (cons article-number fetch-date))
- (push (format "Removed %s article number from \
+ (gnus-agent-append-to-list
+ tail-alist
+ (cons article-number fetch-date)))
+
+ ;; The following articles are READ, UNMARKED, and
+ ;; ORDINARY. See if they can be EXPIRED!!!
+ ((setq type
+ (cond
+ ((not (integerp fetch-date))
+ 'read) ;; never fetched article (may expire
+ ;; right now)
+ ((not (file-exists-p
+ (concat dir (number-to-string
+ article-number))))
+ (setf (nth 1 entry) nil)
+ 'externally-expired) ;; Can't find the cached
+ ;; article. Handle case
+ ;; as though this article
+ ;; was never fetched.
+
+ ;; We now have the arrival day, so we see
+ ;; whether it's old enough to be expired.
+ ((< fetch-date day)
+ 'expired)
+ (force
+ 'forced)))
+
+ ;; I found some reason to expire this entry.
+
+ (let ((actions nil))
+ (when (memq type '(forced expired))
+ (ignore-errors ; Just being paranoid.
+ (delete-file (concat dir (number-to-string
+ article-number)))
+ (push "expired cached article" actions))
+ (setf (nth 1 entry) nil)
+ )
+
+ (when marker
+ (push "NOV entry removed" actions)
+ (goto-char marker)
+ (gnus-delete-line))
+
+ ;; If considering all articles is set, I can only
+ ;; expire article IDs that are no longer in the
+ ;; active range.
+ (if (and gnus-agent-consider-all-articles
+ (>= article-number (car active)))
+ ;; I have to keep this ID in the alist
+ (gnus-agent-append-to-list
+ tail-alist (cons article-number fetch-date))
+ (push (format "Removed %s article number from \
article alist" type) actions))
- (gnus-agent-message 8 "gnus-agent-expire: Article %d: %s"
- article-number
- (mapconcat 'identity actions ", "))))
- (t
- (gnus-agent-message
- 10 "gnus-agent-expire: Article %d: Article kept as \
+ (gnus-agent-message 8 "gnus-agent-expire: Article %d: %s"
+ article-number
+ (mapconcat 'identity actions ", "))))
+ (t
+ (gnus-agent-message
+ 10 "gnus-agent-expire: Article %d: Article kept as \
expiration tests failed." article-number)
- (gnus-agent-append-to-list
- tail-alist (cons article-number fetch-date)))
- )
+ (gnus-agent-append-to-list
+ tail-alist (cons article-number fetch-date)))
+ )
- ;; Clean up markers as I want to recycle this buffer
- ;; over several groups.
- (when marker
- (set-marker marker nil))
+ ;; Clean up markers as I want to recycle this buffer
+ ;; over several groups.
+ (when marker
+ (set-marker marker nil))
- (setq dlist (cdr dlist))))
+ (setq dlist (cdr dlist))))
- (setq alist (cdr alist))
+ (setq alist (cdr alist))
- (let ((inhibit-quit t))
- (unless (equal alist gnus-agent-article-alist)
- (setq gnus-agent-article-alist alist)
- (gnus-agent-save-alist group))
+ (let ((inhibit-quit t))
+ (unless (equal alist gnus-agent-article-alist)
+ (setq gnus-agent-article-alist alist)
+ (gnus-agent-save-alist group))
- (when (buffer-modified-p)
- (let ((coding-system-for-write
- gnus-agent-file-coding-system))
- (gnus-make-directory dir)
- (write-region (point-min) (point-max) nov-file nil
- 'silent)
- ;; clear the modified flag as that I'm not confused by
- ;; its status on the next pass through this routine.
- (set-buffer-modified-p nil)))
+ (when (buffer-modified-p)
+ (let ((coding-system-for-write
+ gnus-agent-file-coding-system))
+ (gnus-make-directory dir)
+ (write-region (point-min) (point-max) nov-file nil
+ 'silent)
+ ;; clear the modified flag as that I'm not confused by
+ ;; its status on the next pass through this routine.
+ (set-buffer-modified-p nil)))
- (when (eq articles t)
- (gnus-summary-update-info)))))))
+ (when (eq articles t)
+ (gnus-summary-update-info))))))))
(defun gnus-agent-expire (&optional articles group force)
"Expire all old articles.
(yes-or-no-p "Are you sure that you want to expire all \
articles in every agentized group."))
(let ((methods gnus-agent-covered-methods)
+ ;; Bind gnus-agent-expire-current-dirs to enable tracking
+ ;; of agent directories.
+ (gnus-agent-expire-current-dirs nil)
gnus-command-method overview orig)
(setq overview (gnus-get-buffer-create " *expire overview*"))
(unwind-protect
(gnus-agent-expire-group-1
expiring-group overview active articles force)))))))
(kill-buffer overview))
+ (gnus-agent-expire-unagentized-dirs)
(gnus-message 4 "Expiry...done")))))
+(defun gnus-agent-expire-unagentized-dirs ()
+ (when (boundp 'gnus-agent-expire-current-dirs)
+ (let* ((keep (gnus-make-hashtable))
+ ;; Formally bind gnus-agent-expire-current-dirs so that the
+ ;; compiler will not complain about free references.
+ (gnus-agent-expire-current-dirs
+ (symbol-value 'gnus-agent-expire-current-dirs))
+ dir)
+
+ (gnus-sethash gnus-agent-directory t keep)
+ (while gnus-agent-expire-current-dirs
+ (setq dir (pop gnus-agent-expire-current-dirs))
+ (when (and (stringp dir)
+ (file-directory-p dir))
+ (while (not (gnus-gethash dir keep))
+ (gnus-sethash dir t keep)
+ (setq dir (file-name-directory (directory-file-name dir))))))
+
+ (let* (to-remove
+ checker
+ (checker
+ (function
+ (lambda (d)
+ (let ((files (directory-files d))
+ file)
+ (while (setq file (pop files))
+ (cond ((equal file ".")
+ nil)
+ ((equal file "..")
+ nil)
+ ((equal file ".overview")
+ (let ((d (file-name-as-directory d))
+ r)
+ (while (not (gnus-gethash
+ (setq d (file-name-directory d)) keep))
+ (setq r d
+ d (directory-file-name d)))
+ (if r
+ (push r to-remove))))
+ ((file-directory-p (setq file (nnheader-concat d file)))
+ (funcall checker file)))))))))
+ (funcall checker gnus-agent-directory)
+
+ (when (and to-remove
+ (gnus-y-or-n-p
+ "gnus-agent-expire has identified local directories that are\
+ not currently required by any agentized group. Do you wish to consider\
+ deleting them?"))
+ (while to-remove
+ (let ((dir (pop to-remove)))
+ (if (gnus-y-or-n-p (format "Delete %s?" dir))
+ (let* (delete-recursive
+ (delete-recursive
+ (function
+ (lambda (f-or-d)
+ (ignore-errors
+ (if (file-directory-p f-or-d)
+ (condition-case nil
+ (delete-directory f-or-d)
+ (file-error
+ (mapcar (lambda (f)
+ (or (member f '("." ".."))
+ (funcall delete-recursive
+ (nnheader-concat
+ f-or-d f))))
+ (directory-files f-or-d))
+ (delete-directory f-or-d)))
+ (delete-file f-or-d)))))))
+ (funcall delete-recursive dir))))))))))
+
;;;###autoload
(defun gnus-agent-batch ()
"Start Gnus, send queue and fetch session."
(defcustom gnus-article-decode-hook
'(article-decode-charset article-decode-encoded-words
- article-decode-group-name)
+ article-decode-group-name article-decode-idna-rhs)
"*Hook run to decode charsets in articles."
:group 'gnus-article-headers
:type 'hook)
(defvar gnus-inhibit-treatment nil
"Whether to inhibit treatment.")
-(defcustom gnus-treat-highlight-signature '(or last (typep "text/x-vcard"))
+(defcustom gnus-treat-highlight-signature '(or t (typep "text/x-vcard"))
"Highlight the signature.
Valid values are nil, t, `head', `last', an integer or a predicate.
See Info node `(gnus)Customizing Articles'."
(and (not noninteractive)
(or (and (fboundp 'image-type-available-p)
(image-type-available-p 'xbm)
- (string-match "^0x" (shell-command-to-string "uncompface")))
+ (string-match "^0x" (shell-command-to-string "uncompface"))
+ (executable-find "icontopbm"))
(and (featurep 'xemacs)
(featurep 'xface)))
'head)
(defvar gnus-article-wash-function nil
"Function used for converting HTML into text.")
+(defcustom gnus-use-idna (and (condition-case nil (require 'idna) (file-error))
+ (fboundp 'coding-system-p)
+ (coding-system-p 'utf-8))
+ "Whether IDNA decoding of headers is used when viewing messages.
+This requires GNU Libidn, and by default only enabled if it is found."
+ :group 'gnus-article-headers
+ :type 'boolean)
+
;;; Internal variables
(defvar gnus-english-month-names
(when (and (or gnus-group-name-charset-method-alist
gnus-group-name-charset-group-alist)
(gnus-buffer-live-p gnus-original-article-buffer))
- (when (nnmail-fetch-field "Newsgroups")
- (nnheader-replace-header "Newsgroups"
- (gnus-decode-newsgroups
- (with-current-buffer
- gnus-original-article-buffer
- (nnmail-fetch-field "Newsgroups"))
- gnus-newsgroup-name method)))
- (when (nnmail-fetch-field "Followup-To")
- (nnheader-replace-header "Followup-To"
- (gnus-decode-newsgroups
- (with-current-buffer
- gnus-original-article-buffer
- (nnmail-fetch-field "Followup-To"))
- gnus-newsgroup-name method))))))
+ (save-restriction
+ (article-narrow-to-head)
+ (with-current-buffer gnus-original-article-buffer
+ (goto-char (point-min)))
+ (while (re-search-forward "^Newsgroups:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]"
+ nil t)
+ (replace-match (save-match-data
+ (gnus-decode-newsgroups
+ ;; XXX how to use data in article buffer?
+ (with-current-buffer gnus-original-article-buffer
+ (re-search-forward
+ "^Newsgroups:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]"
+ nil t)
+ (match-string 1))
+ gnus-newsgroup-name method))
+ t t nil 1))
+ (goto-char (point-min))
+ (with-current-buffer gnus-original-article-buffer
+ (goto-char (point-min)))
+ (while (re-search-forward "^Followup-To:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]"
+ nil t)
+ (replace-match (save-match-data
+ (gnus-decode-newsgroups
+ ;; XXX how to use data in article buffer?
+ (with-current-buffer gnus-original-article-buffer
+ (re-search-forward
+ "^Followup-To:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]"
+ nil t)
+ (match-string 1))
+ gnus-newsgroup-name method))
+ t t nil 1))))))
+
+(autoload 'idna-to-unicode "idna")
+
+(defun article-decode-idna-rhs ()
+ "Decode IDNA strings in RHS in From:, To: and Cc: headers in current buffer."
+ (when gnus-use-idna
+ (save-restriction
+ (let ((inhibit-point-motion-hooks t)
+ buffer-read-only)
+ (article-narrow-to-head)
+ (goto-char (point-min))
+ (while (re-search-forward "\\(xn--[-A-Za-z0-9.]*\\)[ \t\n\r,>]" nil t)
+ (let (ace unicode)
+ (when (save-match-data
+ (and (setq ace (match-string 1))
+ (save-excursion
+ (and (re-search-backward "^[^ \t]" nil t)
+ (looking-at "From\\|To\\|Cc")))
+ (save-excursion (backward-char)
+ (message-idna-inside-rhs-p))
+ (setq unicode (idna-to-unicode ace))))
+ (unless (string= ace unicode)
+ (replace-match unicode nil nil nil 1)))))))))
(defun article-de-quoted-unreadable (&optional force read-charset)
"Translate a quoted-printable-encoded article.
(let ((w3m-safe-url-regexp (if mm-inline-text-html-with-images
nil
"\\`cid:"))
- (w3m-display-inline-images mm-inline-text-html-with-images)
w3m-force-redisplay)
(w3m-region (point-min) (point-max)))
(when mm-inline-text-html-with-w3m-keymap
(sleep-for 1))
(setq file (car file))
(shell-command
- (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | ppmnorm 2>/dev/null | ppmnorm | ppmtopgm | pnmscale -width 48 -height 48 > /tmp/gnus.face.ppm"
+ (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | pnmscale -width 48 -height 48 | ppmtopgm > /tmp/gnus.face.ppm"
file))
(let ((gnus-convert-image-to-face-command
- "cat '%s' | ppmquant %d | pnmtopng"))
+ (format "cat '%%s' | ppmquant %%d | ppmchange %s | pnmtopng"
+ (gnus-fun-ppm-change-string))))
(setq result (gnus-face-from-file "/tmp/gnus.face.ppm")))
(delete-file file)
;;(delete-file "/tmp/gnus.face.ppm")
result))
+(defun gnus-fun-ppm-change-string ()
+ (let* ((possibilites '("%02x0000" "00%02x00" "0000%02x"
+ "%02x%02x00" "00%02x%02x" "%02x00%02x"))
+ (format (concat "'#%02x%02x%02x' '#"
+ (nth (random 6) possibilites)
+ "'"))
+ (values nil))
+ (dotimes (i 255)
+ (push (format format i i i i i i)
+ values))
+ (mapconcat 'identity values " ")))
+
(provide 'gnus-fun)
;;; gnus-fun.el ends here
"f" gnus-group-make-doc-group
"w" gnus-group-make-web-group
"r" gnus-group-rename-group
+ "R" gnus-group-make-rss-group
"c" gnus-group-customize
"x" gnus-group-nnimap-expunge
"\177" gnus-group-delete-group
(cons (current-buffer)
(if (eq major-mode 'gnus-summary-mode) 'summary 'group))))))
+(eval-when-compile (defvar nnrss-group-alist)
+ (defun nnrss-discover-feed (arg))
+ (defun nnrss-save-server-data (arg)))
+(defun gnus-group-make-rss-group (&optional url)
+ "Given a URL, discover if there is an RSS feed. If there is,
+use Gnus' to create an nnrss group"
+ (interactive)
+ (require 'nnrss)
+ (if (not url)
+ (setq url (read-from-minibuffer "URL to Search for RSS: ")))
+ (let ((feedinfo (nnrss-discover-feed url)))
+ (if feedinfo
+ (let ((title (read-from-minibuffer "Title: "
+ (cdr (assoc 'title
+ feedinfo))))
+ (desc (read-from-minibuffer "Description: "
+ (cdr (assoc 'description
+ feedinfo))))
+ (href (cdr (assoc 'href feedinfo))))
+ (push (list title href desc)
+ nnrss-group-alist)
+ (gnus-group-unsubscribe-group
+ (concat "nnrss:" title))
+ (nnrss-save-server-data nil))
+ (error "No feeds found for %s" url))))
+
(defvar nnwarchive-type-definition)
(defvar gnus-group-warchive-type-history nil)
(defvar gnus-group-warchive-login-history nil)
:group 'gnus-start
:type '(choice (const :tag "Ask" nil)
(const :tag "Deny server" denied)
- (const :tag "Unplugg Agent" offline)))
+ (const :tag "Unplug Agent" offline)))
(defvar gnus-internal-registry-spool-current-method nil
"The current method, for the registry.")
nil)
;; Open the server.
(let ((result
- (condition-case ()
+ (condition-case err
(funcall (gnus-get-function gnus-command-method 'open-server)
(nth 1 gnus-command-method)
(nthcdr 2 gnus-command-method))
+ (error
+ (gnus-message 1 (format
+ "Unable to open server due to: %s"
+ (error-message-string err)))
+ nil)
(quit
- (message "Quit trying to open server")
+ (gnus-message 1 "Quit trying to open server")
nil))))
;; If this hasn't been opened before, we add it to the list.
(unless elem
(function)))
(defcustom gnus-mailing-list-groups nil
- "*Regexp matching groups that are really mailing lists.
+ "*If non-nil a regexp matching groups that are really mailing lists.
This is useful when you're reading a mailing list that has been
gatewayed to a newsgroup, and you want to followup to an article in
the group."
:group 'gnus-message
- :type 'regexp)
+ :type '(choice (regexp)
+ (const nil)))
(defcustom gnus-add-to-list nil
"*If non-nil, add a `to-list' parameter automatically."
;; alias puthash is missing from Emacs 20 cl-extra.el
(defalias 'puthash 'cl-puthash)))
+(defun gnus-registry-translate-to-alist ()
+ (setq gnus-registry-alist (hashtable-to-alist gnus-registry-hashtb)))
+
+(defun gnus-registry-translate-from-alist ()
+ (setq gnus-registry-hashtb (alist-to-hashtable gnus-registry-alist)))
+
+(defun alist-to-hashtable (alist)
+ "Build a hashtable from the values in ALIST."
+ (let ((ht (make-hash-table
+ :size 4096
+ :test 'equal)))
+ (mapc
+ (lambda (kv-pair)
+ (puthash (car kv-pair) (cdr kv-pair) ht))
+ alist)
+ ht))
+
+(defun hashtable-to-alist (hash)
+ "Build an alist from the values in HASH."
+ (let ((list nil))
+ (maphash
+ (lambda (key value)
+ (setq list (cons (cons key value) list)))
+ hash)))
+
(defun gnus-register-action (action data-header from &optional to method)
(let* ((id (mail-header-id data-header))
(hash-entry (gethash id gnus-registry-hashtb)))
(gnus-group-prefixed-name
group
gnus-internal-registry-spool-current-method
- t)))
+ t))
+ (puthash id (cons (list 'spool nil group nil)
+ (gethash id gnus-registry-hashtb)) gnus-registry-hashtb))
(add-hook 'gnus-summary-article-move-hook 'gnus-register-action) ; also does copy, respool, and crosspost
(add-hook 'gnus-summary-article-delete-hook 'gnus-register-action)
(add-hook 'gnus-summary-article-expire-hook 'gnus-register-action)
(add-hook 'nnmail-spool-hook 'gnus-register-spool-action)
+(add-hook 'gnus-save-newsrc-hook 'gnus-registry-translate-to-alist)
+(add-hook 'gnus-read-newsrc-el-hook 'gnus-registry-translate-from-alist)
+
;; TODO: a lot of things
-;; TODO: we have to load and save the registry through gnus-save-newsrc-file
(provide 'gnus-registry)
:group 'gnus-group-new
:type 'hook)
+(defcustom gnus-read-newsrc-el-hook nil
+ "A hook called after reading the newsrc.eld? file."
+ :group 'gnus-newsrc
+ :type 'hook)
+
(defcustom gnus-save-newsrc-hook nil
"A hook called before saving any of the newsrc files."
:group 'gnus-newsrc
(gnus-group-set-parameter
"nndraft:drafts" 'gnus-dummy '((gnus-draft-mode)))))
-;;;###autoload
-(defun gnus-unload ()
- "Unload all Gnus features.
-\(For some value of `all' or `Gnus'.) Currently, features whose names
-have prefixes `gnus-', `nn', `mm-' or `rfc' are unloaded. Use
-cautiously -- unloading may cause trouble."
- (interactive)
- (dolist (feature features)
- (if (string-match "^\\(gnus-\\|nn\\|mm-\\|rfc\\)" (symbol-name feature))
- (unload-feature feature 'force))))
-
\f
;;;
;;; Dribble file
(gnus-message 5 "Reading %s..." file)
;; The .el file is newer than the .eld file, so we read that one
;; as well.
- (gnus-read-old-newsrc-el-file file))))
+ (gnus-read-old-newsrc-el-file file)))
+ (gnus-run-hooks 'gnus-read-newsrc-el-hook))
;; Parse the old-style quick startup file
(defun gnus-read-old-newsrc-el-file (file)
(unwind-protect
(progn
- (gnus-with-output-to-file
- working-file
- (gnus-gnus-to-quick-newsrc-format)
- (gnus-run-hooks 'gnus-save-quick-newsrc-hook))
+ (gnus-with-output-to-file working-file
+ (gnus-gnus-to-quick-newsrc-format)
+ (gnus-run-hooks 'gnus-save-quick-newsrc-hook))
;; These bindings will mislead the current buffer
;; into thinking that it is visiting the startup
(princ "(setq gnus-newsrc-file-version ")
(princ (gnus-prin1-to-string gnus-version))
(princ ")\n")
- (let* ((gnus-killed-list
+ (let* ((print-length nil)
+ (gnus-killed-list
(if (and gnus-save-killed-list
(stringp gnus-save-killed-list))
(gnus-strip-killed-list)
the MIME-Version header is missed."
:version "21.3"
:type 'boolean
- :group 'gnus-article)
+ :group 'gnus-article-mime)
(defcustom gnus-article-emulate-mime t
"If non-nil, use MIME emulation for uuencode and the like.
like uuencoded bits, yEncoded bits, and so on, and present that using
the normal Gnus MIME machinery."
:type 'boolean
- :group 'gnus-article)
+ :group 'gnus-article-mime)
;;; Internal variables
")
;; Byte-compiler warning.
-;(eval-when-compile (defvar gnus-article-mode-map))
(eval-when-compile
+ ;; Bind features so that require will believe that gnus-sum has
+ ;; already been loaded (avoids infinite recursion)
(let ((features (cons 'gnus-sum features)))
+ ;; Several of the declarations in gnus-sum are needed to load the
+ ;; following files. Right now, these definitions have been
+ ;; compiled but not defined (evaluated). We could either do a
+ ;; eval-and-compile about all of the declarations or evaluate the
+ ;; source file.
+ (if (boundp 'gnus-newsgroup-variables)
+ nil
+ (load "gnus-sum.el" t t t t))
(require 'gnus)
(require 'gnus-agent)
(require 'gnus-art)))
(substring gnus-tmp-from
(1+ (match-beginning 0)) (1- (match-end 0))))
(t gnus-tmp-from))
+
+ ;; Do the %B string
gnus-tmp-thread-tree-header-string
(cond
((not gnus-show-threads) "")
(> (prefix-numeric-value arg) 0)))
(redraw-display))
-(defun gnus-summary-find-uncancelled ()
- "Return the number of an uncancelled article.
+(defun gnus-summary-find-for-reselect ()
+ "Return the number of an article to stay on across a reselect.
The current article is considered, then following articles, then previous
-articles. If all articles are cancelled then return a dummy 0."
+articles. An article is sought which is not cancelled and isn't a temporary
+insertion from another group. If there's no such then return a dummy 0."
(let (found)
(dolist (rev '(nil t))
(unless found ; don't demand the reverse list if we don't need it
(let ((data (gnus-data-find-list
(gnus-summary-article-number) (gnus-data-list rev))))
(while (and data (not found))
- (if (not (eq gnus-canceled-mark (gnus-data-mark (car data))))
+ (if (and (< 0 (gnus-data-number (car data)))
+ (not (eq gnus-canceled-mark (gnus-data-mark (car data)))))
(setq found (gnus-data-number (car data))))
(setq data (cdr data))))))
(or found 0)))
(interactive "P")
(when (gnus-ephemeral-group-p gnus-newsgroup-name)
(error "Ephemeral groups can't be reselected"))
- (let ((current-subject (gnus-summary-find-uncancelled))
+ (let ((current-subject (gnus-summary-find-for-reselect))
(group gnus-newsgroup-name))
(setq gnus-newsgroup-begin nil)
(gnus-summary-exit)
(c cond)
(list gnus-summary-highlight))
(while list
- (setcdr c (cons (list (caar list) (list 'quote (cdar list))) nil))
+ (setcdr c (cons (list (caar list) (list 'quote (cdar list)))
+ nil))
(setq c (cdr c)
list (cdr list)))
(gnus-byte-compile (list 'lambda nil cond))))))
(,buffer (make-string ,size 0))
(,leng 0)
(append nil)
- (standard-output (lambda (c)
- (aset ,buffer ,leng c)
- (if (= ,size (setq ,leng (1+ ,leng)))
- (progn (write-region ,buffer nil ,file append 'no-msg)
- (setq ,leng 0
- append t))))))
+ (standard-output
+ (lambda (c)
+ (aset ,buffer ,leng c)
+ (if (= ,size (setq ,leng (1+ ,leng)))
+ (progn (write-region ,buffer nil ,file append 'no-msg)
+ (setq ,leng 0
+ append t))))))
,@body
- (if (> ,leng 0)
- (write-region (substring ,buffer 0 ,leng) nil ,file append 'no-msg)))))
+ (when (> ,leng 0)
+ (write-region (substring ,buffer 0 ,leng) nil ,file
+ append 'no-msg)))))
(put 'gnus-with-output-to-file 'lisp-indent-function 1)
(put 'gnus-with-output-to-file 'edebug-form-spec '(form body))
(require 'byte-optimize)
(error))
(require 'bytecomp)
- (defalias 'gnus-byte-compile 'byte-compile)
- (byte-compile form))
+ (defalias 'gnus-byte-compile
+ (lambda (form)
+ (let ((byte-compile-warnings '(unresolved callargs redefine)))
+ (byte-compile form))))
+ (gnus-byte-compile form))
form))
(defun gnus-remassoc (key alist)
(defun gnus-uu-mark-series ()
"Mark the current series with the process mark."
(interactive)
- (let ((articles (gnus-uu-find-articles-matching)))
+ (let* ((articles (gnus-uu-find-articles-matching))
+ (l (length articles)))
(while articles
(gnus-summary-set-process-mark (car articles))
(setq articles (cdr articles)))
- (message ""))
+ (message "Marked %d articles" l))
(gnus-summary-position-point))
(defun gnus-uu-mark-region (beg end &optional unmark)
(if (file-directory-p file)
(gnus-uu-delete-work-dir file)
(gnus-message 9 "Deleting file %s..." file)
- (delete-file file))))
- (delete-directory dir)))
- (gnus-message 7 ""))
+ (condition-case err
+ (delete-file file)
+ (error (gnus-message 3 "Deleting file %s failed... %s" file err))))))
+ (condition-case err
+ (delete-directory dir)
+ (error (gnus-message 3 "Deleting directory %s failed... %s" file err))))
+ (gnus-message 7 "")))
;; Initializing
:link '(custom-manual "(gnus)Exiting Gnus")
:group 'gnus)
-(defconst gnus-version-number "0.16"
+(defconst gnus-version-number "0.17"
"Version number for this version of Gnus.")
(defconst gnus-version (format "Oort Gnus v%s" gnus-version-number)
(string :tag "Move to a group")
(const :tag "Expire" nil))))
:parameter-document
- "Where ham articles will go at summary exit from a spam group."))
+ "Where ham articles will go at summary exit from a spam group.")
+
+ (gnus-define-group-parameter
+ ham-marks
+ :type 'list
+ :parameter-type '(list :tag "Ham mark choices"
+ (set
+ (variable-item gnus-del-mark)
+ (variable-item gnus-read-mark)
+ (variable-item gnus-killed-mark)
+ (variable-item gnus-kill-file-mark)
+ (variable-item gnus-low-score-mark)))
+
+ :parameter-document
+ "Marks considered ham (positively not spam). Such articles will be
+processed as ham (non-spam) on group exit. When nil, the global
+spam-ham-marks variable takes precedence."
+ :variable-default '((".*" ((gnus-del-mark
+ gnus-read-mark
+ gnus-killed-mark
+ gnus-kill-file-mark
+ gnus-low-score-mark))))
+ :variable-group spam
+ :variable-document
+ "*Groups in which to explicitly set the ham marks to some value.")
+
+ (gnus-define-group-parameter
+ spam-marks
+ :type 'list
+ :parameter-type '(list :tag "Spam mark choices"
+ (set
+ (variable-item gnus-spam-mark)
+ (variable-item gnus-killed-mark)
+ (variable-item gnus-kill-file-mark)
+ (variable-item gnus-low-score-mark)))
+
+ :parameter-document
+ "Marks considered spam.
+Such articles will be processed as spam on group exit. When nil, the global
+spam-spam-marks variable takes precedence."
+ :variable-default '((".*" ((gnus-spam-mark))))
+ :variable-group spam
+ :variable-document
+ "*Groups in which to explicitly set the spam marks to some value."))
(defcustom gnus-group-uncollapsed-levels 1
"Number of group name elements to leave alone when making a short group name."
'(gnus-newsrc-options gnus-newsrc-options-n
gnus-newsrc-last-checked-date
gnus-newsrc-alist gnus-server-alist
+ gnus-registry-alist
gnus-killed-list gnus-zombie-list
gnus-topic-topology gnus-topic-alist
gnus-agent-covered-methods gnus-format-specs)
"Assoc list of read articles.
gnus-newsrc-hashtb should be kept so that both hold the same information.")
+(defvar gnus-registry-alist nil
+ "Assoc list of registry data.
+gnus-registry.el will populate this if it's loaded.")
+
(defvar gnus-newsrc-hashtb nil
"Hashtable of gnus-newsrc-alist.")
(autoload 'utf7-decode "utf7")
(autoload 'format-spec "format-spec")
(autoload 'format-spec-make "format-spec")
+ (autoload 'open-tls-stream "tls")
;; Avoid use gnus-point-at-eol so we're independent of Gnus. These
;; days we have point-at-eol anyhow.
(if (fboundp 'point-at-eol)
:group 'imap
:type '(repeat string))
-(defcustom imap-gssapi-program '("imtest -m gssapi -u %l -p %p %s")
+(defcustom imap-gssapi-program (list
+ (concat "gsasl --client --connect %s:%p "
+ "--imap --application-data "
+ "--mechanism GSSAPI "
+ "--authentication-id %l")
+ "imtest -m gssapi -u %l -p %p %s")
"List of strings containing commands for GSSAPI (krb5) authentication.
%s is replaced with server hostname, %p with port to connect to, and
%l with the value of `imap-default-user'. The program should accept
:group 'imap
:type 'string)
+(defcustom imap-read-timeout (if (string-match
+ "windows-nt\\|os/2\\|emx\\|cygwin"
+ (symbol-name system-type))
+ 1.0
+ 0.1)
+ "*How long to wait between checking for the end of output.
+Shorter values mean quicker response, but is more CPU intensive."
+ :type 'number
+ :group 'imap)
+
;; Various variables.
(defvar imap-fetch-data-hook nil
"Hooks called after receiving each FETCH response.")
-(defvar imap-streams '(gssapi kerberos4 starttls ssl network shell)
+(defvar imap-streams '(gssapi kerberos4 starttls tls ssl network shell)
"Priority of streams to consider when opening connection to server.")
(defvar imap-stream-alist
'((gssapi imap-gssapi-stream-p imap-gssapi-open)
(kerberos4 imap-kerberos4-stream-p imap-kerberos4-open)
+ (tls imap-tls-p imap-tls-open)
(ssl imap-ssl-p imap-ssl-open)
(network imap-network-p imap-network-open)
(shell imap-shell-p imap-shell-open)
(defconst imap-default-port 143)
(defconst imap-default-ssl-port 993)
+(defconst imap-default-tls-port 993)
(defconst imap-default-stream 'network)
(defconst imap-coding-system-for-read 'binary)
(defconst imap-coding-system-for-write 'binary)
(set-buffer buffer) ;; XXX "blue moon" nntp.el bug
(goto-char (point-min))
;; cyrus 1.6.x (13? < x <= 22) queries capabilities
- (or (while (looking-at "^C:")
+ (or (while (looking-at "^C:")
(forward-line))
t)
;; cyrus 1.6 imtest print "S: " before server greeting
(not (and (imap-parse-greeting)
;; success in imtest 1.6:
(re-search-forward
- "^\\(Authenticat.*\\)" nil t)
+ (concat "^\\(\\(Authenticat.*\\)\\|\\("
+ "Client authentication "
+ "finished.*\\)\\)")
+ nil t)
(setq response (match-string 1)))))
(accept-process-output process 1)
(sit-for 1))
(message "imap: Opening SSL connection with `%s'...failed" cmd)
nil)))
+(defun imap-tls-p (buffer)
+ nil)
+
+(defun imap-tls-open (name buffer server port)
+ (let* ((port (or port imap-default-tls-port))
+ (coding-system-for-read imap-coding-system-for-read)
+ (coding-system-for-write imap-coding-system-for-write)
+ (process (open-tls-stream name buffer server port)))
+ (when process
+ (while (and (memq (process-status process) '(open run))
+ (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+ (goto-char (point-max))
+ (forward-line -1)
+ (not (imap-parse-greeting)))
+ (accept-process-output process 1)
+ (sit-for 1))
+ (and imap-log
+ (with-current-buffer (get-buffer-create imap-log-buffer)
+ (imap-disable-multibyte)
+ (buffer-disable-undo)
+ (goto-char (point-max))
+ (insert-buffer-substring buffer)))
+ (when (memq (process-status process) '(open run))
+ process))))
+
(defun imap-network-p (buffer)
t)
(unless (< len 10)
(setq imap-have-messaged t)
(message "imap read: %dk" len))
- (accept-process-output imap-process 1)))
+ (accept-process-output imap-process
+ (truncate imap-read-timeout)
+ (truncate (* (- imap-read-timeout
+ (truncate imap-read-timeout))
+ 1000)))))
(when imap-have-messaged
(message ""))
(and (memq (process-status imap-process) '(open run))
create-image display-graphic-p
display-time-event-handler find-image image-size
image-type-available-p insert-image
- make-mode-line-mouse-map make-temp-file propertize
- put-image replace-regexp-in-string rmail-msg-is-pruned
- rmail-msg-restore-non-pruned-header sort-coding-systems
- spam-BBDB-register-routine spam-enter-ham-BBDB
- tool-bar-add-item tool-bar-add-item-from-menu
- tool-bar-local-item-from-menu url-http-file-exists-p
- vcard-pretty-print w32-focus-frame
+ make-mode-line-mouse-map make-temp-file open-ssl-stream
+ propertize put-image replace-regexp-in-string
+ rmail-msg-is-pruned rmail-msg-restore-non-pruned-header
+ sort-coding-systems spam-BBDB-register-routine
+ spam-enter-ham-BBDB tool-bar-add-item
+ tool-bar-add-item-from-menu tool-bar-local-item-from-menu
+ url-http-file-exists-p vcard-pretty-print w32-focus-frame
w3m-charset-to-coding-system x-focus-frame))
(maybe-bind '(filladapt-mode
- mc-pgp-always-sign rmail-enable-mime-composing
+ mc-pgp-always-sign mm-w3m-mode-map rmail-enable-mime-composing
rmail-insert-mime-forwarded-message-function
w3m-cid-retrieve-function-alist w3m-current-buffer
- w3m-meta-content-type-charset-regexp w3m-minor-mode-map))
+ w3m-display-inline-images w3m-meta-content-type-charset-regexp
+ w3m-minor-mode-map))
(if (featurep 'xemacs)
(progn
buffer-display-table buffer-file-coding-system
current-language-environment
default-enable-multibyte-characters
- enable-multibyte-characters language-info-alist
- mark-active mouse-selection-click-count
+ enable-multibyte-characters gnus-agent-expire-current-dirs
+ language-info-alist mark-active mouse-selection-click-count
mouse-selection-click-count-buffer pgg-parse-crc24
- temporary-file-directory transient-mark-mode
- mm-w3m-mode-map)))
+ temporary-file-directory transient-mark-mode)))
(maybe-fbind '(bbdb-complete-name
delete-annotation device-connection dfw-device
events-to-keys font-lock-set-defaults frame-device
w3-prepare-buffer w3-region w3m-region window-pixel-height
window-pixel-width))
(maybe-bind '(help-echo-owns-message
- mail-mode-hook url-package-name url-package-version
+ mail-mode-hook
+ url-current-object url-package-name url-package-version
w3-meta-charset-content-type-regexp
- w3-meta-content-type-charset-regexp mm-w3m-mode-map)))
+ w3-meta-content-type-charset-regexp)))
(defun nnkiboze-score-file (a)
)
+(defun split-line (&optional arg)
+ )
+
(provide 'lpath)
:link '(custom-manual "(message)News Headers")
:type 'string)
+(defcustom message-use-idna (and (condition-case nil (require 'idna)
+ (file-error))
+ (fboundp 'coding-system-p)
+ (coding-system-p 'utf-8)
+ 'ask)
+ "Whether to encode non-ASCII in domain names into ASCII according to IDNA."
+ :group 'message-headers
+ :type '(choice (const :tag "Ask" ask)
+ (const :tag "Never" nil)
+ (const :tag "Always" t)))
+
;;; Internal variables.
(defvar message-sending-message "Sending...")
(define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature)
(define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
;;(define-key message-mode-map "\M-q" 'message-fill-paragraph)
+ (define-key message-mode-map [remap split-line] 'message-split-line)
(define-key message-mode-map "\C-c\C-a" 'mml-attach-file)
["Reduce To: to Cc:" message-reduce-to-to-cc t]
"----"
["Sort Headers" message-sort-headers t]
+ ["Encode non-ASCII domain names" message-idna-to-ascii-rhs t]
["Goto Body" message-goto-body t]
["Goto Signature" message-goto-signature t]))
;; Check "Shoot me".
(message-check 'shoot
(if (re-search-forward
- "Message-ID.*.i-did-not-set--mail-host-address--so-shoot-me" nil t)
+ "Message-ID.*.i-did-not-set--mail-host-address--so-tickle-me" nil t)
(y-or-n-p "You appear to have a misconfigured system. Really post? ")
t))
;; Check for Approved.
(date (mail-header-date message-reply-headers))
(msg-id (mail-header-message-id message-reply-headers)))
(when from
- (let ((stop-pos
- (string-match " *at \\| *@ \\| *(\\| *<" from)))
+ (let ((name (mail-extract-address-components from)))
(concat msg-id (if msg-id " (")
- (if (and stop-pos
- (not (zerop stop-pos)))
- (substring from 0 stop-pos) from)
+ (or (car name)
+ (nth 1 name))
"'s message of \""
(if (or (not date) (string= date ""))
"(unknown date)" date)
list
msg-recipients))))))
+(defun message-idna-inside-rhs-p ()
+ "Return t iff point is inside a RHS (heuristically).
+Only works properly if header contains mailbox-list or address-list.
+I.e., calling it on a Subject: header is useless."
+ (save-restriction
+ (narrow-to-region (save-excursion (or (re-search-backward "^[^ \t]" nil t)
+ (point-min)))
+ (save-excursion (or (re-search-forward "^[^ \t]" nil t)
+ (point-max))))
+ (if (re-search-backward "[\\\n\r\t ]"
+ (save-excursion (search-backward "@" nil t)) t)
+ ;; whitespace between @ and point
+ nil
+ (let ((dquote 1) (paren 1))
+ (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote))
+ (incf dquote))
+ (while (save-excursion (re-search-backward "[^\\]\(" nil t paren))
+ (incf paren))
+ (and (= (% dquote 2) 1) (= (% paren 2) 1))))))
+
+(autoload 'idna-to-ascii "idna")
+
+(defun message-idna-to-ascii-rhs-1 (header)
+ "Interactively potentially IDNA encode domain names in HEADER."
+ (let (rhs ace start startpos endpos ovl)
+ (goto-char (point-min))
+ (while (re-search-forward (concat "^" header) nil t)
+ (while (re-search-forward "@\\([^ \t\r\n>]+\\)"
+ (or (save-excursion
+ (re-search-forward "^[^ \t]" nil t))
+ (point-max))
+ t)
+ (setq rhs (match-string-no-properties 1)
+ startpos (match-beginning 1)
+ endpos (match-end 1))
+ (when (save-match-data
+ (and (message-idna-inside-rhs-p)
+ (setq ace (idna-to-ascii rhs))
+ (not (string= rhs ace))
+ (if (eq message-use-idna 'ask)
+ (unwind-protect
+ (progn
+ (setq ovl (message-make-overlay startpos
+ endpos))
+ (message-overlay-put ovl 'face 'highlight)
+ (y-or-n-p
+ (format "Replace with `%s'? " ace)))
+ (message "")
+ (message-delete-overlay ovl))
+ message-use-idna)))
+ (replace-match (concat "@" ace)))))))
+
+(defun message-idna-to-ascii-rhs ()
+ "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
+See `message-idna-encode'."
+ (interactive)
+ (when message-use-idna
+ (save-excursion
+ (save-restriction
+ (message-narrow-to-head)
+ (message-idna-to-ascii-rhs-1 "From")
+ (message-idna-to-ascii-rhs-1 "To")
+ (message-idna-to-ascii-rhs-1 "Cc")))))
+
(defun message-generate-headers (headers)
"Prepare article HEADERS.
Headers already prepared in the buffer are not modified."
(beginning-of-line))
(when (or (message-news-p)
(string-match "@.+\\.." secure-sender))
- (insert "Sender: " secure-sender "\n")))))))
+ (insert "Sender: " secure-sender "\n"))))
+ ;; Check for IDNA
+ (message-idna-to-ascii-rhs))))
(defun message-insert-courtesy-copy ()
"Insert a courtesy message in mail copies of combined messages."
(widen)
(forward-line 1)))
+(defun message-split-line ()
+ "Split current line, moving portion beyond point vertically down.
+If the current line has `message-yank-prefix', insert it on the new line."
+ (interactive "*")
+ (condition-case nil
+ (split-line message-yank-prefix) ;; Emacs 21.3.50+ supports arg.
+ (error
+ (split-line))))
+
+
(defun message-fill-header (header value)
(let ((begin (point))
(fill-column 78)
(delete-char -2))))))
(defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
+(defalias 'message-make-overlay 'make-overlay)
+(defalias 'message-delete-overlay 'delete-overlay)
+(defalias 'message-overlay-put 'overlay-put)
;; Support for toolbar
(eval-when-compile
'region-exists-p)
(when (>= emacs-major-version 20)
(defalias 'message-make-caesar-translation-table
- 'message-xmas-make-caesar-translation-table)))
+ 'message-xmas-make-caesar-translation-table))
+ (defalias 'message-make-overlay 'make-extent)
+ (defalias 'message-delete-overlay 'delete-extent)
+ (defalias 'message-overlay-put 'set-extent-property))
(message-xmas-redefine)
"Decode region between START and END with CODING-SYSTEM.
If CODING-SYSTEM is not a valid coding system for the text, let Emacs
decide which coding system to use."
- (let* ((decoded (mm-decode-coding-string (buffer-substring start end)
- coding-system))
- (charsets (find-charset-string decoded)))
- (if (or (memq 'eight-bit-control charsets)
- (memq 'eight-bit-graphic charsets))
- (mm-decode-coding-region start end 'undecided)
- (delete-region start end)
- (insert decoded))))
+ (let* ((orig (buffer-substring start end))
+ charsets)
+ (save-restriction
+ (narrow-to-region start end)
+ (mm-decode-coding-region (point-min) (point-max) coding-system)
+ (setq charsets (find-charset-region (point-min) (point-max)))
+ (when (or (memq 'eight-bit-control charsets)
+ (memq 'eight-bit-graphic charsets))
+ (delete-region (point-min) (point-max))
+ (insert orig)
+ (mm-decode-coding-region (point-min) (point-max) 'undecided)))))
(defun mm-decode-string (string charset)
"Decode STRING with CHARSET."
(list url (buffer-size)))
(mm-url-load-url)
(let ((name buffer-file-name)
+ (url-request-extra-headers (list (cons "Connection" "Close")))
(url-package-name (or mm-url-package-name
url-package-name))
(url-package-version (or mm-url-package-version
- url-package-version)))
- (prog1
- (url-insert-file-contents url)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "\r 1000\r ?" nil t)
- (replace-match "")))
- (setq buffer-file-name name)))))
+ url-package-version))
+ result)
+ (setq result (url-insert-file-contents url))
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "\r 1000\r ?" nil t)
+ (replace-match "")))
+ (setq buffer-file-name name)
+ (if (and (fboundp 'url-generic-parse-url)
+ (listp result))
+ (setq url-current-object (url-generic-parse-url
+ (car result))))
+ result)))
(defun mm-url-insert-file-contents-external (url)
(let (program args)
(defun mm-mule-charset-to-mime-charset (charset)
"Return the MIME charset corresponding to the given Mule CHARSET."
- (if (fboundp 'find-coding-systems-for-charsets)
+ (if (and (fboundp 'find-coding-systems-for-charsets)
+ (fboundp 'sort-coding-systems))
(let (mime)
(dolist (cs (sort-coding-systems
(copy-sequence
mm-links-remove-leading-blank
"links" "-dump" file)
(lynx mm-inline-render-with-stdin nil
- "lynx" "-dump" "-force_html" "-stdin")
+ "lynx" "-dump" "-force_html" "-stdin" "-nolist")
(html2text mm-inline-render-with-function html2text))
"The attributes of renderer types for text/html.")
mm-links-remove-leading-blank
"links" "-dump" file)
(lynx mm-inline-wash-with-stdin nil
- "lynx" "-dump" "-force_html" "-stdin")
+ "lynx" "-dump" "-force_html" "-stdin" "-nolist")
(html2text html2text))
"The attributes of washer types for text/html.")
(unless (assq 'gnus-article-mode w3m-cid-retrieve-function-alist)
(push (cons 'gnus-article-mode 'mm-w3m-cid-retrieve)
w3m-cid-retrieve-function-alist))
- (setq mm-w3m-setup t)))
+ (setq mm-w3m-setup t))
+ (setq w3m-display-inline-images mm-inline-text-html-with-images))
(defun mm-w3m-cid-retrieve (url &rest args)
"Insert a content pointed by URL if it has the cid: scheme."
(delete-region (point-min) (point-max))
(insert (mm-decode-string text charset)))
(let ((w3m-safe-url-regexp mm-w3m-safe-url-regexp)
- (w3m-display-inline-images mm-inline-text-html-with-images)
w3m-force-redisplay)
(w3m-region (point-min) (point-max)))
(when mm-inline-text-html-with-w3m-keymap
`((mmdf
(article-begin . "^\^A\^A\^A\^A\n")
(body-end . "^\^A\^A\^A\^A\n"))
+ (mime-parts
+ (generate-head-function . nndoc-generate-mime-parts-head)
+ (article-transform-function . nndoc-transform-mime-parts))
(nsmail
(article-begin . "^From - "))
(news
(body-end . "")
(file-end . "")
(subtype digest guess))
- (mime-parts
- (generate-head-function . nndoc-generate-mime-parts-head)
- (article-transform-function . nndoc-transform-mime-parts))
(standard-digest
(first-article . ,(concat "^" (make-string 70 ?-) "\n *\n+"))
(article-begin . ,(concat "^\n" (make-string 30 ?-) "\n *\n+"))
(defvar nnheader-head-chop-length 2048
"*Length of each read operation when trying to fetch HEAD headers.")
+(defvar nnheader-read-timeout
+ (if (string-match "windows-nt\\|os/2\\|emx\\|cygwin"
+ (symbol-name system-type))
+ 1.0
+ 0.1)
+ "How long nntp should wait between checking for the end of output.
+Shorter values mean quicker response, but is more CPU intensive.")
+
(defvar nnheader-file-name-translation-alist
(let ((case-fold-search t))
(cond
(defalias 'nnheader-cancel-function-timers 'cancel-function-timers)
(defalias 'nnheader-string-as-multibyte 'string-as-multibyte)
+(defun nnheader-accept-process-output (process)
+ (accept-process-output
+ process
+ (truncate nnheader-read-timeout)
+ (truncate (* (- nnheader-read-timeout
+ (truncate nnheader-read-timeout))
+ 1000))))
+
(when (featurep 'xemacs)
(require 'nnheaderxm))
(defvoo nnimap-server-port nil
"Port number on physical IMAP server.
-If nil, defaults to 993 for SSL connections and 143 otherwise.")
+If nil, defaults to 993 for TLS/SSL connections and 143 otherwise.")
;; Splitting variables
Change this if
-1) you want to connect with SSL. The SSL integration with IMAP is
- brain-dead so you'll have to tell it specifically.
+1) you want to connect with TLS/SSL. The TLS/SSL integration
+ with IMAP is suboptimal so you'll have to tell it
+ specifically.
2) your server is more capable than your environment -- i.e. your
server accept Kerberos login's but you haven't installed the
`imtest' program or your machine isn't configured for Kerberos.
-Possible choices: kerberos4, ssl, network")
+Possible choices: gssapi, kerberos4, starttls, tls, ssl, network, shell.
+See also `imap-streams' and `imap-stream-alist'.")
(defvoo nnimap-authenticator nil
"How nnimap authenticate itself to the server.
installed the `imtest' program or your machine isn't configured for
Kerberos.
-Possible choices: kerberos4, cram-md5, login, anonymous.")
+Possible choices: gssapi, kerberos4, digest-md5, cram-md5, login, anonymous.
+See also `imap-authenticators' and `imap-authenticator-alist'")
(defvoo nnimap-directory (nnheader-concat gnus-directory "overview/")
"Directory to keep NOV cache files for nnimap groups.
start
(if (search-forward "\n\n" nil t)
(1- (point))
- ;; This will never happen, but just to be on the safe side --
- ;; if there is no head-body delimiter, we search a bit manually.
+ ;; This will never happen, but just to be on the safe side --
+ ;; if there is no head-body delimiter, we search a bit manually.
(while (and (looking-at "From \\|[^ \t]+:")
(not (eobp)))
(forward-line 1))
(if (search-forward "\n\n" nil t)
(1- (point))
;; This will never happen, but just to be on the safe side --
- ;; if there is no head-body delimiter, we search a bit manually.
+ ;; if there is no head-body delimiter, we search a bit manually.
(while (and (looking-at "From \\|[^ \t]+:")
(not (eobp)))
(forward-line 1))
nil t)
(delete-region (match-beginning 2) (match-end 0))
(beginning-of-line))
- (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" nil t)
+ (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +"
+ nil t)
(delete-region (match-beginning 1) (match-end 1))
(beginning-of-line)))))
;; copying, restoring, etc.
;;
;; Todo:
-;; * Replace create-directory with target-prefix, so the maildirs can be in
-;; the same directory as the symlinks, starting with, e.g., ".".
;; * Add a hook for when moving messages from new/ to cur/, to support
;; nnmail's duplicate detection.
-;; * Allow each mark directory in a group to have its own inode for mark
-;; files, to accommodate AFS.
;; * Improve generated Xrefs, so crossposts are detectable.
;; * Improve code readability.
; ("Mark Mod Time Hash")
(defstruct nnmaildir--srv
- (address nil :type string) ;; server address string
- (method nil :type list) ;; (nnmaildir "address" ...)
- (prefix nil :type string) ;; "nnmaildir+address:"
- (dir nil :type string) ;; "/expanded/path/to/server/dir/"
- (ls nil :type function) ;; directory-files function
- (groups nil :type vector) ;; obarray mapping group names->groups
- (curgrp nil :type nnmaildir--grp) ;; current group, or nil
- (error nil :type string) ;; last error message, or nil
- (mtime nil :type list) ;; modtime of dir
- (gnm nil) ;; flag: split from mail-sources?
- (create-dir nil :type string)) ;; group creation directory
+ (address nil :type string) ;; server address string
+ (method nil :type list) ;; (nnmaildir "address" ...)
+ (prefix nil :type string) ;; "nnmaildir+address:"
+ (dir nil :type string) ;; "/expanded/path/to/server/dir/"
+ (ls nil :type function) ;; directory-files function
+ (groups nil :type vector) ;; obarray mapping group name->group
+ (curgrp nil :type nnmaildir--grp) ;; current group, or nil
+ (error nil :type string) ;; last error message, or nil
+ (mtime nil :type list) ;; modtime of dir
+ (gnm nil) ;; flag: split from mail-sources?
+ (target-prefix nil :type string)) ;; symlink target prefix
(defun nnmaildir--expired-article (group article)
(setf (nnmaildir--art-nov article) nil)
(or (file-exists-p (file-name-as-directory dir))
(make-directory-internal (directory-file-name dir))))
(defun nnmaildir--delete-dir-files (dir ls)
- (mapcar 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort))
- (delete-directory dir))
+ (when (file-attributes dir)
+ (mapcar 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort))
+ (delete-directory dir)))
(defun nnmaildir--group-maxnum (server group)
(if (zerop (nnmaildir--grp-count group)) 0
(defun nnmaildir--up2-1 (n)
(if (zerop n) 1 (1- (lsh 1 (1+ (logb n))))))
+(defun nnmaildir--system-name ()
+ (gnus-replace-in-string
+ (gnus-replace-in-string
+ (gnus-replace-in-string
+ (system-name)
+ "\\\\" "\\134" 'literal)
+ "/" "\\057" 'literal)
+ ":" "\\072" 'literal))
+
(defun nnmaildir-request-type (group &optional article)
'mail)
(car x)
(setf (nnmaildir--srv-gnm server) t)
(require 'nnmail))
- (setq x (assq 'create-directory defs))
- (when x
- (setq x (cadr x)
- x (eval x))
- (setf (nnmaildir--srv-create-dir server) x))
+ (setq x (assq 'target-prefix defs))
+ (if x
+ (progn
+ (setq x (cadr x)
+ x (eval x))
+ (setf (nnmaildir--srv-target-prefix server) x))
+ (setq x (assq 'create-directory defs))
+ (if x
+ (progn
+ (setq x (cadr x)
+ x (eval x)
+ x (file-name-as-directory x))
+ (setf (nnmaildir--srv-target-prefix server) x))
+ (setf (nnmaildir--srv-target-prefix server) "")))
(setf (nnmaildir--srv-groups server) (make-vector size 0))
(setq nnmaildir--cur-server server)
t)))
(nnmaildir-get-new-mail t)
(nnmaildir-group-alist nil)
(nnmaildir-active-file nil)
- x srv-ls srv-dir method groups group dirs grp-dir seen deactivate-mark)
+ x srv-ls srv-dir method groups target-prefix group dirs grp-dir seen
+ deactivate-mark)
(nnmaildir--prepare server nil)
(setq srv-ls (nnmaildir--srv-ls nnmaildir--cur-server)
srv-dir (nnmaildir--srv-dir nnmaildir--cur-server)
method (nnmaildir--srv-method nnmaildir--cur-server)
- groups (nnmaildir--srv-groups nnmaildir--cur-server))
+ groups (nnmaildir--srv-groups nnmaildir--cur-server)
+ target-prefix (nnmaildir--srv-target-prefix nnmaildir--cur-server))
(nnmaildir--with-work-buffer
(save-match-data
(if (stringp scan-group)
method srv-dir srv-ls))
groups))
(setq dirs (funcall srv-ls srv-dir nil "\\`[^.]" 'nosort)
+ dirs (if (zerop (length target-prefix))
+ dirs
+ (remove-if (lambda (dir)
+ (and (>= (length dir) (length target-prefix))
+ (string= (substring dir 0 (length target-prefix))
+ target-prefix)))
+ dirs))
seen (nnmaildir--up2-1 (length dirs))
seen (make-vector seen 0))
(mapcar
(defun nnmaildir-request-create-group (gname &optional server args)
(nnmaildir--prepare server nil)
(catch 'return
- (let ((create-dir (nnmaildir--srv-create-dir nnmaildir--cur-server))
+ (let ((target-prefix (nnmaildir--srv-target-prefix nnmaildir--cur-server))
srv-dir dir groups)
(when (zerop (length gname))
(setf (nnmaildir--srv-error nnmaildir--cur-server)
(concat "Group already exists: " gname))
(throw 'return nil))
(setq srv-dir (nnmaildir--srv-dir nnmaildir--cur-server))
- (if (file-name-absolute-p create-dir)
- (setq dir (expand-file-name create-dir))
+ (if (file-name-absolute-p target-prefix)
+ (setq dir (expand-file-name target-prefix))
(setq dir srv-dir
dir (file-truename dir)
- dir (concat dir create-dir)))
- (setq dir (nnmaildir--subdir (file-name-as-directory dir) gname))
+ dir (concat dir target-prefix)))
+ (setq dir (nnmaildir--subdir dir gname))
(nnmaildir--mkdir dir)
(nnmaildir--mkdir (nnmaildir--tmp dir))
(nnmaildir--mkdir (nnmaildir--new dir))
(nnmaildir--mkdir (nnmaildir--cur dir))
- (setq create-dir (file-name-as-directory create-dir))
- (make-symbolic-link (concat create-dir gname) (concat srv-dir gname))
+ (unless (string= target-prefix "")
+ (make-symbolic-link (concat target-prefix gname)
+ (concat srv-dir gname)))
(nnmaildir-request-scan 'find-new-groups))))
(defun nnmaildir-request-rename-group (gname new-name &optional server)
(defun nnmaildir-request-delete-group (gname force &optional server)
(let ((group (nnmaildir--prepare server gname))
- pgname grp-dir dir ls deactivate-mark)
+ pgname grp-dir target dir ls deactivate-mark)
(catch 'return
(unless group
(setf (nnmaildir--srv-error nnmaildir--cur-server)
(concat "No such group: " gname))
(throw 'return nil))
+ (setq gname (nnmaildir--grp-name group)
+ pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+ grp-dir (nnmaildir--srv-dir nnmaildir--cur-server)
+ target (car (file-attributes (concat grp-dir gname)))
+ grp-dir (nnmaildir--srvgrp-dir grp-dir gname))
+ (unless (or force (stringp target))
+ (setf (nnmaildir--srv-error nnmaildir--cur-server)
+ (concat "Not a symlink: " gname))
+ (throw 'return nil))
(if (eq group (nnmaildir--srv-curgrp nnmaildir--cur-server))
(setf (nnmaildir--srv-curgrp nnmaildir--cur-server) nil))
- (setq gname (nnmaildir--grp-name group)
- pgname (nnmaildir--pgname nnmaildir--cur-server gname))
(unintern gname (nnmaildir--srv-groups nnmaildir--cur-server))
- (setq grp-dir (nnmaildir--srv-dir nnmaildir--cur-server)
- grp-dir (nnmaildir--srvgrp-dir grp-dir gname))
- (if (not force) (setq grp-dir (directory-file-name grp-dir))
+ (if (not force)
+ (progn
+ (setq grp-dir (directory-file-name grp-dir))
+ (nnmaildir--unlink grp-dir))
(setq ls (nnmaildir--group-ls nnmaildir--cur-server pgname))
(if (nnmaildir--param pgname 'read-only)
(progn (delete-directory (nnmaildir--tmp grp-dir))
(nnmaildir--unlink (concat dir "markfile{new}"))
(delete-directory (nnmaildir--marks-dir dir))
(delete-directory dir)
- (setq grp-dir (directory-file-name grp-dir)
- dir (car (file-attributes grp-dir)))
- (unless (eq (aref "/" 0) (aref dir 0))
- (setq dir (concat (file-truename
- (nnmaildir--srv-dir nnmaildir--cur-server))
- dir)))
- (delete-directory dir))
- (nnmaildir--unlink grp-dir)
+ (if (not (stringp target))
+ (delete-directory grp-dir)
+ (setq grp-dir (directory-file-name grp-dir)
+ dir target)
+ (unless (eq (aref "/" 0) (aref dir 0))
+ (setq dir (concat (file-truename
+ (nnmaildir--srv-dir nnmaildir--cur-server))
+ dir)))
+ (delete-directory dir)
+ (nnmaildir--unlink grp-dir)))
t)))
(defun nnmaildir-retrieve-headers (articles &optional gname server fetch-old)
(setq file (concat file "M" (number-to-string (caddr time)))))
(setq file (concat file nnmaildir--delivery-pid)
file (concat file "Q" (number-to-string nnmaildir--delivery-count))
- file (concat file "." (system-name)) ;;;; FIXME: encode / and :
+ file (concat file "." (nnmaildir--system-name))
tmpfile (concat (nnmaildir--tmp dir) file)
curfile (concat (nnmaildir--cur dir) file ":2,"))
(when (file-exists-p tmpfile)
(file-coding-system-alist nil)
del-mark del-action add-action set-action marksdir markfile nlist
ranges begin end article all-marks todo-marks did-marks mdir mfile
- pgname ls markfilenew deactivate-mark)
+ pgname ls permarkfile deactivate-mark)
(setq del-mark
(lambda (mark)
(setq mfile (nnmaildir--subdir marksdir (symbol-name mark))
(mapcar
(lambda (mark)
(setq mdir (nnmaildir--subdir marksdir (symbol-name mark))
+ permarkfile (concat mdir ":")
mfile (concat mdir (nnmaildir--art-prefix article)))
(unless (memq mark did-marks)
+ (setq did-marks (cons mark did-marks))
(nnmaildir--mkdir mdir)
- (setq did-marks (cons mark did-marks)))
+ (unless (file-attributes permarkfile)
+ (condition-case nil
+ (add-name-to-file markfile permarkfile)
+ (file-error
+ ;; AFS can't make hard links in separate directories
+ (write-region "" nil permarkfile nil 'no-message)))))
(unless (file-exists-p mfile)
- (condition-case nil
- (add-name-to-file markfile mfile)
- (file-error
- (unless (file-exists-p mfile)
- ;; too many links, maybe
- (write-region "" nil markfilenew nil 'no-message)
- (add-name-to-file markfilenew mfile
- 'ok-if-already-exists)
- (rename-file markfilenew markfile 'replace))))))
+ (add-name-to-file permarkfile mfile)))
todo-marks))
set-action (lambda (article)
(funcall add-action)
marksdir (nnmaildir--srvgrp-dir marksdir gname)
marksdir (nnmaildir--nndir marksdir)
markfile (concat marksdir "markfile")
- markfilenew (concat markfile "{new}")
marksdir (nnmaildir--marks-dir marksdir)
gname (nnmaildir--grp-name group)
pgname (nnmaildir--pgname nnmaildir--cur-server gname)
dir (file-name-as-directory (car dir)))
(mapcar
(lambda (file)
- (unless (intern-soft file flist)
+ (unless (or (intern-soft file flist) (string= file ":"))
(setq file (concat dir file))
(delete-file file)))
files))
(defconst nnrss-version "nnrss 1.0")
-(defvar nnrss-group-alist
- '(("MacWeek"
- "http://macweek.zdnet.com/macweek.xml"
- "The Macintosh news authority.")
- ("Linux.Weekly.News"
- "http://lwn.net/headlines/rss")
- ("Motley.Fool"
- "http://www.fool.com/About/headlines/rss_headlines.asp")
- ("NewsForge.rdf"
- "http://www.newsforge.com/newsforge.rdf")
- ("Slashdot"
- "http://www.slashdot.com/slashdot.rdf")
- ("CNN"
- "http://www.cnn.com/cnn.rss"
- "The world's news leader.")
- ("FreshMeat"
- "http://freshmeat.net/backend/fm-releases.rdf"
- "The one-stop-shop for all your Linux software needs.")
- ("The.Guardian.newspaper"
- "http://www.guardianunlimited.co.uk/rss/1,,,00.xml"
- "Intelligent news and comment throughout the day from The Guardian newspaper.")
- ("MonkeyFist.rdf"
- "http://monkeyfist.com/rdf.php3"
- "News and opinion on politics, technology, and eclectic miscellany.")
- ("NewsForge"
- "http://www.newsforge.com/newsforge.rss")
- ("Reuters.Health"
- "http://www.reutershealth.com/eline.rss"
- "Consumer-oriented health-related news stories.")
- ("Salon"
- "http://www.salon.com/feed/RDF/salon_use.rdf")
- ("Wired"
- "http://www.wired.com/news_drop/netcenter/netcenter.rdf")
- ("ITN"
- "http://www.itn.co.uk/itn.rdf")
- ("Meerkat"
- "http://www.oreillynet.com/meerkat/?_fl=rss10"
- "An Open Wire Service")
- ("MonkeyFist"
- "http://monkeyfist.com/rss1.php3"
- "News and opinion on politics, technology, and eclectic miscellany.")
- ("Reuters.Health.rdf"
- "http://www.reutershealth.com/eline.rdf"
- "Consumer-oriented health-related news stories.")
- ("Aaronland" "http://aaronland.net/xml/abhb.rdf" "A boy and his basement.")
- ("Art of the Mix" "http://www.artofthemix.org/xml/rss.asp" "A website devoted to the art of making mixed tapes and cds.")
- ("Dave Beckett's RDF Resource Guide" "http://www.ilrt.bristol.ac.uk/discovery/rdf/resources/rss.rdf" "A comprehensive guide to resources about RDF.")
- ("David Chess" "http://www.davidchess.com/words/log.rss" "Mostly-daily musings on philosophy, children, culture, technology, the emergence of life from matter, chocolate, Nomic, and all that sort of thing.")
- ("Figby Articles" "http://www.figby.com/index-rss.php" "A weblog with daily stories about technology, books and publishing, privacy, science, and occasional humor.")
- ("Figby Quickies" "http://www.figby.com/quickies-rss.php" "Quick commented links to other sites from Figby.com.")
- ("Flutterby!" "http://www.flutterby.com/main.rdf" "News and views from Dan Lyke.")
- ("Groovelog"
- "http://groovelog.agora.co.uk/groove+log/groovelog.nsf/today.rss.xml"
- "The open-access groove users' weblog.")
- ("Hit or Miss" "http://hit-or-miss.org/rss/" "Daily weblog and journal.")
- ("Larkfarm News" "http://www.larkfarm.com/Larkfarm.rdf" "Mike Gunderloy's web site.")
- ("Latest RFCs" "http://x42.com/rss/rfc.rss")
- ("Linux Today" "http://linuxtoday.com/backend/biglt.rss")
- ("Linux Today.rdf" "http://linuxtoday.com/backend/my-netscape10.rdf")
- ("More Like This WebLog" "http://www.whump.com/moreLikeThis/RSS" "Because the more you know, the more jokes you get.")
- ("Motivational Quotes of the Day" "http://www.quotationspage.com/data/mqotd.rss" "Four motivational quotations each day from the Quotations Page.")
- ("Network World Fusion NetFlash" "http://www.nwfusion.com/netflash.rss" "Daily breaking news about networking products, technologies and services.")
- ("News Is Free" "http://www.newsisfree.com/news.rdf.php3")
- ("O'Reilly Network Articles" "http://www.oreillynet.com/cs/rss/query/q/260?x-ver=1.0")
- ("Quotes of the Day" "http://www.quotationspage.com/data/qotd.rss" "Four humorous quotations each day from the Quotations Page.")
- ("RDF Interest Group" "http://ilrt.org/discovery/rdf-dev/roads/cgi-bin/desire/ig2rss?list=www-rdf-interest" "An experimental channel scraped from the RDF Interest Group mail archives.")
- ("RDF Logic List" "http://ilrt.org/discovery/rdf-dev/roads/cgi-bin/desire/ig2rss?list=www-rdf-logic" "An experimental channel scraped from the RDF Logic mail archives.")
- ("RSS Info" "http://www.blogspace.com/rss/rss10" "News and information on the RSS format")
- ("Semantic Web List"
- "http://ilrt.org/discovery/rdf-dev/roads/cgi-bin/desire/ig2rss?list=semantic-web"
- "An experimental channel scraped from the W3C's Semantic Web mail archives.")
- ("W3C"
- "http://www.w3.org/2000/08/w3c-synd/home.rss"
- "The latest news at the World Wide Web Consortium.")
- ("|fr| XMLfr" "http://xmlfr.org/actualites/general.rss10"
- "French speaking portal site dedicated to XML.")
- ("XMLhack" "http://xmlhack.com/rss10.php"
- "Developer news from the XML community.")
- ("The Register"
- "http://www.theregister.co.uk/tonys/slashdot.rdf"
- "The Register -- Biting the hand that feeds IT.")
- ("|de| Heise-Ticker"
- "http://www.heise.de/newsticker/heise.rdf"
- "German news ticker about technology.")
- ("|de| Telepolis News"
- "http://www.heise.de/tp/news.rdf"
- "German background news about technology.")
- ("Kuro5hin"
- "http://www.kuro5hin.org/backend.rdf"
- "Technology and culture, from the trenches.")
- ("Jabber Software Foundation News"
- "http://www.jabber.org/news/rss.xml"
- "News and announcements from the Jabber Software Foundation.")
- ("MacRumors"
- "http://www.macrumors.com/macrumors.xml"
- "The mac news you care about.")
- ("Mac OS X Hints"
- "http://www.macosxhints.com/backend/geeklog.rdf"
- "Mac OS X Hits.")
- )
+(defvar nnrss-group-alist '()
"List of RSS addresses.")
(defvar nnrss-use-local nil)
(with-current-buffer nntp-server-buffer
(erase-buffer)
(goto-char (point-min))
+ (insert "Mime-Version: 1.0\nContent-Type: text/html\n")
(if group
(insert "Newsgroups: " group "\n"))
(if (nth 3 e)
(let ((point (point)))
(insert (nnrss-string-as-multibyte (nth 6 e)))
(goto-char point)
- (while (search-forward "\n" nil t)
- (delete-char -1))
+ (while (re-search-forward "\n" nil t)
+ (replace-match " "))
(goto-char (point-max))
(insert "\n\n")
(fill-region point (point))))
(if (nth 2 e)
- (insert (nth 2 e) "\n"))
+ (insert "<p><a href='" (nth 2 e) "'>link</a></p>\n"))
(if nnrss-content-function
(funcall nnrss-content-function e group article)))))
(cond
(err
(nnheader-report 'nnrss err))
((not e)
- (nnheader-report 'nnrss "No such id: %d" article))
+ (nnheader-report 'nnrss "no such id: %d" article))
(t
- (nnheader-report 'nnrss "Article %s retrieved" (car e))
- ;; We return the article number.
+ (nnheader-report 'nnrss "article %s retrieved" (car e))
+ ;; we return the article number.
(cons nnrss-group (car e))))))
(deffoo nnrss-request-list (&optional server)
(nnoo-define-skeleton nnrss)
;;; Internal functions
+(eval-when-compile (defun xml-rpc-method-call (&rest args)))
+(defun nnrss-fetch (url &optional local)
+ "Fetch the url and put it in a the expected lisp structure."
+ (with-temp-buffer
+ ;some CVS versions of url.el need this to close the connection quickly
+ (let* (xmlform htmlform)
+ ;; bit o' work necessary for w3 pre-cvs and post-cvs
+ (if local
+ (let ((coding-system-for-read 'binary))
+ (insert-file-contents url))
+ (mm-url-insert url))
+
+;; Because xml-parse-region can't deal with anything that isn't
+;; xml and w3-parse-buffer can't deal with some xml, we have to
+;; parse with xml-parse-region first and, if that fails, parse
+;; with w3-parse-buffer. Yuck. Eventually, someone should find out
+;; why w3-parse-buffer fails to parse some well-formed xml and
+;; fix it.
+
+ (condition-case err
+ (setq xmlform (xml-parse-region (point-min) (point-max)))
+ (error (if (fboundp 'w3-parse-buffer)
+ (setq htmlform (caddar (w3-parse-buffer
+ (current-buffer))))
+ (message "nnrss: Not valid XML and w3 parse not available (%s)"
+ url))))
+ (if htmlform
+ htmlform
+ xmlform))))
(defun nnrss-possibly-change-group (&optional group server)
(when (and server
(defvar nnrss-extra-categories '(nnrss-snarf-moreover-categories))
(defun nnrss-generate-active ()
- (if (y-or-n-p "Fetch extra categories? ")
+ (if (y-or-n-p "fetch extra categories? ")
(dolist (func nnrss-extra-categories)
(funcall func)))
(save-excursion
(unless (assoc (car elem) nnrss-group-alist)
(insert (prin1-to-string (car elem)) " 0 1 y\n")))))
-;;; Data functions
+;;; data functions
(defun nnrss-read-server-data (server)
(setq nnrss-server-data nil)
(mm-url-insert url)))
(defun nnrss-decode-entities-unibyte-string (string)
- (mm-with-unibyte-buffer
- (insert string)
- (mm-url-decode-entities-nbsp)
- (buffer-string)))
+ (if string
+ (mm-with-unibyte-buffer
+ (insert string)
+ (mm-url-decode-entities-nbsp)
+ (buffer-string))))
(defalias 'nnrss-insert 'nnrss-insert-w3)
;;; Snarf functions
(defun nnrss-check-group (group server)
- (let (file xml subject url extra changed author date)
- (condition-case err
- (mm-with-unibyte-buffer
- (if (and nnrss-use-local
- (file-exists-p (setq file (expand-file-name
- (nnrss-translate-file-chars
- (concat group ".xml"))
- nnrss-directory))))
- (insert-file-contents file)
- (setq url (or (nth 2 (assoc group nnrss-server-data))
- (second (assoc group nnrss-group-alist))))
- (unless url
- (setq url
- (read-string (format "RSS url of %s: " group "http://")))
- (let ((pair (assoc group nnrss-server-data)))
- (if pair
- (setcdr (cdr pair) (list url))
- (push (list group nnrss-group-max url) nnrss-server-data)))
- (setq changed t))
- (nnrss-insert url))
- (goto-char (point-min))
- (while (re-search-forward "\r\n?" nil t)
- (replace-match "\n"))
- (goto-char (point-min))
- (if (re-search-forward "<rdf\\|<rss" nil t)
- (goto-char (match-beginning 0)))
- (setq xml (xml-parse-region (point) (point-max))))
- (error
- (nnheader-message 1 "Error in group %s: %s" group (cadr err))))
- (while (and xml (not (assq 'item xml)))
- (setq xml (cddar xml))
- (while (not (listp (car xml)))
- (setq xml (cdr xml))))
- (dolist (item (nreverse xml))
+ (let (file xml subject url extra changed author date rss-ns rdf-ns content-ns dc-ns)
+ (if (and nnrss-use-local
+ (file-exists-p (setq file (expand-file-name
+ (nnrss-translate-file-chars
+ (concat group ".xml"))
+ nnrss-directory))))
+ (nnrss-fetch file t)
+ (setq url (or (nth 2 (assoc group nnrss-server-data))
+ (second (assoc group nnrss-group-alist))))
+ (unless url
+ (setq url
+ (nnrss-discover-feed (read-string (format "URL to search for %s: " group) "http://")))
+ (let ((pair (assoc group nnrss-server-data)))
+ (if pair
+ (setcdr (cdr pair) (list url))
+ (push (list group nnrss-group-max url) nnrss-server-data)))
+ (setq changed t))
+ (setq xml (nnrss-fetch url)))
+ ;; See
+ ;; http://feeds.archive.org/validator/docs/howto/declare_namespaces.html
+ ;; for more RSS namespaces.
+ (setq dc-ns (nnrss-get-namespace-prefix xml "http://purl.org/dc/elements/1.1/")
+ rdf-ns (nnrss-get-namespace-prefix xml "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+ rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/")
+ content-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/modules/content/"))
+ (dolist (item (nreverse (nnrss-find-el (intern (concat rss-ns "item")) xml)))
(when (and (listp item)
- (eq 'item (car item))
- (setq url (nnrss-node-text (assq 'link (cddr item))))
- (setq url (nnrss-decode-entities-unibyte-string url))
+ (eq (intern (concat rss-ns "item")) (car item))
+ (setq url (nnrss-decode-entities-unibyte-string
+ (nnrss-node-text rss-ns 'link (cddr item))))
(not (gnus-gethash url nnrss-group-hashtb)))
- (setq subject (nnrss-node-text (assq 'title (cddr item))))
- (setq extra (or (nnrss-node-text (assq 'description (cddr item)))
- (nnrss-node-text (assq 'dc:description (cddr item)))))
- (setq author (nnrss-node-text (assq 'dc:creator (cddr item))))
- (setq date (or (nnrss-node-text (assq 'dc:date (cddr item)))
+ (setq subject (nnrss-node-text rss-ns 'title item))
+ (setq extra (or (nnrss-node-text content-ns 'encoded item)
+ (nnrss-node-text rss-ns 'description item)))
+ (setq author (or (nnrss-node-text rss-ns 'author item)
+ (nnrss-node-text dc-ns 'creator item)))
+ (setq date (or (nnrss-node-text dc-ns 'date item)
+ (nnrss-node-text rss-ns 'pubDate item)
(message-make-date)))
(push
(list
(nnrss-insert nnrss-moreover-url)
(goto-char (point-min))
(while (re-search-forward
- "<A NAME=\"\\([^\"]+\\)\">\\|<A HREF=\"\\(http://[^\"]*moreover\\.com[^\"]+page\\?c=\\([^\"&]+\\)&o=rss\\)" nil t)
+ "<a name=\"\\([^\"]+\\)\">\\|<a href=\"\\(http://[^\"]*moreover\\.com[^\"]+page\\?c=\\([^\"&]+\\)&o=rss\\)" nil t)
(if (match-string 1)
(setq category (match-string 1))
(setq url (match-string 2)
(defun nnrss-format-string (string)
(gnus-replace-in-string (nnrss-string-as-multibyte string) " *\n *" " "))
-(defun nnrss-node-text (node)
+(defun nnrss-node-text (namespace local-name element)
+ (let* ((node (assq (intern (concat namespace (symbol-name local-name))) element))
+ (text (if (and node (listp node))
+ (nnrss-node-just-text node)
+ node))
+ (cleaned-text (if text
+ (replace-regexp-in-string
+ " *$" "" (replace-regexp-in-string
+ "^ *" "" (replace-regexp-in-string
+ "^[[:cntrl:]]+" "" text))))))
+ (if (string-equal "" cleaned-text)
+ nil
+ cleaned-text)))
+
+(defun nnrss-node-just-text (node)
(if (and node (listp node))
- (mapconcat 'nnrss-node-text (cddr node) "")
+ (mapconcat 'nnrss-node-just-text (cddr node) " ")
node))
+(defun nnrss-find-el (tag data &optional found-list)
+ "Find the all matching elements in the data. Careful with this on
+large documents!"
+ (if (listp data)
+ (mapcar (lambda (bit)
+ (if (car-safe bit)
+ (progn (if (equal tag (car bit))
+ (setq found-list
+ (append found-list
+ (list bit))))
+ (if (and (listp (car-safe (caddr bit)))
+ (not (stringp (caddr bit))))
+ (setq found-list
+ (append found-list
+ (nnrss-find-el
+ tag (caddr bit))))
+ (setq found-list
+ (append found-list
+ (nnrss-find-el
+ tag (cddr bit))))))))
+ data))
+ found-list)
+
+(defun nnrss-rsslink-p (el)
+ "Test if the element we are handed is an RSS autodiscovery link."
+ (and (eq (car-safe el) 'link)
+ (string-equal (cdr (assoc 'rel (cadr el))) "alternate")
+ (or (string-equal (cdr (assoc 'type (cadr el)))
+ "application/rss+xml")
+ (string-equal (cdr (assoc 'type (cadr el))) "text/xml"))))
+
+(defun nnrss-get-rsslinks (data)
+ "Extract the <link> elements that are links to RSS from the parsed data."
+ (delq nil (mapcar
+ (lambda (el)
+ (if (nnrss-rsslink-p el) el))
+ (nnrss-find-el 'link data))))
+
+(defun nnrss-extract-hrefs (data)
+ "Recursively extract hrefs from a page's source. DATA should be
+the output of xml-parse-region or w3-parse-buffer."
+ (mapcar (lambda (ahref)
+ (cdr (assoc 'href (cadr ahref))))
+ (nnrss-find-el 'a data)))
+
+(defmacro nnrss-match-macro (base-uri item
+ onsite-list offsite-list)
+ `(cond ((or (string-match (concat "^" ,base-uri) ,item)
+ (not (string-match "://" ,item)))
+ (setq ,onsite-list (append ,onsite-list (list ,item))))
+ (t (setq ,offsite-list (append ,offsite-list (list ,item))))))
+
+(defun nnrss-order-hrefs (base-uri hrefs)
+ "Given a list of hrefs, sort them using the following priorities:
+ 1. links ending in .rss
+ 2. links ending in .rdf
+ 3. links ending in .xml
+ 4. links containing the above
+ 5. offsite links
+
+BASE-URI is used to determine the location of the links and
+whether they are `offsite' or `onsite'."
+ (let (rss-onsite-end rdf-onsite-end xml-onsite-end
+ rss-onsite-in rdf-onsite-in xml-onsite-in
+ rss-offsite-end rdf-offsite-end xml-offsite-end
+ rss-offsite-in rdf-offsite-in xml-offsite-in)
+ (mapcar (lambda (href)
+ (if (not (null href))
+ (cond ((string-match "\\.rss$" href)
+ (nnrss-match-macro
+ base-uri href rss-onsite-end rss-offsite-end))
+ ((string-match "\\.rdf$" href)
+ (nnrss-match-macro
+ base-uri href rdf-onsite-end rdf-offsite-end))
+ ((string-match "\\.xml$" href)
+ (nnrss-match-macro
+ base-uri href xml-onsite-end xml-offsite-end))
+ ((string-match "rss" href)
+ (nnrss-match-macro
+ base-uri href rss-onsite-in rss-offsite-in))
+ ((string-match "rdf" href)
+ (nnrss-match-macro
+ base-uri href rdf-onsite-in rdf-offsite-in))
+ ((string-match "xml" href)
+ (nnrss-match-macro
+ base-uri href xml-onsite-in xml-offsite-in)))))
+ hrefs)
+ (append
+ rss-onsite-end rdf-onsite-end xml-onsite-end
+ rss-onsite-in rdf-onsite-in xml-onsite-in
+ rss-offsite-end rdf-offsite-end xml-offsite-end
+ rss-offsite-in rdf-offsite-in xml-offsite-in)))
+
+(defun nnrss-discover-feed (url)
+ "Given a page, find an RSS feed using Mark Pilgrim's
+`ultra-liberal rss locator' (http://diveintomark.org/2002/08/15.html)."
+
+ (let ((parsed-page (nnrss-fetch url)))
+
+;; 1. if this url is the rss, use it.
+ (if (nnrss-rss-p parsed-page)
+ (let ((rss-ns (nnrss-get-namespace-prefix parsed-page "http://purl.org/rss/1.0/")))
+ (nnrss-rss-title-description rss-ns parsed-page url))
+
+;; 2. look for the <link rel="alternate"
+;; type="application/rss+xml" and use that if it is there.
+ (let ((links (nnrss-get-rsslinks parsed-page)))
+ (if links
+ (let* ((xml (nnrss-fetch
+ (cdr (assoc 'href (cadar links)))))
+ (rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/")))
+ (nnrss-rss-title-description rss-ns xml (cdr (assoc 'href (cadar links)))))
+
+;; 3. look for links on the site in the following order:
+;; - onsite links ending in .rss, .rdf, or .xml
+;; - onsite links containing any of the above
+;; - offsite links ending in .rss, .rdf, or .xml
+;; - offsite links containing any of the above
+ (let* ((base-uri (progn (string-match ".*://[^/]+/?" url)
+ (match-string 0 url)))
+ (hrefs (nnrss-order-hrefs
+ base-uri (nnrss-extract-hrefs parsed-page)))
+ (rss-link nil))
+ (while (and (eq rss-link nil) (not (eq hrefs nil)))
+ (let ((href-data (nnrss-fetch (car hrefs))))
+ (if (nnrss-rss-p href-data)
+ (let* ((rss-ns (nnrss-get-namespace-prefix href-data "http://purl.org/rss/1.0/")))
+ (setq rss-link (nnrss-rss-title-description
+ rss-ns href-data (car hrefs))))
+ (setq hrefs (cdr hrefs)))))
+ (if rss-link rss-link
+
+;; 4. check syndic8
+ (nnrss-find-rss-via-syndic8 url))))))))
+
+(defun nnrss-find-rss-via-syndic8 (url)
+ "query syndic8 for the rss feeds it has for the url."
+ (condition-case nil
+ (progn (require 'xml-rpc)
+ (let ((feedid (xml-rpc-method-call
+ "http://www.syndic8.com/xmlrpc.php"
+ 'syndic8.FindSites
+ url)))
+ (if feedid
+ (let* ((feedinfo (xml-rpc-method-call
+ "http://www.syndic8.com/xmlrpc.php"
+ 'syndic8.GetFeedInfo
+ feedid))
+ (urllist
+ (delq nil
+ (mapcar
+ (lambda (listinfo)
+ (if (string-equal
+ (cdr (assoc "status" listinfo))
+ "Syndicated")
+ (cons
+ (cdr (assoc "sitename" listinfo))
+ (list
+ (cons 'title
+ (cdr (assoc
+ "sitename" listinfo)))
+ (cons 'href
+ (cdr (assoc
+ "dataurl" listinfo)))))))
+ feedinfo))))
+ (if (> (length urllist) 1)
+ (let ((completion-ignore-case t)
+ (selection
+ (mapcar (lambda (listinfo)
+ (cons (cdr (assoc "sitename" listinfo))
+ (string-to-int
+ (cdr (assoc "feedid" listinfo)))))
+ feedinfo)))
+ (cdr (assoc
+ (completing-read
+ "Multiple feeds found. Select one: "
+ selection nil t) urllist)))
+ (cdar urllist))))))
+ (message "XML-RPC is not available... not checking Syndic8.")))
+
+(defun nnrss-rss-p (data)
+ "Test if data is an RSS feed. Simply ensures that the first
+element is rss or rdf."
+ (or (eq (caar data) 'rss)
+ (eq (caar data) 'rdf:RDF)))
+
+(defun nnrss-rss-title-description (rss-namespace data url)
+ "Return the title of an RSS feed."
+ (if (nnrss-rss-p data)
+ (let ((description (intern (concat rss-namespace "description")))
+ (title (intern (concat rss-namespace "title")))
+ (channel (nnrss-find-el (intern (concat rss-namespace "channel"))
+ data)))
+ (list
+ (cons 'description (caddr (nth 0 (nnrss-find-el description channel))))
+ (cons 'title (caddr (nth 0 (nnrss-find-el title channel))))
+ (cons 'href url)))))
+
+(defun nnrss-get-namespace-prefix (el uri)
+ "Given EL (containing a parsed element) and URI (containing a string
+that gives the URI for which you want to retrieve the namespace
+prefix), return the prefix."
+ (let* ((prefix (car (rassoc uri (cadar el))))
+ (nslist (if prefix
+ (split-string (symbol-name prefix) ":")))
+ (ns (cond ((eq (length nslist) 1) ; no prefix given
+ "")
+ ((eq (length nslist) 2) ; extract prefix
+ (cadr nslist)))))
+ (if (and ns (not (eq ns "")))
+ (concat ns ":")
+ ns)))
+
(provide 'nnrss)
+
;;; nnrss.el ends here
+
Direct connections:
- `nntp-open-network-stream' (the default),
- `nntp-open-ssl-stream',
+- `nntp-open-tls-stream',
- `nntp-open-telnet-stream'.
Indirect connections:
"*Hook run just before posting an article. It is supposed to be used
to insert Cancel-Lock headers.")
-(defvoo nntp-read-timeout (if (string-match "windows-nt\\|os/2\\|emx\\|cygwin"
- (symbol-name system-type))
- 1.0
- 0.1)
- "How long nntp should wait between checking for the end of output.
-Shorter values mean quicker response, but is more CPU intensive.")
-
;;; Internal variables.
(defvar nntp-record-commands nil
(process-kill-without-query proc)
(save-excursion
(set-buffer buffer)
- (nntp-wait-for-string "^\r*20[01]")
+ (let ((nntp-connection-alist (list proc buffer nil)))
+ (nntp-wait-for-string "^\r*20[01]"))
+ (beginning-of-line)
+ (delete-region (point-min) (point))
+ proc)))
+
+(defun nntp-open-tls-stream (buffer)
+ (let ((proc (open-tls-stream "nntpd" buffer nntp-address nntp-port-number)))
+ (process-kill-without-query proc)
+ (save-excursion
+ (set-buffer buffer)
+ (let ((nntp-connection-alist (list proc buffer nil)))
+ (nntp-wait-for-string "^\r*20[01]"))
(beginning-of-line)
(delete-region (point-min) (point))
proc)))
(unless (< len 10)
(setq nntp-have-messaged t)
(nnheader-message 7 "nntp read: %dk" len)))
- (accept-process-output
- process
- (truncate nntp-read-timeout)
- (truncate (* (- nntp-read-timeout
- (truncate nntp-read-timeout))
- 1000)))
+ (nnheader-accept-process-output process)
;; accept-process-output may update status of process to indicate
;; that the server has closed the connection. This MUST be
;; handled here as the buffer restored by the save-excursion may
(set-buffer (process-buffer process))
(goto-char pop3-read-point)
(while (not (search-forward "\r\n" nil t))
- (accept-process-output process 0 500)
+ (nnheader-accept-process-output process)
(goto-char pop3-read-point))
(setq match-end (point))
(goto-char pop3-read-point)
(save-excursion
(set-buffer (process-buffer process))
(while (not (re-search-forward "^\\.\r\n" nil t))
- (accept-process-output process 0 500)
+ (nnheader-accept-process-output process)
;; bill@att.com ... to save wear and tear on the heap
;; uncommented because the condensed version below is a problem for
;; some.
(defvar rfc2047-header-encoding-alist
'(("Newsgroups" . nil)
+ ("Followup-To" . nil)
("Message-ID" . nil)
("\\(Resent-\\)?\\(From\\|Cc\\|To\\|Bcc\\|Reply-To\\|Sender\\)" .
"-A-Za-z0-9!*+/=_")
;; Encode using the charset, if any.
(when (and (mm-multibyte-p)
(> (length elems) 1)
- (not (equal (intern (car elems)) 'us-ascii)))
+ (not (equal (intern (downcase (car elems))) 'us-ascii)))
(mm-decode-coding-region (point-min) (point-max)
- (intern (car elems))))
+ (intern (downcase (car elems)))))
(buffer-string))))
(defun rfc2231-encode-string (param value)
(gnus-put-image image string))))
images))))
+;;;###autoload
+(defun smiley-buffer (&optional buffer)
+ "Run `smiley-region' at the buffer, specified in the argument or
+interactively. If there's no argument, do it at the current buffer"
+ (interactive "bBuffer to run smiley-region: ")
+ (save-excursion
+ (if buffer
+ (set-buffer (get-buffer buffer)))
+ (smiley-region (point-min) (point-max))))
+
(defun smiley-toggle-buffer (&optional arg)
"Toggle displaying smiley faces in article buffer.
With arg, turn displaying on if and only if arg is positive."
:type 'regexp
:group 'spam)
-(defcustom spam-ham-marks (list 'gnus-del-mark 'gnus-read-mark
- 'gnus-killed-mark 'gnus-kill-file-mark
- 'gnus-low-score-mark)
- "Marks considered as being ham (positively not spam).
-Such articles will be processed as ham (non-spam) on group exit."
- :type '(set
- (variable-item gnus-del-mark)
- (variable-item gnus-read-mark)
- (variable-item gnus-killed-mark)
- (variable-item gnus-kill-file-mark)
- (variable-item gnus-low-score-mark))
- :group 'spam)
-
-(defcustom spam-spam-marks (list 'gnus-spam-mark)
- "Marks considered as being spam (positively spam).
-Such articles will be transmitted to `bogofilter -s' on group exit."
- :type '(set
- (variable-item gnus-spam-mark)
- (variable-item gnus-killed-mark)
- (variable-item gnus-kill-file-mark)
- (variable-item gnus-low-score-mark))
- :group 'spam)
-
(defcustom spam-face 'gnus-splash-face
"Face for spam-marked articles"
:type 'face
gnus-summary-highlight)
;; convenience functions
+(defun spam-group-ham-mark-p (group mark &optional spam)
+ (when (stringp group)
+ (let* ((marks (spam-group-ham-marks group spam))
+ (marks (if (symbolp mark)
+ marks
+ (mapcar 'symbol-value marks))))
+ (memq mark marks))))
+
+(defun spam-group-spam-mark-p (group mark)
+ (spam-group-ham-mark-p group mark t))
+
+(defun spam-group-ham-marks (group &optional spam)
+ (when (stringp group)
+ (let* ((marks (if spam
+ (gnus-parameter-spam-marks group)
+ (gnus-parameter-ham-marks group)))
+ (marks (car marks))
+ (marks (if (listp (car marks)) (car marks) marks)))
+ marks)))
+
+(defun spam-group-spam-marks (group)
+ (spam-group-ham-marks group t))
+
(defun spam-group-spam-contents-p (group)
(if (stringp group)
(or (member group spam-junk-mailgroups)
(defun spam-ham-move-routine (&optional group copy)
(gnus-summary-kill-process-mark)
(let ((articles gnus-newsgroup-articles)
- article ham-mark-values mark tomove)
+ article mark tomove)
(when (stringp group) ; this routine will do nothing
; without a valid group
- (dolist (mark spam-ham-marks)
- (push (symbol-value mark) ham-mark-values))
(dolist (article articles)
- (when (memq (gnus-summary-article-mark article) ham-mark-values)
+ (when (spam-group-spam-mark-p gnus-newsgroup-name
+ (gnus-summary-article-mark article))
(push article tomove)))
;; now do the actual move
(defun spam-generic-register-routine (spam-func ham-func)
(let ((articles gnus-newsgroup-articles)
- article mark ham-articles spam-articles spam-mark-values
- ham-mark-values)
-
- ;; marks are stored as symbolic values, so we have to dereference
- ;; them for memq to work. we wouldn't have to do this if
- ;; gnus-summary-article-mark returned a symbol.
- (dolist (mark spam-ham-marks)
- (push (symbol-value mark) ham-mark-values))
-
- (dolist (mark spam-spam-marks)
- (push (symbol-value mark) spam-mark-values))
+ article mark ham-articles spam-articles)
(while articles
(setq article (pop articles)
mark (gnus-summary-article-mark article))
- (cond ((memq mark spam-mark-values) (push article spam-articles))
+ (cond ((spam-group-spam-mark-p gnus-newsgroup-name mark)
+ (push article spam-articles))
((memq article gnus-newsgroup-saved))
- ((memq mark ham-mark-values) (push article ham-articles))))
+ ((spam-group-ham-mark-p gnus-newsgroup-name mark)
+ (push article ham-articles))))
+
(when (and ham-articles ham-func)
(mapc ham-func ham-articles)) ; we use mapc because unlike
; mapcar it discards the
--- /dev/null
+;;; tls.el --- TLS/SSL support via wrapper around GnuTLS
+
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+;; Keywords: comm, tls, gnutls, ssl
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This package implements a simple wrapper around "gnutls-cli" to
+;; make Emacs support TLS/SSL.
+;;
+;; Usage is the same as `open-network-stream', i.e.:
+;;
+;; (setq tmp (open-tls-stream "test" (current-buffer) "news.mozilla.org" 563))
+;; ...
+;; #<process test>
+;; (process-send-string tmp "mode reader\n")
+;; 200 secnews.netscape.com Netscape-Collabra/3.52 03615 NNRP ready ...
+;; nil
+;; (process-send-string tmp "quit\n")
+;; 205
+;; nil
+
+;; To use this package as a replacement for ssl.el by William M. Perry
+;; <wmperry@cs.indiana.edu>, you need to evaluate the following:
+;;
+;; (defalias 'open-ssl-stream 'open-tls-stream)
+
+;;; Code:
+
+(eval-and-compile
+ (autoload 'format-spec "format-spec")
+ (autoload 'format-spec-make "format-spec"))
+
+(defgroup tls nil
+ "Transport Layer Security (TLS) parameters."
+ :group 'comm)
+
+(defcustom tls-program '("gnutls-cli -p %p %h"
+ "gnutls-cli -p %p %h --protocols ssl3")
+ "List of strings containing commands to start TLS stream to a host.
+Each entry in the list is tried until a connection is successful.
+%s is replaced with server hostname, %p with port to connect to.
+The program should read input on stdin and write output to
+stdout. Also see `tls-success' for what the program should output
+after successful negotiation."
+ :type '(repeat string)
+ :group 'tls)
+
+(defcustom tls-process-connection-type nil
+ "*Value for `process-connection-type' to use when starting process."
+ :type 'boolean
+ :group 'tls)
+
+(defcustom tls-success "- Handshake was completed"
+ "*Regular expression indicating completed TLS handshakes.
+The default is what GNUTLS's \"gnutls-cli\" outputs."
+ :type 'regexp
+ :group 'tls)
+
+(defun open-tls-stream (name buffer host service)
+ "Open a TLS connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Input and output work as for subprocesses; `delete-process' closes it.
+Args are NAME BUFFER HOST SERVICE.
+NAME is name for process. It is modified if necessary to make it unique.
+BUFFER is the buffer (or buffer-name) to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+ BUFFER may be also nil, meaning that this process is not associated
+ with any buffer
+Third arg is name of the host to connect to, or its IP address.
+Fourth arg SERVICE is name of the service desired, or an integer
+specifying a port number to connect to."
+ (let ((cmds tls-program) cmd done)
+ (message "Opening TLS connection to `%s'..." host)
+ (while (and (not done) (setq cmd (pop cmds)))
+ (message "Opening TLS connection with `%s'..." cmd)
+ (let* ((process-connection-type tls-process-connection-type)
+ (process (start-process
+ name buffer shell-file-name shell-command-switch
+ (format-spec
+ cmd
+ (format-spec-make
+ ?h host
+ ?p (if (integerp service)
+ (int-to-string service)
+ service)))))
+ response)
+ (while (and process
+ (memq (process-status process) '(open run))
+ (save-excursion
+ (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+ (goto-char (point-min))
+ (not (setq done (re-search-forward tls-success nil t)))))
+ (accept-process-output process 1)
+ (sit-for 1))
+ (message "Opening TLS connection with `%s'...%s" cmd
+ (if done "done" "failed"))
+ (if done
+ (setq done process)
+ (delete-process process))))
+ (message "Opening TLS connection to `%s'...%s"
+ host (if done "done" "failed"))
+ done))
+
+(provide 'tls)
+
+;;; tls.el ends here
@echo off\r
\r
-rem Written by David Charlap (shamino@writeme.com)\r
-rem\r
-rem There are two possible problems with this batch file. The emacs.bat batch\r
-rem file may not exist in all distributions. It is part of the GNU build of\r
-rem Emacs 20.4 (http://www.gnu.org/softare/emacs/windows.ntemacs.html) If you\r
-rem install Gnus with some other build, you may have to replace calls to\r
-rem %1\emacs.bat with something else.\r
-rem \r
-rem Also, the emacs.bat file that comes with Emacs does not accept more than 9\r
-rem parameters, so the attempts to compile the .texi files will fail. To\r
-rem fix that (at least on NT. I don't know about Win95), the following\r
-rem change should be made to emacs.bat:\r
-rem \r
-rem %emacs_dir%\bin\emacs.exe %1 %2 %3 %4 %5 %6 %7 %8 %9\r
-rem \r
-rem should become\r
-rem \r
-rem %emacs_dir%\bin\emacs.exe %*\r
-rem \r
-rem which will allow the batch file to accept an unlimited number of\r
-rem parameters.\r
-\r
+rem Written by Frank Schmitt <ich@frank-schmitt.net>\r
+rem based on the work by David Charlap (shamino@writeme.com)\r
+rem .\r
rem Clear PWD so emacs doesn't get confused\r
set GNUS_PWD_SAVE=%PWD%\r
set PWD=\r
+set ERROR=:\r
\r
if "%1" == "" goto usage\r
\r
-rem Directory where the info files are installed\r
-set GNUS_INFO_DIR=%1\info\r
-\r
rem Emacs 20.7 no longer includes emacs.bat. Use emacs.exe if the batch file is\r
rem not present -- this also fixes the problem about too many parameters on Win9x.\r
-set emacs=emacs.exe\r
-if exist %1\bin\emacs.bat set emacs=emacs.bat\r
-set EMACSBATCH=call %1\bin\%emacs% -no-site-file -batch -q\r
+if exist %1\emacs.bat goto ebat\r
+if exist %1\emacs.exe goto eexe\r
+if exist %1\xemacs.exe goto xemacs\r
+goto noemacs\r
+\r
+:ebat\r
+set EMACS=emacs.bat\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using emacs.bat (If you've got en Emacs >= 20.3 please remove Emacs.bat, \r
+echo * it isn't needed anymore.\r
+echo ***************************************************************************\r
+echo.\r
+goto emacs\r
+\r
+:eexe\r
+set EMACS=emacs.exe\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using emacs.exe\r
+echo ***************************************************************************\r
+echo.\r
+goto emacs\r
\r
+:emacs\r
+if not "%2" == "/copy" goto emacsnocopy\r
+if not exist %1\..\site-lisp mkdir %1\..\site-lisp\r
+if not exist %1\..\site-lisp\gnus mkdir %1\..\site-lisp\gnus\r
+if not exist %1\..\site-lisp\subdirs.el set subdirwarning=yes\r
+:emacsnocopy\r
+set GNUS_INFO_DIR=%1\..\info\r
+set GNUS_LISP_DIR=%1\..\site-lisp\gnus\lisp\r
+set GNUS_ETC_DIR=%1\..\site-lisp\gnus\etc\r
+goto lisp\r
+ \r
+:xemacs \r
+set EMACS=xemacs.exe\r
+if not "%2" == "/copy" goto xemacsnocopy\r
+if not exist %1\..\..\site-packages\ mkdir %1\..\..\site-packages\\r
+if not exist %1\..\..\site-packages\info mkdir %1\..\..\site-packages\info\r
+if not exist %1\..\..\site-packages\lisp mkdir %1\..\..\site-packages\lisp\r
+if not exist %1\..\..\site-packages\etc mkdir %1\..\..\site-packages\etc\r
+:xemacsnocopy\r
+set GNUS_INFO_DIR=%1\..\..\site-packages\info\r
+set GNUS_LISP_DIR=%1\..\..\site-packages\lisp\gnus\r
+set GNUS_ETC_DIR=%1\..\..\site-packages\etc\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using xemacs.exe\r
+echo ***************************************************************************\r
+echo.\r
+goto lisp\r
+\r
+:lisp\r
+set EMACSBATCH=call %1\%EMACS% -no-site-file -batch -q\r
cd lisp\r
+if exist gnus-load.el del gnus-load.el\r
+echo.\r
+echo Stand by while generating autoloads.\r
+echo.\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-cus-load .\r
+if ErrorLevel 1 set ERROR=make-cus-load\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-auto-load .\r
+if ErrorLevel 1 set ERROR=%ERROR%,make-auto-load\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-load\r
+if ErrorLevel 1 set ERROR=%ERROR%,make-load\r
+echo.\r
+echo Stand by while compiling lisp files.\r
+echo.\r
%EMACSBATCH% -l ./dgnushack.el -f dgnushack-compile\r
-if not "%2" == "/copy" goto info\r
-attrib -r %1\lisp\gnus\*\r
-copy *.el* %1\lisp\gnus\r
+if ErrorLevel 1 set ERROR=%ERROR%,compile\r
\r
-:info\r
-set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo\r
+if not "%2" == "/copy" goto infotest\r
+echo.\r
+echo Stand by while copying lisp files.\r
+echo.\r
+if not exist %GNUS_LISP_DIR% mkdir %GNUS_LISP_DIR%\r
+xcopy /R /Q /Y *.el* %GNUS_LISP_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-lisp\r
+goto infotest\r
+\r
+:infotest\r
cd ..\texi\r
-%EMACSINFO% message.texi\r
+if exist sieve del sieve\r
+makeinfo sieve.texi\r
+if exist sieve goto minfo \r
+REM It seems that makeinfo isn't available\r
+set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using infohack.el, if you've got makeinfo.exe put it in PATH.\r
+echo ***************************************************************************\r
+echo.\r
+goto info\r
+\r
+:minfo\r
+set EMACSINFO=makeinfo \r
+echo.\r
+echo ***************************************************************************\r
+echo * Using makeinfo\r
+echo ***************************************************************************\r
+echo.\r
+goto info\r
+\r
+:info\r
+echo.\r
+echo Stand by while generating info files.\r
+echo.\r
%EMACSINFO% emacs-mime.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,emacs-mime.texi\r
%EMACSINFO% gnus.texi\r
-if not "%2" == "/copy" goto done\r
-copy gnus %GNUS_INFO_DIR%\r
-copy gnus-? %GNUS_INFO_DIR%\r
-copy gnus-?? %GNUS_INFO_DIR%\r
-copy message %GNUS_INFO_DIR%\r
-copy message-? %GNUS_INFO_DIR%\r
-copy emacs-mime %GNUS_INFO_DIR%\r
-copy sieve %GNUS_INFO_DIR%\r
-copy pgg %GNUS_INFO_DIR%\r
-echo Maybe you should add the following line to %GNUS_INFO_DIR%\dir:\r
+if ErrorLevel 1 set ERROR=%ERROR%,gnus.texi\r
+%EMACSINFO% sieve.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,sieve.texi\r
+%EMACSINFO% pgg.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,pgg.texi\r
+%EMACSINFO% message.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,message.texi\r
+\r
+if not "%2" == "/copy" goto nocopy\r
+if not exist %GNUS_INFO_DIR% mkdir %GNUS_INFO_DIR%\r
+\r
+echo.\r
+echo Stand by while copying info files.\r
+echo.\r
+xcopy /R /Q /Y gnus %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-info\r
+xcopy /R /Q /Y gnus-? %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-x-info\r
+xcopy /R /Q /Y gnus-?? %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-xx-info\r
+xcopy /R /Q /Y message %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-message-info\r
+if exist message-1 xcopy /R /Q /Y message-? %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-message-x-info\r
+xcopy /R /Q /Y emacs-mime %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-emacs-mime-info\r
+xcopy /R /Q /Y sieve %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-sieve-info\r
+xcopy /R /Q /Y pgg %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-pgg-info\r
+\r
echo.\r
-echo * PGG: (pgg). Emacs interface to various PGP implementations.\r
-echo * Sieve: (sieve). Managing Sieve scripts in Emacs.\r
+echo ***************************************************************************\r
+echo * You should add the following lines to \r
+echo * %GNUS_INFO_DIR%\dir \r
+echo * if they aren't already there:\r
+echo *\r
+echo * * PGG: (pgg). Emacs interface to various PGP implementations.\r
+echo * * Sieve: (sieve). Managing Sieve scripts in Emacs.\r
+echo ***************************************************************************\r
echo.\r
\r
:etc\r
cd ..\etc\r
-copy gnus-tut.txt %1\etc\r
+echo.\r
+echo Stand by while copying etc files.\r
+echo.\r
+if not exist %GNUS_ETC_DIR% mkdir %GNUS_ETC_DIR%\r
+xcopy /R /Q /Y gnus-tut.txt %GNUS_ETC_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-gnus-tut-txt\r
+if not exist %GNUS_ETC_DIR%\gnus mkdir %GNUS_ETC_DIR%\gnus\r
+xcopy /R /Q /Y .\gnus\* %GNUS_ETC_DIR%\gnus\\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-gnus-*\r
+if not exist %GNUS_ETC_DIR%\smilies mkdir %GNUS_ETC_DIR%\smilies\r
+xcopy /R /Q /Y .\smilies\* %GNUS_ETC_DIR%\smilies\\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-smilies-*\r
+goto warnings\r
+\r
+:nocopy\r
+echo.\r
+echo ***************************************************************************\r
+echo * You chose not to copy the files, therefore you should add the \r
+echo * following lines to the TOP of your [X]emacs customization file:\r
+echo *\r
+echo * (add-to-list 'load-path "/Path/to/gnus/lisp")\r
+echo * (if (featurep 'xemacs)\r
+echo * (add-to-list 'Info-directory-list "c:/Path/to/gnus/texi/")\r
+echo * (add-to-list 'Info-default-directory-list "c:/Path/to/gnus/texi/")\r
+echo * (require 'gnus-load)\r
+echo *\r
+echo * Replace c:/Path/to/gnus with the Path where your new Gnus is (that's here\r
+echo * and yes, you've got to use forward slashes).\r
+echo ***************************************************************************\r
+echo.\r
+\r
+:warnings\r
+if not "%subdirwarning%" == "yes" goto warngnusload\r
+echo.\r
+echo ***************************************************************************\r
+echo * There's no subdirs.el file in your site-lisp directory, you should\r
+echo * therefor add the following line to the TOP of your Emacs\r
+echo * customization file:\r
+echo *\r
+echo * (add-to-list 'load-path "/Path/to/emacs-site-lisp-directory/gnus/lisp")\r
+echo * (require 'gnus-load)\r
+echo * Yes, it must be forward slashes.\r
+echo ***************************************************************************\r
+echo.\r
+goto warnerrors\r
+\r
+:warngnusload\r
+echo.\r
+echo ***************************************************************************\r
+echo * You should add the following line to the TOP of your Emacs\r
+echo * customization file:\r
+echo *\r
+echo * (require 'gnus-load)\r
+echo ***************************************************************************\r
+echo.\r
+\r
+:warnerrors\r
+if "%ERROR%"==":" goto noerrors\r
+set errorlevel=1\r
+echo.\r
+echo ***************************************************************************\r
+echo * WARNING ERRORS OCCURRED!\r
+echo * You should look for error messages in the output of the called programs\r
+echo * and try to find out what exactly went wrong.\r
+echo * Errors occured in the following modules:\r
+echo * %ERROR%\r
+echo ***************************************************************************\r
+echo.\r
+goto done\r
+\r
+:noerrors\r
+set errorlevel=0\r
\r
:done\r
cd ..\r
goto end\r
\r
+:noemacs\r
+echo.\r
+echo ***************************************************************************\r
+echo * Unable to find emacs.exe or xemacs.exe on the path you specified!\r
+echo * STOP!\r
+echo ***************************************************************************\r
+echo.\r
+goto usage\r
+\r
:usage\r
-echo Usage: make :emacs-dir: [/copy]\r
echo.\r
-echo where: :emacs-dir: is the directory you installed emacs in\r
-echo eg. d:\emacs\20.4\r
-echo /copy indicates that the compiled files should be copied to your\r
-echo emacs lisp, info, and etc directories\r
+echo ***************************************************************************\r
+echo * Usage: make.bat :[X]Emacs-exe-dir: [/copy]\r
+echo *\r
+echo * where: :[X]Emacs-exe-dir: is the directory your \r
+echo * emacs.exe respectively xemacs.exe resides in, \r
+echo * e.g. G:\Programme\XEmacs\XEmacs-21.4.11\i586-pc-win32\\r
+echo * or G:\Emacs\bin\r
+echo * /copy indicates that the compiled files should be copied to your\r
+echo * emacs lisp, info, and etc site directories.\r
+echo *\r
+echo * Note: If you have Emacs/w3 you should set the environment variable \r
+echo * W3DIR to the directory where w3 is installed eg.\r
+echo * set W3DIR=d:\lisp\w3-4.0pre46\lisp\r
+echo ***************************************************************************\r
echo.\r
-echo Note: If you have Emacs/w3 you should set the environment variable \r
-echo W3DIR to the directory where w3 is installed eg.\r
-echo set W3DIR=d:\lisp\w3-4.0pre46\lisp\r
\r
-rem Restore PWD so whoever called this batch file doesn't get confused\r
+:end\r
+rem Restore environment variables\r
set PWD=%GNUS_PWD_SAVE%\r
set GNUS_PWD_SAVE=\r
set EMACSBATCH=\r
+set GNUS_LISP_DIR=\r
set GNUS_INFO_DIR=\r
-:end\r
+set GNUS_ETC_DIR=\r
+set subdirwarning=\r
+set ERROR=\r
+2003-03-31 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnus.texi (Exiting Gnus): Removed gnus-unload.
+
+2003-03-31 Simon Josefsson <jas@extundo.com>
+
+ * gnus.texi (IMAP): Add.
+
+2003-03-27 Paul Jarc <prj@po.cwru.edu>
+
+ * gnus.texi (Comparing Mail Back Ends): Note nnmaildir's
+ incompatibilities more prominently.
+
+2003-03-27 Paul Jarc <prj@po.cwru.edu>
+
+ * gnus.texi (Maildir): Note nnmail-expiry-target incompatibility.
+
+2003-03-27 Jesper Harder <harder@ifa.au.dk>
+
+ * gnus.texi (Adaptive Scoring): Fix.
+
+2003-03-23 Simon Josefsson <jas@extundo.com>
+
+ * gnus.texi (Direct Functions, Common Variables)
+ (Mail Source Specifiers, IMAP): Add TLS wherever SSL is mentioned
+ now.
+
+2003-03-23 Jesper Harder <harder@ifa.au.dk>
+
+ * gnus.texi (Group Information, Article Washing)
+ (Formatting Fonts, Group Parameters): Fix external xrefs.
+
+ * message.texi (Mailing Lists): do.
+
+2003-03-22 Simon Josefsson <jas@extundo.com>
+
+ * gnus.texi (Troubleshooting): Fix typo.
+ (Drafts): Mention how to restore special property, suggested by
+ Florian Weimer <fw@deneb.enyo.de>.
+
+2003-03-19 Simon Josefsson <jas@extundo.com>
+
+ * gnus.texi (Misc Article): Add.
+ (Agent Basics): Fix makeinfo warnings.
+
+ * message.texi (IDNA): New.
+
+2003-03-18 Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+ * gnus.texi (Gnus Unplugged): Refer to new agent Group/Topic
+ parameters.
+ (Category Syntax): New description.
+ (Category Buffer): New command.
+ (Category Variables): New variables.
+ (Agent as Cache): Expanded description.
+ (Agent Expiry): Expanded description.
+ (Agent Variables): Fixed and new descriptions.
+
+ * infohack.el (batch-makeinfo): Provide local implementation of
+ subst-char-in-region as the built-in implementation is unreliable
+ on Windows XP (Intermittent failure results in build looping
+ forever).
+
+2003-03-18 Paul Jarc <prj@po.cwru.edu>
+
+ * gnus.texi (Maildir): Replace create-directory with
+ target-prefix.
+
+2003-03-18 Paul Jarc <prj@po.cwru.edu>
+
+ * gnus.texi (Maildir): More info for expire-group; add
+ distrust-Lines:.
+
+2003-03-17 Paul Jarc <prj@po.cwru.edu>
+
+ * gnus.texi (Comparing Mail Back Ends): nnmaildir fixes.
+
2003-03-17 Reiner Steib <Reiner.Steib@gmx.de>
* gnus.texi (Using MIME): Added gnus-mime-delete-part.
(Mail Group Commands): do.
* gnus.texi: Mark-up fixes.
-
+
2003-01-27 Teodor Zlatanov <tzz@lifelogs.com>
* gnus.texi: replace `H' mark with `$' mark
(gnus-agent-mark-unread-after-downloaded): New variable.
(gnus-agent-consider-all-articles): New variable.
(gnus-agent-max-fetch-size): New variable.
-
+
2003-01-22 Jesper Harder <harder@ifa.au.dk>
* gnusref.tex (subsection*{Notes}): do.
* gnus.texi: Markup fixes: use @code for nil and t, use @file for
files.
-
+
* message.texi: do.
* emacs-mime.texi: do.
-
+
2003-01-19 Jesper Harder <harder@ifa.au.dk>
* dir (File): Add pgg.
2003-01-15 ShengHuo ZHU <zsh@cs.rochester.edu>
- * gnus.texi: Don't use `path' in some cases.
+ * gnus.texi: Don't use `path' in some cases.
From the GNU coding standards:
-
+
Please do not use the term ``pathname'' that is used in Unix
documentation; use ``file name'' (two words) instead. We use
the term ``path'' only for search paths, which are lists of
2003-01-09 Teodor Zlatanov <tzz@lifelogs.com>
- * gnus.texi (Filtering Spam Using spam.el, ifile spam filtering)
+ * gnus.texi (Filtering Spam Using spam.el, ifile spam filtering)
(spam-stat spam filtering): added new functionality and explained
old functionality better, especially where it has changed in
ham/spam/unclassified group exit processing.
2003-01-05 Teodor Zlatanov <tzz@lifelogs.com>
- * gnus.texi (Filtering Spam Using spam.el)
- (Blacklists and Whitelists, BBDB Whitelists, Blackholes)
+ * gnus.texi (Filtering Spam Using spam.el)
+ (Blacklists and Whitelists, BBDB Whitelists, Blackholes)
(Bogofilter, Ifile spam filtering, Extending spam.el): updated
documentation for the new spam.el functionality
2002-12-29 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus.texi (Loose Threads): add
- gnus-summary-make-false-root-always.
+ gnus-summary-make-false-root-always.
(Finding the Parent): Change name of nnweb server.
2002-12-22 Jesper Harder <harder@ifa.au.dk>
* gnus.texi (Optional Back End Functions):
nnchoke-request-update-info need not return the info object.
-
+
2002-12-15 Jesper Harder <harder@ifa.au.dk>
* gnusref.tex: Additions.
\makeindex
\begin{document}
-\newcommand{\gnusversionname}{Oort Gnus v0.16}
+\newcommand{\gnusversionname}{Oort Gnus v0.17}
\newcommand{\gnuschaptername}{}
\newcommand{\gnussectionname}{}
spool or your mbox file. All at the same time, if you want to push your
luck.
-This manual corresponds to Oort Gnus v0.16.
+This manual corresponds to Oort Gnus v0.17.
@end ifinfo
to-address and to-list parameters for this group as addresses of
mailing lists you are subscribed to. Giving Gnus this information is
(only) a first step in getting it to generate correct Mail-Followup-To
-headers for your posts to these lists. Look here @pxref{(message)Mailing
-Lists} for a complete treatment of available MFT support.
+headers for your posts to these lists. Look here @pxref{Mailing
+Lists, , Mailing Lists, message, The Message Manual} for a complete
+treatment of available MFT support.
See also @code{gnus-find-subscribed-addresses}, the function that
directly uses this group parameter.
@code{gnus-after-exiting-gnus-hook} is called as the final item when
exiting Gnus.
-@findex gnus-unload
-@cindex unloading
-If you wish to completely unload Gnus and all its adherents, you can use
-the @code{gnus-unload} command. This command is also very handy when
-trying to customize meta-variables.
-
Note:
@quotation
and displayed in an ephemeral group.
Note that the control messages are compressed. To use this command
-you need to turn on @code{auto-compression-mode}
-(@pxref{(emacs)Compressed Files}).
+you need to turn on @code{auto-compression-mode} (@pxref{Compressed
+Files, ,Compressed Files, emacs, The Emacs Manual}).
@item H d
@itemx C-c C-d
@vindex gnus-article-wash-function
The default is to use the function specified by
-@code{mm-text-html-renderer} (@pxref{(emacs-mime)Display
-Customization}) to convert the @sc{html}, but this is controlled by
-the @code{gnus-article-wash-function} variable. Pre-defined functions
-you can use include:
+@code{mm-text-html-renderer} (@pxref{Display Customization, ,Display
+Customization, emacs-mime, The Emacs MIME Manual}) to convert the
+@sc{html}, but this is controlled by the
+@code{gnus-article-wash-function} variable. Pre-defined functions you
+can use include:
@table @code
@item w3
@vindex gnus-page-delimiter
This is the delimiter mentioned above. By default, it is @samp{^L}
(formfeed).
+
+@cindex IDNA
+@cindex internationalized domain names
+@vindex gnus-use-idna
+@item gnus-use-idna
+This variable controls whether Gnus performs IDNA decoding of
+internationalized domain names inside @sc{From:}, @sc{To:} and
+@sc{Cc:} headers. This requires GNU Libidn
+(@url{http://www.gnu.org/software/libidn/}, and this variable is only
+enabled if you have installed it.
+
@end table
If the group doesn't exist, it will be created and you'll be subscribed
to it. The only way to make it disappear from the Group buffer is to
-unsubscribe it.
+unsubscribe it. The special properties of the draft group comes from
+a group property (@pxref{Group Parameters}), and if lost the group
+behaves like any other group. This means the commands below will not
+be available. To restore the special properties of the group, the
+simplest way is to kill the group, using @kbd{C-k}, and restart
+Gnus. The group is automatically created again with the
+correct parameters. The content of the group is not lost.
@c @findex gnus-dissociate-buffer-from-draft
@c @kindex C-c M-d (Mail)
This is the default, and simply connects to some port or other on the
remote system.
+@findex nntp-open-tls-stream
+@item nntp-open-tls-stream
+Opens a connection to a server over a @dfn{secure} channel. To use
+this you must have GNUTLS installed (see
+@uref{http://www.gnu.org/software/gnutls/}). You then define a server
+as follows:
+
+@lisp
+;; "nntps" is port 563 and is predefined in our /etc/services
+;; however, gnutls-cli -p doesn't like named ports.
+;;
+(nntp "snews.bar.com"
+ (nntp-open-connection-function nntp-open-tls-stream)
+ (nntp-port-number )
+ (nntp-address "snews.bar.com"))
+@end lisp
+
@findex nntp-open-ssl-stream
@item nntp-open-ssl-stream
Opens a connection to a server over a @dfn{secure} channel. To use this
define a server as follows:
@lisp
-;; Type `C-c C-c' after you've finished editing.
-;;
;; "snews" is port 563 and is predefined in our /etc/services
-;; however, openssl s_client -port doesn't like named ports
+;; however, openssl s_client -port doesn't like named ports.
;;
(nntp "snews.bar.com"
(nntp-open-connection-function nntp-open-ssl-stream)
@item nntp-pre-command
@vindex nntp-pre-command
-A command wrapper to use when connecting through a non native connection
-function (all except @code{nntp-open-network-stream} and
-@code{nntp-open-ssl-stream}. This is where you would put a @samp{SOCKS}
-wrapper for instance.
+A command wrapper to use when connecting through a non native
+connection function (all except @code{nntp-open-network-stream},
+@code{nntp-open-tls-stream}, and @code{nntp-open-ssl-stream}. This is
+where you would put a @samp{SOCKS} wrapper for instance.
@item nntp-address
@vindex nntp-address
@item nntp-port-number
@vindex nntp-port-number
-Port number to connect to the @sc{nntp} server. The default is @samp{nntp}.
-If you use @sc{nntp} over @sc{ssl}, you may want to use integer ports rather
-than named ports (i.e, use @samp{563} instead of @samp{snews}), because
-external SSL tools may not work with named ports.
+Port number to connect to the @sc{nntp} server. The default is
+@samp{nntp}. If you use @sc{nntp} over @sc{tls}/@sc{ssl}, you may
+want to use integer ports rather than named ports (i.e, use @samp{563}
+instead of @samp{snews} or @samp{nntps}), because external TLS/SSL
+tools may not work with named ports.
@item nntp-end-of-line
@vindex nntp-end-of-line
and fetches articles from a given @sc{imap} mailbox. @xref{IMAP}, for
more information.
-Note that for the Kerberos, GSSAPI, SSL/TLS and STARTTLS support you
+Note that for the Kerberos, GSSAPI, TLS/SSL and STARTTLS support you
may need external programs and libraries, @xref{IMAP}.
Keywords:
@item :port
The port number of the @sc{imap} server. The default is @samp{143}, or
-@samp{993} for SSL/TLS connections.
+@samp{993} for TLS/SSL connections.
@item :user
The user name to give to the @sc{imap} server. The default is the login
@item :stream
What stream to use for connecting to the server, this is one of the
symbols in @code{imap-stream-alist}. Right now, this means
-@samp{gssapi}, @samp{kerberos4}, @samp{starttls}, @samp{ssl},
-@samp{shell} or the default @samp{network}.
+@samp{gssapi}, @samp{kerberos4}, @samp{starttls}, @samp{tls},
+@samp{ssl}, @samp{shell} or the default @samp{network}.
@item :authentication
Which authenticator to use for authenticating to the server, this is
@item directory
For each of your nnmaildir servers (it's very unlikely that you'd need
more than one), you need to create a directory and populate it with
-symlinks to maildirs (and nothing else; do not choose a directory
-already used for other purposes). You could also put maildirs
-themselves (instead of symlinks to them) directly in the server
-directory, but that would break @code{nnmaildir-request-delete-group},
-so you wouldn't be able to delete those groups from within Gnus. (You
-could still delete them from your shell with @code{rm -r foo}.) Each
-maildir will be represented in Gnus as a newsgroup on that server; the
-filename of the symlink will be the name of the group. Any filenames
-in the directory starting with `.' are ignored. The directory is
-scanned when you first start Gnus, and each time you type @kbd{g} in
-the group buffer; if any maildirs have been removed or added,
-nnmaildir notices at these times.
+maildirs or symlinks to maildirs (and nothing else; do not choose a
+directory already used for other purposes). Each maildir will be
+represented in Gnus as a newsgroup on that server; the filename of the
+symlink will be the name of the group. Any filenames in the directory
+starting with `.' are ignored. The directory is scanned when you
+first start Gnus, and each time you type @kbd{g} in the group buffer;
+if any maildirs have been removed or added, nnmaildir notices at these
+times.
The value of the @code{directory} parameter should be a Lisp form
which is processed by @code{eval} and @code{expand-file-name} to get
only when the server is opened; the resulting string is used until the
server is closed. (If you don't know about forms and @code{eval},
don't worry - a simple string will work.) This parameter is not
-optional; you must specify it. I don't recommend using @file{~/Mail}
-or a subdirectory of it; several other parts of Gnus use that
-directory by default for various things, and may get confused if
-nnmaildir uses it too. @file{~/.nnmaildir} is a typical value.
+optional; you must specify it. I don't recommend using
+@code{"~/Mail"} or a subdirectory of it; several other parts of Gnus
+use that directory by default for various things, and may get confused
+if nnmaildir uses it too. @code{"~/.nnmaildir"} is a typical value.
-@item create-directory
+@item target-prefix
This should be a Lisp form which is processed by @code{eval} and
-@code{expand-file-name} to get the name of the directory where new
-maildirs are created. The form is @code{eval}ed only when the server
-is opened; the resulting string is used until the server is closed.
-This parameter is optional, but if you do not supply it, you cannot
-create new groups from within Gnus. (You could still create them from
-your shell with @code{mkdir -m 0700 foo foo/tmp foo/new foo/cur}.) A
-relative path is interpreted as relative to the @code{directory} path.
-@code{create-directory} and @code{directory} must be different;
-otherwise, group creation and deletion will break. (If you don't need
-those features, you can omit @code{create-directory} entirely.)
+@code{expand-file-name}. The form is @code{eval}ed only when the
+server is opened; the resulting string is used until the server is
+closed.
+
+When you create a group on an nnmaildir server, the maildir is created
+with @code{target-prefix} prepended to its name, and a symlink
+pointing to that maildir is created, named with the plain group name.
+So if @code{directory} is @code{"~/.nnmaildir"} and
+@code{target-prefix} is @code{"../maildirs/"}, then when you create
+the group @code{foo}, nnmaildir will create
+@file{~/.nnmaildir/../maildirs/foo} as a maildir, and will create
+@file{~/.nnmaildir/foo} as a symlink pointing to
+@file{../maildirs/foo}.
+
+You can set @code{target-prefix} to a string without any slashes to
+create both maildirs and symlinks in the same @code{directory}; in
+this case, any maildirs found in @code{directory} whose names start
+with @code{target-prefix} will not be listed as groups (but the
+symlinks pointing to them will be).
+
+As a special case, if @code{target-prefix} is @code{""} (the default),
+then when you create a group, the maildir will be created in
+@code{directory} without a corresponding symlink. Beware that you
+cannot use @code{gnus-group-delete-group} on such groups without the
+@code{force} argument.
@item directory-files
This should be a function with the same interface as
articles will be moved to the specified group during expiry before
being deleted. @emph{If this is set to an nnmaildir group, the
article will be just as old in the destination group as it was in the
-source group.} So be careful with @code{expire-age} in the destination
-group.
+source group.} So be careful with @code{expire-age} in the
+destination group. If this is set to the name of the same group that
+the parameter belongs to, then the article is not expired at all. If
+you use the vector form, the first element is evaluated once for each
+article. So that form can refer to
+@code{nnmaildir-article-file-name}, etc., to decide where to put the
+article. @emph{If this parameter is not set, nnmaildir does not fall
+back to the @code{expiry-target} group parameter or the
+@code{nnmail-expiry-target} variable.}
@item read-only
If this is set to @code{t}, nnmaildir will treat the articles in this
group to find articles. The default is the function specified by the
server's @code{directory-files} parameter.
+@item distrust-Lines:
+If non-@code{nil}, nnmaildir will always count the lines of an
+article, rather than use the @code{Lines:} header field. If
+@code{nil}, the header field will be used if present.
+
@item always-marks
A list of mark symbols, such as
@code{['(read expire)]}. Whenever Gnus asks nnmaildir for
@item nnmaildir
+For configuring expiry and other things, @code{nnmaildir} uses
+incompatible group parameters, slightly different from those of other
+mail back ends.
+
@code{nnmaildir} is largely similar to @code{nnml}, with some notable
differences. Each message is stored in a separate file, but the
filename is unrelated to the article number in Gnus. @code{nnmaildir}
thus damaging message bodies), and another set to be used as groups (in
whatever format you like). A maildir has a built-in spool, in the
@code{new/} subdirectory. Beware that currently, mail moved from
-@code{new/} to @code{cur/} instead of via mail splitting will undergo
-treatment such as duplicate checking.
-
-An article will not necessarily keep the same number across Gnus
-sessions; articles are renumbered starting from 1 for each Gnus session
-(more precisely, each time you open the @code{nnmaildir} server). This
-way, you don't get gaps in your article number ranges, and when entering
-large groups, Gnus is likely to give a more accurate article count. The
-price is that @code{nnmaildir} doesn't work with the cache or agent.
-This will probably be changed in the future.
+@code{new/} to @code{cur/} instead of via mail splitting will not
+undergo treatment such as duplicate checking.
@code{nnmaildir} stores article marks for a given group in the
corresponding maildir, in a way designed so that it's easy to manipulate
it's not as easy to work with them from outside Gnus as with
@code{nnmaildir}.
-For configuring expiry and other things, @code{nnmaildir} uses group
-parameters slightly different from those of other mail back ends.
-
@code{nnmaildir} uses a significant amount of memory to speed things up.
(It keeps in memory some of the things that @code{nnml} stores in files
and that @code{nnmh} repeatedly parses out of message files.) If this
is a problem for you, you can set the @code{nov-cache-size} group
parameter to something small (0 would probably not work, but 1 probably
-would) to make it use less memory.
+would) to make it use less memory. This caching will probably be
+removed in the future.
-Startup and shutdown are likely to be slower with @code{nnmaildir} than
-with other back ends. Everything in between is likely to be faster,
-depending in part on your file system.
+Startup is likely to be slower with @code{nnmaildir} than with other
+back ends. Everything else is likely to be faster, depending in part
+on your file system.
@code{nnmaildir} does not use @code{nnoo}, so you cannot use @code{nnoo}
to write an @code{nnmaildir}-derived back end.
usage explained in this section.
A server configuration in @file{~/.gnus} with a few @sc{imap} servers
-might look something like the following. (Note that for SSL/TLS, you
+might look something like the following. (Note that for TLS/SSL, you
need external programs and libraries, see below.)
@lisp
@item nnimap-server-port
@vindex nnimap-server-port
-Port on server to contact. Defaults to port 143, or 993 for SSL.
+Port on server to contact. Defaults to port 143, or 993 for TLS/SSL.
Note that this should be an integer, example server specification:
@vindex nnimap-stream
The type of stream used to connect to your server. By default, nnimap
will detect and automatically use all of the below, with the exception
-of SSL/TLS. (@sc{imap} over SSL/TLS is being replaced by STARTTLS, which
+of TLS/SSL. (@sc{imap} over TLS/SSL is being replaced by STARTTLS, which
can be automatically detected, but it's not widely deployed yet.)
Example server specification:
@itemize @bullet
@item
@dfn{gssapi:} Connect with GSSAPI (usually Kerberos 5). Requires the
-@samp{imtest} program.
+@samp{gsasl} or @samp{imtest} program.
@item
@dfn{kerberos4:} Connect with Kerberos 4. Requires the @samp{imtest} program.
@item
@dfn{starttls:} Connect via the STARTTLS extension (similar to
-SSL). Requires the external library @samp{starttls.el} and program
+TLS/SSL). Requires the external library @samp{starttls.el} and program
@samp{starttls}.
@item
+@dfn{tls:} Connect through TLS. Requires GNUTLS (the program
+@samp{gnutls-cli}).
+@item
@dfn{ssl:} Connect through SSL. Requires OpenSSL (the program
@samp{openssl}) or SSLeay (@samp{s_client}).
@item
@code{imap-kerberos4-program} contain parameters to pass to the imtest
program.
+For TLS connection, the @code{gnutls-cli} program from GNUTLS is
+needed. It is available from
+@uref{http://www.gnu.org/software/gnutls/}.
+
+@vindex imap-gssapi-program
+This parameter specifies a list of command lines that invoke a GSSAPI
+authenticated IMAP stream in a subshell. They are tried sequentially
+until a connection is made, or the list has been exhausted. By
+default, @samp{gsasl} from GNU SASL, available from
+@uref{http://www.gnu.org/software/gsasl/}, and the @samp{imtest}
+program from Cyrus IMAPD (see @code{imap-kerberos4-program}), are
+tried.
+
@vindex imap-ssl-program
For SSL connections, the OpenSSL program is available from
@uref{http://www.openssl.org/}. OpenSSL was formerly known as SSLeay,
@itemize @bullet
@item
@dfn{gssapi:} GSSAPI (usually kerberos 5) authentication. Requires
-external program @code{imtest}.
+external program @code{gsasl} or @code{imtest}.
@item
@dfn{kerberos4:} Kerberos 4 authentication. Requires external program
@code{imtest}.
@code{gnus-secondary-select-methods} are agentized.
@item
-Decide on download policy. @xref{Agent Categories}.
+
+Decide on download policy. It's fairly simple once you decide whether
+you are going to use agent categories, topic parameters, and/or group
+parameters to implement your policy. If you're new to gnus, it
+is probably best to start with a category @xref{Agent Categories}.
+
+Both topic parameters (@pxref{Topic Parameters}) and agent categories
+(@pxref{Agent Categories}) provide for setting a policy that applies
+to multiple groups. Which you use is entirely up to you. Topic
+parameters do override categories so, if you mix the two, you'll have
+to take that into account. If you have a few groups that deviate from
+your policy, you can use grou parameters (@pxref{Group Parameters}) to
+configure them.
@item
Uhm@dots{} that's it.
mark the articles for downloading manually if it should turn out that
you're interested in the articles anyway.
-The main way to control what is to be downloaded is to create a
-@dfn{category} and then assign some (or all) groups to this category.
-Groups that do not belong in any other category belong to the
-@code{default} category. Gnus has its own buffer for creating and
-managing categories.
+One of the more effective methods for controlling what is to be
+downloaded is to create a @dfn{category} and then assign some (or all)
+groups to this category. Groups that do not belong in any other
+category belong to the @code{default} category. Gnus has its own
+buffer for creating and managing categories.
+
+If you prefer, you can also use group parameters (@pxref{Group
+Parameters}) and topic parameters (@pxref{Topic Parameters}) for an
+alternative approach to controlling the agent. The only real
+difference is that categories are specific to the agent (so there is
+less to learn) while group and topic parameters include the kitchen
+sink.
+
+Since you can set agent parameters in several different places we have
+a rule to decide which source to believe. This rule specifies that
+the parameter sources are checked in the following order: group
+parameters, topic parameters, agent category, and finally customizable
+variables. So you can mix all of these sources to produce a wide range
+of behavior, just don't blame me if you don't remember where you put
+your settings.
@menu
* Category Syntax:: What a category looks like.
@node Category Syntax
@subsubsection Category Syntax
-A category consists of two things.
+A category consists of a name, the list of groups belonging to the
+category, and a number of optional parameters that override the
+customizable variables. The complete list of agent parameters are
+listed below.
-@enumerate
-@item
+@table @code
+@item gnus-agent-cat-name
+The name of the category.
+
+@item gnus-agent-cat-groups
+The list of groups that are in this category.
+
+@item gnus-agent-cat-predicate
A predicate which (generally) gives a rough outline of which articles
are eligible for downloading; and
-@item
+@item gnus-agent-cat-score-file
a score rule which (generally) gives you a finer granularity when
deciding what articles to download. (Note that this @dfn{download
score} is not necessarily related to normal scores.)
-@end enumerate
+
+@item gnus-agent-cat-enable-expiration
+a boolean indicating whether the agent should expire old articles in
+this group. Most groups should be expired to conserve disk space. In
+fact, its probably safe to say that the gnus.* hierarchy contains the
+only groups that should not be expired.
+
+@item gnus-agent-cat-days-until-old
+an integer indicating the number of days that the agent should wait
+before deciding that a read article is safe to expire.
+
+@item gnus-agent-cat-low-score
+an integer that overrides the value of @code{gnus-agent-low-score}.
+
+@item gnus-agent-cat-high-score
+an integer that overrides the value of @code{gnus-agent-high-score}.
+
+@item gnus-agent-cat-length-when-short
+an integer that overrides the value of
+@code{gnus-agent-short-article}.
+
+@item gnus-agent-cat-length-when-long
+an integer that overrides the value of @code{gnus-agent-long-article}.
+@end table
+
+The name of a category can not be changed once the category has been
+created.
+
+Each category maintains a list of groups that are exclusive members of
+that category. The exclusivity rule is automatically enforced, add a
+group to a new category and it is automatically removed from its old
+category.
A predicate in its simplest form can be a single predicate such as
@code{true} or @code{false}. These two will download every available
The following predicates are pre-defined, but if none of these fit what
you want to do, you can write your own.
+When evaluating each of these predicates, the named constant will be
+bound to the value determined by calling
+@code{gnus-agent-find-parameter} on the appropriate parameter. For
+example, gnus-agent-short-article will be bound to
+@code{(gnus-agent-find-parameter group 'agent-short-article)}. This
+means that you can specify a predicate in your category then tune that
+predicate to individual groups.
+
@table @code
@item short
True iff the article is shorter than @code{gnus-agent-short-article}
(agent-predicate . short)
@end lisp
-This is the group parameter equivalent of the agent category default.
+This is the group/topic parameter equivalent of the agent category default.
Note that when specifying a single word predicate like this, the
@code{agent-predicate} specification must be in dotted pair notation.
@end lisp
@item
-Group Parameter specification
+Group/Topic Parameter specification
@lisp
(agent-score ("from"
@findex gnus-category-exit
Return to the group buffer (@code{gnus-category-exit}).
+@item e
+@kindex e (Category)
+@findex gnus-category-customize-category
+Use a customization buffer to set all of the selected category's
+parameters at one time (@code{gnus-category-customize-category}).
+
@item k
@kindex k (Category)
@findex gnus-category-kill
Articles that have a score higher than this have a high score. Default
0.
+@item gnus-agent-expire-days
+@vindex gnus-agent-expire-days
+The number of days that a @samp{read} article must stay in the agent's
+local disk before becoming eligible for expiration (While the name is
+the same, this doesn't mean expiring the article on the server. It
+just means deleting the local copy of the article). What is also
+important to understand is that the counter starts with the time the
+article was written to the local disk and not the time the article was
+read.
+Default 7.
+
+@item gnus-agent-enable-expiration
+@vindex gnus-agent-enable-expiration
+Determines whether articles in a group are, by default, expired or
+retained indefinitely. The default is @code{ENABLE} which means that
+you'll have to disable expiration when desired. On the other hand,
+you could set this to @code{DISABLE}. In that case, you would then
+have to enable expiration in selected groups.
+
@end table
article into the Agent, Gnus will not download the article from the
server again but use the locally stored copy instead.
-This behaviour can be controlled by @code{gnus-agent-cache}
-(@pxref{Agent Variables}).
+If you so desire, you can configure the agent (see @code{gnus-agent-cache}
+@pxref{Agent Variables}) to always download headers and articles while
+plugged. Gnus will almost certainly be slower, but it will be kept
+synchronized with the server. That last point probably won't make any
+sense if you are using a nntp or nnimap backend.
@node Agent Expiry
@subsection Agent Expiry
@vindex gnus-agent-expire-days
@findex gnus-agent-expire
@kindex M-x gnus-agent-expire
+@kindex M-x gnus-agent-expire-group
+@findex gnus-agent-expire-group
@cindex Agent expiry
@cindex Gnus Agent expiry
@cindex expiry
-@code{nnagent} doesn't handle expiry. Instead, there's a special
-@code{gnus-agent-expire} command that will expire all read articles that
-are older than @code{gnus-agent-expire-days} days. It can be run
-whenever you feel that you're running out of space. It's not
-particularly fast or efficient, and it's not a particularly good idea to
-interrupt it (with @kbd{C-g} or anything else) once you've started it.
+The Agent backend, @code{nnagent}, doesn't handle expiry. Well, at
+least it doesn't handle it like other backends. Instead, there are
+special @code{gnus-agent-expire} and @code{gnus-agent-expire-group}
+commands that will expire all read articles that are older than
+@code{gnus-agent-expire-days} days. They can be run whenever you feel
+that you're running out of space. Neither are particularly fast or
+efficient, and it's not a particularly good idea to interrupt them (with
+@kbd{C-g} or anything else) once you've started one of them.
Note that other functions, e.g. @code{gnus-request-expire-articles},
might run @code{gnus-agent-expire} for you to keep the agent
synchronized with the group.
-@code{gnus-agent-expire-days} can also be a list of regexp/day pairs.
-The regexps will be matched against group names to allow differing
-expiry in different groups.
-
-@lisp
-(setq gnus-agent-expire-days
- '(("alt\\." 7)
- (".*binary" 1)
- ("." 21)))
-@end lisp
-
-If you use the list form, the last element must always be the default
-method---it must always match all groups. Also, for a regexp to match,
-it must match from the beginning of the group's name.
+The agent parameter @code{agent-enable-expiration} may be used to
+prevent expiration in selected groups.
@vindex gnus-agent-expire-all
-If @code{gnus-agent-expire-all} is non-@code{nil}, this command will
-expire all articles---unread, read, ticked and dormant. If @code{nil}
-(which is the default), only read articles are eligible for expiry, and
-unread, ticked and dormant articles will be kept indefinitely.
+If @code{gnus-agent-expire-all} is non-@code{nil}, the agent
+expiration commands will expire all articles---unread, read, ticked
+and dormant. If @code{nil} (which is the default), only read articles
+are eligible for expiry, and unread, ticked and dormant articles will
+be kept indefinitely.
If you find that some articles eligible for expiry are never expired,
-perhaps some Gnus Agent files are corrupted. There's a special
-@code{gnus-agent-regenerate} command to fix possible problems.
+perhaps some Gnus Agent files are corrupted. There's are special
+commands, @code{gnus-agent-regenerate} and
+@code{gnus-agent-regenerate-group}, to fix possible problems.
@node Agent Regeneration
@subsection Agent Regeneration
For example, if your connection to your server is lost while
downloaded articles into the agent, the local data structures will not
-know about articles downloaded prior to the connection failure.
-Running @code{gnus-agent-regenerate} or
+know about articles successfully downloaded prior to the connection
+failure. Running @code{gnus-agent-regenerate} or
@code{gnus-agent-regenerate-group} will update the data structures
such that you don't need to download these articles a second time.
@item gnus-agent-fetched-hook
@vindex gnus-agent-fetched-hook
-Hook run when after finishing fetching articles.
+Hook run when finished fetching articles.
@item gnus-agent-cache
@vindex gnus-agent-cache
@item gnus-agent-mark-unread-after-downloaded
@vindex gnus-agent-mark-unread-after-downloaded
If @code{gnus-agent-mark-unread-after-downloaded} is non-@code{nil},
-mark articles as unread after downloading. The default is t.
+mark articles as unread after downloading. This is usually a safe
+thing to do as the newly downloaded article has obviously not been
+read. The default is t.
@item gnus-agent-consider-all-articles
@vindex gnus-agent-consider-all-articles
connection be lost while fetching (You may need to run
@code{gnus-agent-regenerate-group} to update the group's state.
However, all articles parsed prior to loosing the connection will be
-available while unplugged).
+available while unplugged). The default is 10M so it is unusual to
+see any cycling.
@item gnus-server-unopen-status
@vindex gnus-server-unopen-status
for this variable include @code{denied} and @code{offline} the latter
is only valid if the Agent is used.
+@item gnus-auto-goto-ignores
+@vindex gnus-auto-goto-ignores
+Another variable that isn't a Agent variable, yet so closely related
+that most will look for it here, this variable tells the summary
+buffer how to maneuver around undownloaded (only headers stored in the
+agent) and unfetched (neither article nor headers stored) articles.
+
+The legal values are @code{nil} (maneuver to any article),
+@code{undownloaded} (maneuvering while unplugged ignores articles that
+have not been fetched), @code{always-undownloaded} (maneuvering always
+ignores articles that have not been fetched), @code{unfetched}
+(maneuvering ignores articles whose headers have not been fetched).
+
@end table
@code{gnus-agent-fetch-selected-article} to
@code{gnus-select-article-hook}.
-@item If I read an article while plugged, and the article already exists in the Agent, will it get downloaded once more?
+@item If I read an article while plugged, and the article already exists in
+the Agent, will it get downloaded once more?
@strong{No}, unless @code{gnus-agent-cache} is @code{nil}.
will be applied to each article.
To take @code{gnus-del-mark} as an example---this alist says that all
-articles that have that mark (i.e., are marked with @samp{D}) will have a
+articles that have that mark (i.e., are marked with @samp{e}) will have a
score entry added to lower based on the @code{From} header by -4, and
lowered by @code{Subject} by -1. Change this to fit your prejudices.
@samp{hello} mouse-highlighted with @code{gnus-mouse-face-3}.
Text inside the @samp{%<<} and @samp{%>>} specifiers will get the
-special @code{balloon-help} property set to @code{gnus-balloon-face-0}.
-If you say @samp{%1<<}, you'll get @code{gnus-balloon-face-1} and so on.
-The @code{gnus-balloon-face-*} variables should be either strings or
-symbols naming functions that return a string. When the mouse passes
-over text with this property set, a balloon window will appear and
-display the string. Please refer to @ref{(emacs)Help Echo} (in GNU
-Emacs) or the doc string of @code{balloon-help-mode} (in XEmacs) for
-more information on this. (For technical reasons, the guillemets have
-been approximated as @samp{<<} and @samp{>>} in this paragraph.)
+special @code{balloon-help} property set to
+@code{gnus-balloon-face-0}. If you say @samp{%1<<}, you'll get
+@code{gnus-balloon-face-1} and so on. The @code{gnus-balloon-face-*}
+variables should be either strings or symbols naming functions that
+return a string. When the mouse passes over text with this property
+set, a balloon window will appear and display the string. Please
+refer to @ref{Tooltips, ,Tooltips, emacs, The Emacs Manual},
+(in GNU Emacs) or the doc string of @code{balloon-help-mode} (in
+XEmacs) for more information on this. (For technical reasons, the
+guillemets have been approximated as @samp{<<} and @samp{>>} in this
+paragraph.)
Here's an alternative recipe for the group buffer:
@cindex slow
Sometimes, a problem do not directly generate a elisp error but
manifests itself by causing Gnus to be very slow. In these cases, you
-can use @kbd{M-x toggle-debug-on-quit} and press @kbd{C-j} when things are
+can use @kbd{M-x toggle-debug-on-quit} and press @kbd{C-g} when things are
slow, and then try to analyze the backtrace (repeating the procedure
helps isolating the real problem areas). A fancier approach is to use
the elisp profiler, ELP. The profiler is (or should be) fully
(Info-split))
(save-buffer)))
+(eval-and-compile
+ (when (string-match "windows-nt\\|os/2\\|emx\\|cygwin"
+ (symbol-name system-type))
+ (defun subst-char-in-region (START END FROMCHAR TOCHAR &optional NOUNDO)
+ "From START to END, replace FROMCHAR with TOCHAR each time it occurs.
+If optional arg NOUNDO is non-nil, don't record this change for undo
+and don't mark the buffer as really changed.
+Both characters must have the same length of multi-byte form."
+ (let ((original-buffer-undo-list buffer-undo-list)
+ (modified (buffer-modified-p)))
+ (if NOUNDO
+ (setq buffer-undo-list t))
+ (goto-char START)
+ (let ((from (char-to-string FROMCHAR))
+ (to (char-to-string TOCHAR)))
+ (while (search-forward from END t)
+ (replace-match to t t)))
+ (if NOUNDO
+ (progn (setq buffer-undo-list original-buffer-undo-list)
+ (set-buffer-modidifed-p modified)))))))
+
(defun batch-makeinfo ()
"Emacs makeinfo in batch mode."
(infohack (car command-line-args-left))
There is a pre-defined function in Gnus that is a good candidate for
this variable. @code{gnus-find-subscribed-addresses} is a function
that returns a list of addresses corresponding to the groups that have
-the @code{subscribed} (@pxref{(gnus)subscribed})
-group parameter set to a non-nil value. This is how you would do it.
+the @code{subscribed} (@pxref{Group Parameters, ,Group Parameters,
+gnus, The Gnus Manual}) group parameter set to a non-nil value. This
+is how you would do it.
@lisp
(setq message-subscribed-address-functions
* Movement:: Moving around in message buffers.
* Insertion:: Inserting things into message buffers.
* MIME:: @sc{mime} considerations.
+* IDNA:: Non-ASCII domain name considerations.
* Security:: Signing and encrypting messages.
* Various Commands:: Various things.
* Sending:: Actually sending the message.
language (@pxref{Composing, , Composing, emacs-mime, The Emacs MIME
Manual}).
+@node IDNA
+@section IDNA
+@cindex IDNA
+@cindex internationalized domain names
+@cindex non-ascii domain names
+
+Message is a @sc{idna}-compliant posting agent. The user generally
+doesn't have to do anything to make the @sc{idna} happen---Message
+will encode non-ASCII domain names in @code{From}, @code{To}, and
+@code{Cc} headers automatically.
+
+Until IDNA becomes more well known, Message queries you whether IDNA
+encoding of the domain name really should occur. Some users might not
+be aware that domain names can contain non-ASCII now, so this gives
+them a safety net if they accidently typed a non-ASCII domain name.
+
+@vindex message-use-idna
+The @code{message-use-idna} variable control whether @sc{idna} is
+used. If the variable is @sc{nil} no IDNA encoding will ever happen,
+if it is set to the symbol @sc{ask} the user will be queried (the
+default), and if set to @sc{t} IDNA encoding happens automatically.
+
+@findex message-idna-to-ascii-rhs
+If you want to experiment with the IDNA encoding, you can invoke
+@kbd{M-x message-idna-to-ascii-rhs RET} in the message buffer to have
+the non-ASCII domain names encoded while you edit the message.
+
+Note that you must have GNU Libidn
+(@url{http://www.gnu.org/software/libidn/} installed in order to use
+this functionality.
+
@node Security
@section Security
@cindex Security