diff options
| author | Kenichi Handa | 2004-03-04 23:33:44 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2004-03-04 23:33:44 +0000 |
| commit | 608aa380cffd0645d9ea99abae420ea82a601e5e (patch) | |
| tree | c6d3acab838f112388176890e7697255ffb064d9 | |
| parent | 9fb9a1b555501db302a77a4860b223922d1dded4 (diff) | |
| download | emacs-608aa380cffd0645d9ea99abae420ea82a601e5e.tar.gz emacs-608aa380cffd0645d9ea99abae420ea82a601e5e.zip | |
Sync to HEAD.
| -rw-r--r-- | lisp/mail/rmail.el | 239 |
1 files changed, 176 insertions, 63 deletions
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index deb043ffba9..4090749d83e 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs | 1 | ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1985,86,87,88,93,94,95,96,97,98,2000, 2001 | 3 | ;; Copyright (C) 1985,86,87,88,93,94,95,96,97,98,2000, 01, 2004 |
| 4 | ;; Free Software Foundation, Inc. | 4 | ;; Free Software Foundation, Inc. |
| 5 | 5 | ||
| 6 | ;; Maintainer: FSF | 6 | ;; Maintainer: FSF |
| @@ -139,9 +139,9 @@ plus whatever is specified by `rmail-default-dont-reply-to-names'." | |||
| 139 | :group 'rmail-reply) | 139 | :group 'rmail-reply) |
| 140 | 140 | ||
| 141 | ;;;###autoload | 141 | ;;;###autoload |
| 142 | (defvar rmail-default-dont-reply-to-names "info-" "\ | 142 | (defvar rmail-default-dont-reply-to-names "\\`info-" "\ |
| 143 | A regular expression specifying part of the value of the default value of | 143 | A regular expression specifying part of the default value of the |
| 144 | the variable `rmail-dont-reply-to-names', for when the user does not set | 144 | variable `rmail-dont-reply-to-names', for when the user does not set |
| 145 | `rmail-dont-reply-to-names' explicitly. (The other part of the default | 145 | `rmail-dont-reply-to-names' explicitly. (The other part of the default |
| 146 | value is the user's email address and name.) | 146 | value is the user's email address and name.) |
| 147 | It is useful to set this variable in the site customization file.") | 147 | It is useful to set this variable in the site customization file.") |
| @@ -1364,6 +1364,7 @@ It returns t if it got any new messages." | |||
| 1364 | (while all-files | 1364 | (while all-files |
| 1365 | (let ((opoint (point)) | 1365 | (let ((opoint (point)) |
| 1366 | (new-messages 0) | 1366 | (new-messages 0) |
| 1367 | (rsf-number-of-spam 0) | ||
| 1367 | (delete-files ()) | 1368 | (delete-files ()) |
| 1368 | ;; If buffer has not changed yet, and has not been saved yet, | 1369 | ;; If buffer has not changed yet, and has not been saved yet, |
| 1369 | ;; don't replace the old backup file now. | 1370 | ;; don't replace the old backup file now. |
| @@ -1446,11 +1447,62 @@ It returns t if it got any new messages." | |||
| 1446 | (progn (goto-char opoint) | 1447 | (progn (goto-char opoint) |
| 1447 | (if (or file-name rmail-inbox-list) | 1448 | (if (or file-name rmail-inbox-list) |
| 1448 | (message "(No new mail has arrived)"))) | 1449 | (message "(No new mail has arrived)"))) |
| 1449 | (if (rmail-summary-exists) | 1450 | ;; check new messages to see if any of them is spam: |
| 1451 | (if (and (featurep 'rmail-spam-filter) | ||
| 1452 | rmail-use-spam-filter) | ||
| 1453 | (let* | ||
| 1454 | ((old-messages (- rmail-total-messages new-messages)) | ||
| 1455 | (rsf-scanned-message-number (1+ old-messages)) | ||
| 1456 | ;; save deletion flags of old messages: vector starts | ||
| 1457 | ;; at zero (is one longer that no of messages), | ||
| 1458 | ;; therefore take 1+ old-messages | ||
| 1459 | (save-deleted | ||
| 1460 | (substring rmail-deleted-vector 0 (1+ | ||
| 1461 | old-messages)))) | ||
| 1462 | ;; set all messages to undeleted | ||
| 1463 | (setq rmail-deleted-vector | ||
| 1464 | (make-string (1+ rmail-total-messages) ?\ )) | ||
| 1465 | (while (<= rsf-scanned-message-number | ||
| 1466 | rmail-total-messages) | ||
| 1467 | (progn | ||
| 1468 | (if (not (rmail-spam-filter rsf-scanned-message-number)) | ||
| 1469 | (progn (setq rsf-number-of-spam (1+ rsf-number-of-spam))) | ||
| 1470 | ) | ||
| 1471 | (setq rsf-scanned-message-number (1+ rsf-scanned-message-number)) | ||
| 1472 | )) | ||
| 1473 | (if (> rsf-number-of-spam 0) | ||
| 1474 | (progn | ||
| 1475 | (when (rmail-expunge-confirmed) | ||
| 1476 | (rmail-only-expunge t)) | ||
| 1477 | )) | ||
| 1478 | (setq rmail-deleted-vector | ||
| 1479 | (concat | ||
| 1480 | save-deleted | ||
| 1481 | (make-string (- rmail-total-messages old-messages) | ||
| 1482 | ?\ ))) | ||
| 1483 | )) | ||
| 1484 | (if (rmail-summary-exists) | ||
| 1450 | (rmail-select-summary | 1485 | (rmail-select-summary |
| 1451 | (rmail-update-summary))) | 1486 | (rmail-update-summary))) |
| 1452 | (message "%d new message%s read" | 1487 | (message "%d new message%s read%s" |
| 1453 | new-messages (if (= 1 new-messages) "" "s")) | 1488 | new-messages (if (= 1 new-messages) "" "s") |
| 1489 | ;; print out a message on number of spam messages found: | ||
| 1490 | (if (and (featurep 'rmail-spam-filter) | ||
| 1491 | rmail-use-spam-filter | ||
| 1492 | (> rsf-number-of-spam 0)) | ||
| 1493 | (if (= 1 new-messages) | ||
| 1494 | ", and found to be a spam message" | ||
| 1495 | (if (> rsf-number-of-spam 1) | ||
| 1496 | (format ", %d of which found to be spam messages" | ||
| 1497 | rsf-number-of-spam) | ||
| 1498 | ", one of which found to be a spam message")) | ||
| 1499 | "")) | ||
| 1500 | (if (and (featurep 'rmail-spam-filter) | ||
| 1501 | rmail-use-spam-filter | ||
| 1502 | (> rsf-number-of-spam 0)) | ||
| 1503 | (progn (if rmail-spam-filter-beep (beep t)) | ||
| 1504 | (sleep-for rmail-spam-sleep-after-message))) | ||
| 1505 | |||
| 1454 | ;; Move to the first new message | 1506 | ;; Move to the first new message |
| 1455 | ;; unless we have other unseen messages before it. | 1507 | ;; unless we have other unseen messages before it. |
| 1456 | (rmail-show-message (rmail-first-unseen-message)) | 1508 | (rmail-show-message (rmail-first-unseen-message)) |
| @@ -1652,12 +1704,73 @@ It returns t if it got any new messages." | |||
| 1652 | (save-excursion | 1704 | (save-excursion |
| 1653 | (skip-chars-forward " \t\n") | 1705 | (skip-chars-forward " \t\n") |
| 1654 | (point))) | 1706 | (point))) |
| 1655 | (setq last-coding-system-used nil) | 1707 | (save-excursion |
| 1656 | (or rmail-enable-mime | 1708 | (let* ((header-end |
| 1657 | (not rmail-enable-multibyte) | 1709 | (progn |
| 1658 | (decode-coding-region start (point) | 1710 | (save-excursion |
| 1659 | (or rmail-file-coding-system | 1711 | (goto-char start) |
| 1660 | 'undecided))) | 1712 | (forward-line 1) |
| 1713 | (if (looking-at "0") | ||
| 1714 | (forward-line 1) | ||
| 1715 | (forward-line 2)) | ||
| 1716 | (save-restriction | ||
| 1717 | (narrow-to-region (point) (point-max)) | ||
| 1718 | (rfc822-goto-eoh) | ||
| 1719 | (point))))) | ||
| 1720 | (case-fold-search t) | ||
| 1721 | (quoted-printable-header-field-end | ||
| 1722 | (save-excursion | ||
| 1723 | (goto-char start) | ||
| 1724 | (re-search-forward | ||
| 1725 | "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*" | ||
| 1726 | header-end t))) | ||
| 1727 | (base64-header-field-end | ||
| 1728 | (save-excursion | ||
| 1729 | (goto-char start) | ||
| 1730 | (re-search-forward | ||
| 1731 | "^content-transfer-encoding:\\(\n?[\t ]\\)*base64\\(\n?[\t ]\\)*" | ||
| 1732 | header-end t)))) | ||
| 1733 | (if quoted-printable-header-field-end | ||
| 1734 | (save-excursion | ||
| 1735 | (unless | ||
| 1736 | (mail-unquote-printable-region header-end (point) nil t) | ||
| 1737 | (message "Malformed MIME quoted-printable message")) | ||
| 1738 | ;; Change "quoted-printable" to "8bit", | ||
| 1739 | ;; to reflect the decoding we just did. | ||
| 1740 | (goto-char quoted-printable-header-field-end) | ||
| 1741 | (delete-region (point) (search-backward ":")) | ||
| 1742 | (insert ": 8bit"))) | ||
| 1743 | (if base64-header-field-end | ||
| 1744 | (save-excursion | ||
| 1745 | (when | ||
| 1746 | (condition-case nil | ||
| 1747 | (progn | ||
| 1748 | (base64-decode-region (1+ header-end) | ||
| 1749 | (- (point) 2)) | ||
| 1750 | t) | ||
| 1751 | (error nil)) | ||
| 1752 | ;; Change "base64" to "8bit", to reflect the | ||
| 1753 | ;; decoding we just did. | ||
| 1754 | (goto-char (1+ header-end)) | ||
| 1755 | (while (search-forward "\r\n" (point-max) t) | ||
| 1756 | (replace-match "\n")) | ||
| 1757 | (goto-char base64-header-field-end) | ||
| 1758 | (delete-region (point) (search-backward ":")) | ||
| 1759 | (insert ": 8bit")))) | ||
| 1760 | (setq last-coding-system-used nil) | ||
| 1761 | (or rmail-enable-mime | ||
| 1762 | (not rmail-enable-multibyte) | ||
| 1763 | (let ((mime-charset | ||
| 1764 | (if (and rmail-decode-mime-charset | ||
| 1765 | (save-excursion | ||
| 1766 | (goto-char start) | ||
| 1767 | (search-forward "\n\n" nil t) | ||
| 1768 | (let ((case-fold-search t)) | ||
| 1769 | (re-search-backward | ||
| 1770 | rmail-mime-charset-pattern | ||
| 1771 | start t)))) | ||
| 1772 | (intern (downcase (match-string 1)))))) | ||
| 1773 | (rmail-decode-region start (point) mime-charset))))) | ||
| 1661 | ;; Add an X-Coding-System: header if we don't have one. | 1774 | ;; Add an X-Coding-System: header if we don't have one. |
| 1662 | (save-excursion | 1775 | (save-excursion |
| 1663 | (goto-char start) | 1776 | (goto-char start) |
| @@ -1673,7 +1786,9 @@ It returns t if it got any new messages." | |||
| 1673 | (insert "X-Coding-System: " | 1786 | (insert "X-Coding-System: " |
| 1674 | (symbol-name last-coding-system-used) | 1787 | (symbol-name last-coding-system-used) |
| 1675 | "\n"))) | 1788 | "\n"))) |
| 1676 | (narrow-to-region (point) (point-max))) | 1789 | (narrow-to-region (point) (point-max)) |
| 1790 | (and (= 0 (% count 10)) | ||
| 1791 | (message "Converting to Babyl format...%d" count))) | ||
| 1677 | ;;*** MMDF format | 1792 | ;;*** MMDF format |
| 1678 | ((let ((case-fold-search t)) | 1793 | ((let ((case-fold-search t)) |
| 1679 | (looking-at rmail-mmdf-delim1)) | 1794 | (looking-at rmail-mmdf-delim1)) |
| @@ -1698,7 +1813,9 @@ It returns t if it got any new messages." | |||
| 1698 | (symbol-name last-coding-system-used) | 1813 | (symbol-name last-coding-system-used) |
| 1699 | "\n")) | 1814 | "\n")) |
| 1700 | (narrow-to-region (point) (point-max)) | 1815 | (narrow-to-region (point) (point-max)) |
| 1701 | (setq count (1+ count))) | 1816 | (setq count (1+ count)) |
| 1817 | (and (= 0 (% count 10)) | ||
| 1818 | (message "Converting to Babyl format...%d" count))) | ||
| 1702 | ;;*** Mail format | 1819 | ;;*** Mail format |
| 1703 | ((looking-at "^From ") | 1820 | ((looking-at "^From ") |
| 1704 | (insert "\^L\n0, unseen,,\n*** EOOH ***\n") | 1821 | (insert "\^L\n0, unseen,,\n*** EOOH ***\n") |
| @@ -1714,6 +1831,11 @@ It returns t if it got any new messages." | |||
| 1714 | (re-search-forward | 1831 | (re-search-forward |
| 1715 | "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*" | 1832 | "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*" |
| 1716 | header-end t))) | 1833 | header-end t))) |
| 1834 | (base64-header-field-end | ||
| 1835 | (save-excursion | ||
| 1836 | (re-search-forward | ||
| 1837 | "^content-transfer-encoding:\\(\n?[\t ]\\)*base64\\(\n?[\t ]\\)*" | ||
| 1838 | header-end t))) | ||
| 1717 | (size | 1839 | (size |
| 1718 | ;; Get the numeric value from the Content-Length field. | 1840 | ;; Get the numeric value from the Content-Length field. |
| 1719 | (save-excursion | 1841 | (save-excursion |
| @@ -1757,12 +1879,37 @@ It returns t if it got any new messages." | |||
| 1757 | (setq count (1+ count)) | 1879 | (setq count (1+ count)) |
| 1758 | (if quoted-printable-header-field-end | 1880 | (if quoted-printable-header-field-end |
| 1759 | (save-excursion | 1881 | (save-excursion |
| 1760 | (rmail-decode-quoted-printable header-end (point)) | 1882 | (unless |
| 1883 | (mail-unquote-printable-region header-end (point) nil t) | ||
| 1884 | |||
| 1885 | (message "Malformed MIME quoted-printable message")) | ||
| 1761 | ;; Change "quoted-printable" to "8bit", | 1886 | ;; Change "quoted-printable" to "8bit", |
| 1762 | ;; to reflect the decoding we just did. | 1887 | ;; to reflect the decoding we just did. |
| 1763 | (goto-char quoted-printable-header-field-end) | 1888 | (goto-char quoted-printable-header-field-end) |
| 1764 | (delete-region (point) (search-backward ":")) | 1889 | (delete-region (point) (search-backward ":")) |
| 1765 | (insert ": 8bit")))) | 1890 | (insert ": 8bit"))) |
| 1891 | (if base64-header-field-end | ||
| 1892 | (save-excursion | ||
| 1893 | (when | ||
| 1894 | (condition-case nil | ||
| 1895 | (progn | ||
| 1896 | (base64-decode-region | ||
| 1897 | (1+ header-end) | ||
| 1898 | (save-excursion | ||
| 1899 | ;; Prevent base64-decode-region | ||
| 1900 | ;; from removing newline characters. | ||
| 1901 | (skip-chars-backward "\n\t ") | ||
| 1902 | (point))) | ||
| 1903 | t) | ||
| 1904 | (error nil)) | ||
| 1905 | (goto-char header-end) | ||
| 1906 | (while (search-forward "\r\n" (point-max) t) | ||
| 1907 | (replace-match "\n")) | ||
| 1908 | ;; Change "base64" to "8bit", to reflect the | ||
| 1909 | ;; decoding we just did. | ||
| 1910 | (goto-char base64-header-field-end) | ||
| 1911 | (delete-region (point) (search-backward ":")) | ||
| 1912 | (insert ": 8bit"))))) | ||
| 1766 | 1913 | ||
| 1767 | (save-excursion | 1914 | (save-excursion |
| 1768 | (save-restriction | 1915 | (save-restriction |
| @@ -1770,6 +1917,7 @@ It returns t if it got any new messages." | |||
| 1770 | (goto-char (point-min)) | 1917 | (goto-char (point-min)) |
| 1771 | (while (search-forward "\n\^_" nil t); single char | 1918 | (while (search-forward "\n\^_" nil t); single char |
| 1772 | (replace-match "\n^_")))); 2 chars: "^" and "_" | 1919 | (replace-match "\n^_")))); 2 chars: "^" and "_" |
| 1920 | (or (bolp) (newline)) ; in case we lost the final newline. | ||
| 1773 | (insert ?\^_) | 1921 | (insert ?\^_) |
| 1774 | (setq last-coding-system-used nil) | 1922 | (setq last-coding-system-used nil) |
| 1775 | (or rmail-enable-mime | 1923 | (or rmail-enable-mime |
| @@ -1791,7 +1939,9 @@ It returns t if it got any new messages." | |||
| 1791 | (insert "X-Coding-System: " | 1939 | (insert "X-Coding-System: " |
| 1792 | (symbol-name last-coding-system-used) | 1940 | (symbol-name last-coding-system-used) |
| 1793 | "\n")) | 1941 | "\n")) |
| 1794 | (narrow-to-region (point) (point-max))) | 1942 | (narrow-to-region (point) (point-max)) |
| 1943 | (and (= 0 (% count 10)) | ||
| 1944 | (message "Converting to Babyl format...%d" count))) | ||
| 1795 | ;; | 1945 | ;; |
| 1796 | ;; This kludge is because some versions of sendmail.el | 1946 | ;; This kludge is because some versions of sendmail.el |
| 1797 | ;; insert an extra newline at the beginning that shouldn't | 1947 | ;; insert an extra newline at the beginning that shouldn't |
| @@ -1801,45 +1951,6 @@ It returns t if it got any new messages." | |||
| 1801 | (t (error "Cannot convert to babyl format"))))) | 1951 | (t (error "Cannot convert to babyl format"))))) |
| 1802 | count)) | 1952 | count)) |
| 1803 | 1953 | ||
| 1804 | (defun rmail-hex-char-to-integer (character) | ||
| 1805 | "Return CHARACTER's value interpreted as a hex digit." | ||
| 1806 | (if (and (>= character ?0) (<= character ?9)) | ||
| 1807 | (- character ?0) | ||
| 1808 | (let ((ch (logior character 32))) | ||
| 1809 | (if (and (>= ch ?a) (<= ch ?f)) | ||
| 1810 | (- ch (- ?a 10)) | ||
| 1811 | (error "Invalid hex digit `%c'" ch))))) | ||
| 1812 | |||
| 1813 | (defun rmail-hex-string-to-integer (hex-string) | ||
| 1814 | "Return decimal integer for HEX-STRING." | ||
| 1815 | (let ((hex-num 0) | ||
| 1816 | (index 0)) | ||
| 1817 | (while (< index (length hex-string)) | ||
| 1818 | (setq hex-num (+ (* hex-num 16) | ||
| 1819 | (rmail-hex-char-to-integer (aref hex-string index)))) | ||
| 1820 | (setq index (1+ index))) | ||
| 1821 | hex-num)) | ||
| 1822 | |||
| 1823 | (defun rmail-decode-quoted-printable (from to) | ||
| 1824 | "Decode Quoted-Printable in the region between FROM and TO." | ||
| 1825 | (interactive "r") | ||
| 1826 | (goto-char from) | ||
| 1827 | (or (markerp to) | ||
| 1828 | (setq to (copy-marker to))) | ||
| 1829 | (while (search-forward "=" to t) | ||
| 1830 | (cond ((eq (following-char) ?\n) | ||
| 1831 | (delete-char -1) | ||
| 1832 | (delete-char 1)) | ||
| 1833 | ((looking-at "[0-9A-F][0-9A-F]") | ||
| 1834 | (let ((byte (rmail-hex-string-to-integer | ||
| 1835 | (buffer-substring (point) (+ 2 (point)))))) | ||
| 1836 | (delete-region (1- (point)) (+ 2 (point))) | ||
| 1837 | (insert byte))) | ||
| 1838 | ((looking-at "=") | ||
| 1839 | (delete-char 1)) | ||
| 1840 | (t | ||
| 1841 | (message "Malformed MIME quoted-printable message"))))) | ||
| 1842 | |||
| 1843 | ;; Delete the "From ..." line, creating various other headers with | 1954 | ;; Delete the "From ..." line, creating various other headers with |
| 1844 | ;; information from it if they don't already exist. Now puts the | 1955 | ;; information from it if they don't already exist. Now puts the |
| 1845 | ;; original line into a mail-from: header line for debugging and for | 1956 | ;; original line into a mail-from: header line for debugging and for |
| @@ -2947,7 +3058,7 @@ See also user-option `rmail-confirm-expunge'." | |||
| 2947 | (funcall rmail-confirm-expunge | 3058 | (funcall rmail-confirm-expunge |
| 2948 | "Erase deleted messages from Rmail file? "))) | 3059 | "Erase deleted messages from Rmail file? "))) |
| 2949 | 3060 | ||
| 2950 | (defun rmail-only-expunge () | 3061 | (defun rmail-only-expunge (&optional dont-show) |
| 2951 | "Actually erase all deleted messages in the file." | 3062 | "Actually erase all deleted messages in the file." |
| 2952 | (interactive) | 3063 | (interactive) |
| 2953 | (set-buffer rmail-buffer) | 3064 | (set-buffer rmail-buffer) |
| @@ -3026,11 +3137,12 @@ See also user-option `rmail-confirm-expunge'." | |||
| 3026 | (message "Expunging deleted messages...done") | 3137 | (message "Expunging deleted messages...done") |
| 3027 | (if (not win) | 3138 | (if (not win) |
| 3028 | (narrow-to-region (- (buffer-size) omin) (- (buffer-size) omax))) | 3139 | (narrow-to-region (- (buffer-size) omin) (- (buffer-size) omax))) |
| 3029 | (rmail-show-message | 3140 | (if (not dont-show) |
| 3030 | (if (zerop rmail-current-message) 1 nil)) | 3141 | (rmail-show-message |
| 3031 | (if rmail-enable-mime | 3142 | (if (zerop rmail-current-message) 1 nil) |
| 3032 | (goto-char (+ (point-min) opoint)) | 3143 | (if rmail-enable-mime |
| 3033 | (goto-char (+ (point) opoint)))))) | 3144 | (goto-char (+ (point-min) opoint)) |
| 3145 | (goto-char (+ (point) opoint)))))))) | ||
| 3034 | 3146 | ||
| 3035 | (defun rmail-expunge () | 3147 | (defun rmail-expunge () |
| 3036 | "Erase deleted messages from Rmail file and summary buffer." | 3148 | "Erase deleted messages from Rmail file and summary buffer." |
| @@ -3755,4 +3867,5 @@ encoded string (and the same mask) will decode the string." | |||
| 3755 | 3867 | ||
| 3756 | (provide 'rmail) | 3868 | (provide 'rmail) |
| 3757 | 3869 | ||
| 3870 | ;;; arch-tag: cff0a950-57fe-4f73-a86e-91ff75afd06c | ||
| 3758 | ;;; rmail.el ends here | 3871 | ;;; rmail.el ends here |