X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=tm-edit.el;h=e79cd70b65388f861a5616982ee7fd66b8303152;hb=b130d8500e514fa13ed91f7710ef8dcb09e589c9;hp=142aa450f86f9d44bb2fef453b9873f1d1629ea2;hpb=80f1943d32ac9df38fcdce6a8396e4d64b2a4e13;p=elisp%2Ftm.git diff --git a/tm-edit.el b/tm-edit.el index 142aa45..e79cd70 100644 --- a/tm-edit.el +++ b/tm-edit.el @@ -1,29 +1,31 @@ ;;; ;;; tm-edit.el --- Simple MIME Composer for GNU Emacs ;;; - -;; Copyright (C) 1993 UMEDA Masanobu -;; Copyright (C) 1994,1995 MORIOKA Tomohiko - -;; Author: UMEDA Masanobu -;; MORIOKA Tomohiko -;; Keywords: mail, news, MIME, multimedia, multilingual - -;; This file is not 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, 675 Mass Ave, Cambridge, MA 02139, USA. +;;; Copyright (C) 1993 UMEDA Masanobu +;;; Copyright (C) 1994,1995 MORIOKA Tomohiko +;;; +;;; Author: UMEDA Masanobu +;;; MORIOKA Tomohiko +;;; Maintainer: MORIOKA Tomohiko +;;; Created: 1994/08/21 renamed from mime.el +;;; Version: $Revision: 7.40 $ +;;; Keywords: mail, news, MIME, multimedia, multilingual +;;; +;;; This file is part of tm (Tools for MIME). +;;; +;;; This program 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. +;;; +;;; This program 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 This program. If not, write to the Free Software +;;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: @@ -48,7 +50,7 @@ ;; definition to load mime/editor-mode automatically: ;; ;; (autoload 'mime/editor-mode "tm-edit" -;; "Minor mode for editing MIME message." t) +;; "Minor mode for editing MIME message." t) ;; ;; In case of Mail mode (includes VM mode), you need the following ;; hook definition: @@ -104,11 +106,6 @@ ;; ;;--[[audio/basic][base64]]^M...audio encoded in base64 comes here... -;; LCD Archive Entry: -;; mime|Masanobu UMEDA|umerin@mse.kyutech.ac.jp| -;; Simple MIME Composer| -;; $Date: 1995/11/25 02:14:25 $|$Revision: 7.28 $|~/misc/mime.el.Z| - ;;; Code: (require 'sendmail) @@ -125,7 +122,7 @@ ;;; (defconst mime-editor/RCS-ID - "$Id: tm-edit.el,v 7.28 1995/11/25 02:14:25 morioka Exp $") + "$Id: tm-edit.el,v 7.40 1996/01/14 05:52:49 morioka Exp $") (defconst mime-editor/version (get-version-string mime-editor/RCS-ID)) @@ -152,19 +149,6 @@ If non-nil, the text tag is not inserted unless something different.") (defvar mime-auto-hide-body t "*Hide non-textual body encoded in base64 after insertion if non-nil.") -(defvar mime-body-charset-chooser - (cond ((boundp 'NEMACS) - (function mime-body-charset-chooser-for-nemacs)) - ((featurep 'mule) - (function mime-body-charset-chooser-for-mule)) - ((string-match "^19\\." emacs-version) - (function mime-body-charset-chooser-for-emacs19)) - (t ;ASCII only emacs - (function mime-body-charset-chooser-for-emacs18))) - "*Function to identify charset and encoding of a text in a given region. -The value is a form of (CHARSET . ENCODING), where ENCODING must be a -full name, such as base64.") - (defvar mime-string-encoder (cond ((boundp 'NEMACS) (function mime-string-encoder-for-nemacs)) @@ -235,10 +219,7 @@ To insert a signature file specified by mime-signature-file ("rfc822") ) ("application" - ("octet-stream" - ("name") - ("type" "" "tar" "shar") - ("conversions")) + ("octet-stream" ("type" "" "tar" "shar")) ("postscript") ("x-kiss" ("x-cnf"))) ("image" @@ -246,6 +227,7 @@ To insert a signature file specified by mime-signature-file ("jpeg") ("tiff") ("x-pic") + ("x-mag") ("x-xwd") ("x-xbm") ) @@ -256,44 +238,83 @@ To insert a signature file specified by mime-signature-file (defvar mime-file-types '(("\\.rtf$" - "text" "richtext" nil nil) + "text" "richtext" nil + nil + nil nil) ("\\.html$" - "text" "html" nil nil) + "text" "html" nil + nil + nil nil) ("\\.ps$" - "application" "postscript" nil "quoted-printable") - ("\\.gif$" - "image" "gif" nil "base64" - (("Content-Description" . file)) + "application" "postscript" nil + "quoted-printable" + "attachment" (("filename" . file)) ) ("\\.jpg$" - "image" "jpeg" nil "base64") - ("\\.xwd$" - "image" "x-xwd" nil "base64") - ("\\.xbm$" - "image" "x-xbm" nil "base64") - ("\\.pic$" - "image" "x-pic" nil "base64" - (("Content-Description" . file)) + "image" "jpeg" nil + "base64" + "inline" (("filename" . file)) + ) + ("\\.gif$" + "image" "gif" nil + "base64" + "inline" (("filename" . file)) ) ("\\.tiff$" - "image" "tiff" nil "base64") + "image" "tiff" nil + "base64" + "inline" (("filename" . file)) + ) + ("\\.pic$" + "image" "x-pic" nil + "base64" + "inline" (("filename" . file)) + ) + ("\\.mag$" + "image" "x-mag" nil + "base64" + "inline" (("filename" . file)) + ) + ("\\.xbm$" + "image" "x-xbm" nil + "base64" + "inline" (("filename" . file)) + ) + ("\\.xwd$" + "image" "x-xwd" nil + "base64" + "inline" (("filename" . file)) + ) ("\\.au$" - "audio" "basic" nil "base64") + "audio" "basic" nil + "base64" + "attachment" (("filename" . file)) + ) ("\\.mpg$" - "video" "mpeg" nil "base64") + "video" "mpeg" nil + "base64" + "attachment" (("filename" . file)) + ) ("\\.el$" - "application" "octet-stream" (("name" . file) - ("type" . "emacs-lisp")) "7bit") + "application" "octet-stream" (("type" . "emacs-lisp")) + "7bit" + "attachment" (("filename" . file)) + ) ("\\.lsp$" - "application" "octet-stream" (("name" . file) - ("type" . "common-lisp")) "7bit") + "application" "octet-stream" (("type" . "common-lisp")) + "7bit" + "attachment" (("filename" . file)) + ) ("\\.tar.gz$" - "application" "octet-stream" (("name" . file) - ("type" . "tar") - ("conversions" . "gzip")) nil) + "application" "octet-stream" (("type" . "tar+gzip")) + nil + "attachment" (("filename" . file)) + ) ("\\.diff$" - "application" "octet-stream" (("name" . file) - ("type" . "patch")) nil) + "application" "octet-stream" (("type" . "patch")) + nil + "attachment" (("filename" . file)) + ) ("\\.signature" "text" "plain" nil nil) (".*" nil nil nil nil) @@ -321,9 +342,11 @@ Each elements are regexp of field-name. [tm-edit.el]") ;;; @@ about message splitting ;;; -(defvar mime-editor/split-message t) +(defvar mime-editor/split-message t + "*Split large message if it is non-nil. [tm-edit.el]") -(defvar mime-editor/message-default-max-length 1000) +(defvar mime-editor/message-default-max-length 1000 + "*Default maximum size of a message. [tm-edit.el]") (defvar mime-editor/message-max-length-alist '((news-reply-mode . 500))) @@ -387,6 +410,21 @@ Each elements are regexp of field-name. [tm-edit.el]") (defvar mime-editor/news-reply-mode-server-running nil) + +;;; @@ about PGP +;;; + +(defvar mime-editor/signing-type nil + "*PGP signing type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]") + +(defvar mime-editor/encrypting-type nil + "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]") + +(if (or mime-editor/signing-type mime-editor/encrypting-type) + (require 'mailcrypt) + ) + + ;;; @@ about tag ;;; @@ -464,11 +502,14 @@ Tspecials means any character that matches with it in header must be quoted.") (define-key keymap "\C-m" 'mime-editor/insert-mail) (define-key keymap "\C-w" 'mime-editor/insert-signature) (define-key keymap "\C-s" 'mime-editor/insert-signature) + (define-key keymap "\C-k" 'mime-editor/insert-key) (define-key keymap "t" 'mime-editor/insert-tag) (define-key keymap "a" 'mime-editor/enclose-alternative-region) (define-key keymap "p" 'mime-editor/enclose-parallel-region) (define-key keymap "m" 'mime-editor/enclose-mixed-region) (define-key keymap "d" 'mime-editor/enclose-digest-region) + (define-key keymap "s" 'mime-editor/enclose-signed-region) + (define-key keymap "e" 'mime-editor/enclose-encrypted-region) (define-key keymap "\C-p" 'mime-editor/preview-message) (define-key keymap "\C-z" 'mime-editor/exit) (define-key keymap "?" 'mime-editor/help) @@ -477,22 +518,33 @@ Tspecials means any character that matches with it in header must be quoted.") (defconst mime-editor/menu-title "MIME-Edit") (defconst mime-editor/menu-list - '((mime-help "Describe MIME Mode" mime-editor/help) - (file "Insert File" mime-editor/insert-file) - (external "Insert External" mime-editor/insert-external) - (voice "Insert Voice" mime-editor/insert-voice) - (message "Insert Message" mime-editor/insert-message) - (mail "Insert Mail" mime-editor/insert-mail) - (signature "Insert Signature" mime-editor/insert-signature) - (text "Insert Text" mime-editor/insert-text) - (tag "Insert Tag" mime-editor/insert-tag) - (alternative "Enclose as alternative" - mime-editor/enclose-alternative-region) - (parallel "Enclose as parallel" mime-editor/enclose-parallel-region) - (mixed "Enclose as serial" mime-editor/enclose-mixed-region) - (digest "Enclose as digest" mime-editor/enclose-digest-region) - (preview "Preview Message" mime-editor/preview-message) - ) + (nconc + '((mime-help "Describe MIME editor mode" mime-editor/help) + (file "Insert File" mime-editor/insert-file) + (external "Insert External" mime-editor/insert-external) + (voice "Insert Voice" mime-editor/insert-voice) + (message "Insert Message" mime-editor/insert-message) + (mail "Insert Mail" mime-editor/insert-mail) + (signature "Insert Signature" mime-editor/insert-signature) + (text "Insert Text" mime-editor/insert-text) + (tag "Insert Tag" mime-editor/insert-tag) + (alternative "Enclose as alternative" + mime-editor/enclose-alternative-region) + (parallel "Enclose as parallel" mime-editor/enclose-parallel-region) + (mixed "Enclose as serial" mime-editor/enclose-mixed-region) + (digest "Enclose as digest" mime-editor/enclose-digest-region) + (signed "Enclose as signed" mime-editor/enclose-signed-region) + (encrypted "Enclose as encrypted" mime-editor/enclose-encrypted-region) + (key "Insert Public Key" mime-editor/insert-key) + (split "About split" mime-editor/set-split) + ) + (if (and (featurep 'mailcrypt) + (not (or mime-editor/signing-type mime-editor/encrypting-type))) + '((sign "About sign" mime-editor/set-sign) + (encrypt "About encryption" mime-editor/set-encrypt) + )) + '((preview "Preview Message" mime-editor/preview-message)) + ) "MIME-edit menubar entry.") (defun mime-editor/define-menu-for-emacs19 () @@ -511,7 +563,7 @@ Tspecials means any character that matches with it in header must be quoted.") )) ;;; modified by Pekka Marjola -;;; 1995/9/5 (c.f. [tm-eng:69]) +;;; 1995/9/5 (c.f. [tm-en:69]) (defun mime-editor/define-menu-for-xemacs () "Define menu for Emacs 19." (cond ((featurep 'menubar) @@ -526,6 +578,19 @@ Tspecials means any character that matches with it in header must be quoted.") )) mime-editor/menu-list))) ))) + +;;; modified by Steven L. Baur +;;; 1995/12/6 (c.f. [tm-en:209]) +(if (and (string-match "XEmacs\\|Lucid" emacs-version) + (not (boundp 'mime-editor/popup-menu-for-xemacs))) + (setq mime-editor/popup-menu-for-xemacs + (append '("MIME Commands" "---") + (mapcar (function (lambda (item) + (vector (nth 1 item) + (nth 2 item) + t))) + mime-editor/menu-list))) + ) ;;; end @@ -577,6 +642,9 @@ Following commands are available in addition to major mode commands: \\[mime-editor/enclose-parallel-region] enclose as multipart/parallel. \\[mime-editor/enclose-mixed-region] enclose as multipart/mixed. \\[mime-editor/enclose-digest-region] enclose as multipart/digest. +\\[mime-editor/enclose-signed-region] enclose as PGP signed. +\\[mime-editor/enclose-encrypted-region] enclose as PGP encrypted. +\\[mime-editor/insert-key] insert PGP public key. \\[mime-editor/preview-message] preview editing MIME message. \\[mime-editor/exit] exit and translate into a MIME compliant message. \\[mime-editor/maybe-translate] exit, translate and run the original command. @@ -623,11 +691,6 @@ User customizable variables (not documented all of them): Hide a non-textual body message encoded in base64 after insertion if non-nil. - mime-body-charset-chooser - Specifies a function to identify charset and encoding of a text in - a given region. The value is a form of (CHARSET . ENCODING), - where ENCODING must be a full name, such as base64. - mime-string-encoder Specifies a function to encode a string for given encoding method. The method is a form of (CHARSET . ENCODING). @@ -680,9 +743,11 @@ User customizable variables (not documented all of them): (setq selective-display t) ;; I don't care about saving these. (setq paragraph-start - (concat mime-editor/single-part-tag-regexp "\\|" paragraph-start)) + (regexp-or mime-editor/single-part-tag-regexp + paragraph-start)) (setq paragraph-separate - (concat mime-editor/single-part-tag-regexp "\\|" paragraph-separate)) + (regexp-or mime-editor/single-part-tag-regexp + paragraph-separate)) (run-hooks 'mime/editor-mode-hook) (message (substitute-command-keys @@ -730,7 +795,7 @@ just return to previous mode." (defun mime-editor/maybe-translate () (interactive) (mime-editor/exit nil t) - (call-interactively 'mime-editor/split-and-send) + (call-interactively 'mime-editor/maybe-split-and-send) ) (defun mime-editor/help () @@ -743,7 +808,7 @@ just return to previous mode." (defun mime-editor/insert-text () "Insert a text message. -Charset is automatically obtained from the mime-body-charset-chooser." +Charset is automatically obtained from the `mime/lc-charset-alist'." (interactive) (if (and (mime-editor/insert-tag "text" nil nil) (looking-at mime-editor/single-part-tag-regexp)) @@ -761,7 +826,8 @@ Charset is automatically obtained from the mime-body-charset-chooser." (subtype (nth 1 guess)) (parameters (nth 2 guess)) (default (nth 3 guess)) ;Guess encoding from its file name. - (fields (nth 4 guess)) + (disposition-type (nth 4 guess)) + (disposition-params (nth 5 guess)) (encoding (if (not (interactive-p)) default @@ -778,7 +844,7 @@ Charset is automatically obtained from the mime-body-charset-chooser." mime-encoding-method-alist nil t nil)))) (if (string-equal encoding "") (setq encoding default)) - (if (or (consp parameters) (consp fields)) + (if (or (consp parameters) (stringp disposition-type)) (let ((rest parameters) cell attribute value) (setq parameters "") (while rest @@ -791,17 +857,24 @@ Charset is automatically obtained from the mime-body-charset-chooser." (setq parameters (concat parameters "; " attribute "=" value)) (setq rest (cdr rest)) ) - (setq rest fields) - (while rest - (setq cell (car rest)) - (setq attribute (car cell)) - (setq value (cdr cell)) - (if (eq value 'file) - (setq value (file-name-nondirectory file)) - ) - (setq parameters (concat parameters "\n" attribute ": " value)) - (setq rest (cdr rest)) - ) + (if disposition-type + (progn + (setq parameters + (concat parameters "\n" + "Content-Disposition: " disposition-type)) + (setq rest disposition-params) + (while rest + (setq cell (car rest)) + (setq attribute (car cell)) + (setq value (cdr cell)) + (if (eq value 'file) + (setq value (file-name-nondirectory file)) + ) + (setq parameters + (concat parameters "; " attribute "=" value)) + (setq rest (cdr rest)) + ) + )) )) (mime-editor/insert-tag pritype subtype parameters) (mime-editor/insert-binary-file file encoding) @@ -1127,17 +1200,8 @@ Optional argument ENCODING specifies an encoding method such as base64." (defun mime-editor/choose-charset () "Choose charset of a text following current point." - (save-excursion - (let* ((beg (point)) - (end (mime-editor/content-end))) - (car (funcall mime-body-charset-chooser beg end))))) - -(defun mime-editor/choose-encoding () - "Choose encoding of a text following current point." - (save-excursion - (let* ((beg (point)) - (end (mime-editor/content-end))) - (cdr (funcall mime-body-charset-chooser beg end))))) + (mime/find-charset-region (point) (mime-editor/content-end)) + ) (defun mime-make-text-tag (&optional subtype) "Make a tag for a text after current point. @@ -1366,26 +1430,343 @@ while if FLAG is `\\^M' (control-M) the text is hidden." (set-buffer-modified-p modp)))) -;; Translate the tagged MIME messages into a MIME compliant message. +;;; @ Translate the tagged MIME messages into a MIME compliant message. +;;; (defun mime-editor/translate-buffer () "Encode the tagged MIME message in current buffer in MIME compliant message." (interactive) - (mime/encode-message-header) - (mime-editor/translate-body) - ) + (if (catch 'mime-editor/error + (save-excursion + (mime/encode-message-header) + (mime-editor/translate-body) + (mime-editor/pgp-processing) + )) + (progn + (undo) + (error "Translation error!") + ))) + +(defun mime-editor/find-inmost () + (goto-char (point-min)) + (if (re-search-forward mime-editor/multipart-beginning-regexp nil t) + (let ((bb (match-beginning 0)) + (be (match-end 0)) + (type (buffer-substring (match-beginning 1)(match-end 1))) + end-exp eb ee) + (setq end-exp (format "^--}-<<%s>>\n" type)) + (widen) + (if (re-search-forward end-exp nil t) + (progn + (setq eb (match-beginning 0)) + (setq ee (match-end 0)) + ) + (setq eb (point-max)) + (setq ee (point-max)) + ) + (narrow-to-region be eb) + (goto-char be) + (if (re-search-forward mime-editor/multipart-beginning-regexp nil t) + (let (ret) + (narrow-to-region (match-beginning 0)(point-max)) + (mime-editor/find-inmost) + ) + (widen) + ;;(delete-region eb ee) + (list type bb be eb) + )))) + +(defun mime-editor/process-multipart-1 (boundary) + (let ((ret (mime-editor/find-inmost))) + (if ret + (let ((type (car ret)) + (bb (nth 1 ret))(be (nth 2 ret)) + (eb (nth 3 ret)) + ) + (narrow-to-region bb eb) + (delete-region bb be) + (setq bb (point-min)) + (setq eb (point-max)) + (widen) + (goto-char eb) + (if (looking-at mime-editor/multipart-end-regexp) + (let ((beg (match-beginning 0)) + (end (match-end 0)) + ) + (delete-region beg end) + (if (and (not (looking-at mime-editor/single-part-tag-regexp)) + (not (eobp))) + (insert (concat (mime-make-text-tag) "\n")) + ))) + (cond ((string= type "signed") + (cond ((eq mime-editor/signing-type 'pgp-elkins) + (mime-editor/sign-pgp-elkins bb eb boundary) + ) + ((eq mime-editor/signing-type 'pgp-kazu) + (mime-editor/process-pgp-kazu 'mc-sign + bb eb boundary) + ) + )) + ((string= type "encrypted") + (cond ((eq mime-editor/signing-type 'pgp-elkins) + (mime-editor/encrypt-pgp-elkins bb eb boundary) + ) + ((eq mime-editor/signing-type 'pgp-kazu) + (mime-editor/process-pgp-kazu 'mc-encrypt + bb eb boundary) + ))) + (t + (setq boundary + (nth 2 (mime-editor/translate-region bb eb + boundary t))) + (goto-char bb) + (insert + (format "--[[multipart/%s; + boundary=\"%s\"][7bit]]\n" + type boundary)) + )) + boundary)))) + +(defun tm:mc-pgp-generic-parser (result) + (let ((ret (mc-pgp-generic-parser result))) + (if (consp ret) + (vector (car ret)(cdr ret)) + ))) + +(autoload 'mc-pgp-lookup-key "mc-pgp") + +(defun tm:mc-process-region + (beg end passwd program args parser &optional buffer boundary) + (let ((obuf (current-buffer)) + (process-connection-type nil) + mybuf result rgn proc) + (unwind-protect + (progn + (setq mybuf (or buffer (generate-new-buffer " *mailcrypt temp"))) + (set-buffer mybuf) + (erase-buffer) + (set-buffer obuf) + (buffer-disable-undo mybuf) + (setq proc + (apply 'start-process "*PGP*" mybuf program args)) + (if passwd + (progn + (process-send-string proc (concat passwd "\n")) + (or mc-passwd-timeout (mc-deactivate-passwd t)))) + (process-send-region proc beg end) + (process-send-eof proc) + (while (eq 'run (process-status proc)) + (accept-process-output proc 5)) + (setq result (process-exit-status proc)) + ;; Hack to force a status_notify() in Emacs 19.29 + (delete-process proc) + (set-buffer mybuf) + (goto-char (point-max)) + (if (re-search-backward "\nProcess \\*PGP.*\n\\'" nil t) + (delete-region (match-beginning 0) (match-end 0))) + (goto-char (point-min)) + ;; CRNL -> NL + (while (search-forward "\r\n" nil t) + (replace-match "\n")) + ;; Hurm. FIXME; must get better result codes. + (if (stringp result) + (error "%s exited abnormally: '%s'" program result) + (setq rgn (funcall parser result)) + ;; If the parser found something, migrate it + (if (consp rgn) + (progn + (set-buffer obuf) + (if boundary + (save-restriction + (narrow-to-region beg end) + (goto-char beg) + (insert (format "--%s\n" boundary)) + (goto-char (point-max)) + (insert (format "\n--%s +Content-Type: application/pgp-signature +Content-Transfer-Encoding: 7bit + +" boundary)) + (insert-buffer-substring mybuf (car rgn) (cdr rgn)) + (goto-char (point-max)) + (insert (format "\n--%s--\n" boundary)) + ) + (delete-region beg end) + (goto-char beg) + (insert-buffer-substring mybuf (car rgn) (cdr rgn)) + ) + (set-buffer mybuf) + (delete-region (car rgn) (cdr rgn))))) + ;; Return nil on failure and exit code on success + (if rgn result)) + ;; Cleanup even on nonlocal exit + (if (and proc (eq 'run (process-status proc))) + (interrupt-process proc)) + (set-buffer obuf) + (or buffer (null mybuf) (kill-buffer mybuf))))) + +(defun tm:mc-pgp-sign-region (start end &optional id unclear boundary) + (if (not (boundp 'mc-pgp-user-id)) + (load "mc-pgp") + ) + (let ((process-environment process-environment) + (buffer (get-buffer-create mc-buffer-name)) + passwd args key + (parser (function mc-pgp-generic-parser)) + (pgp-path mc-pgp-path) + ) + (setq key (mc-pgp-lookup-key (or id mc-pgp-user-id))) + (setq passwd + (mc-activate-passwd + (cdr key) + (format "PGP passphrase for %s (%s): " (car key) (cdr key)))) + (setenv "PGPPASSFD" "0") + (setq args + (cons + (if boundary + "-fbast" + "-fast") + (list "+verbose=1" "+language=en" + (format "+clearsig=%s" (if unclear "off" "on")) + "+batchmode" "-u" (cdr key)))) + (if mc-pgp-comment + (setq args (cons (format "+comment=%s" mc-pgp-comment) args)) + ) + (message "Signing as %s ..." (car key)) + (if (tm:mc-process-region + start end passwd pgp-path args parser buffer boundary) + (progn + (if boundary + (progn + (goto-char (point-min)) + (insert + (format "\ +--[[multipart/signed; protocol=\"application/pgp-signature\"; + boundary=\"%s\"; micalg=pgp-md5][7bit]]\n" boundary)) + )) + (message "Signing as %s ... Done." (car key)) + t) + nil))) + +(defun mime-editor/sign-pgp-elkins (beg end boundary) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (let* ((ret + (mime-editor/translate-region beg end boundary)) + (ctype (car ret)) + (encoding (nth 1 ret)) + (parts (nth 3 ret)) + (pgp-boundary (concat "pgp-sign-" boundary)) + ) + (goto-char beg) + (insert (format "Content-Type: %s\n" ctype)) + (if encoding + (insert (format "Content-Transfer-Encoding: %s\n" encoding)) + ) + (insert "\n") + (or (tm:mc-pgp-sign-region (point-min)(point-max) + nil nil pgp-boundary) + (throw 'mime-editor/error 'pgp-error) + ) + )))) + +(defun mime-editor/encrypt-pgp-elkins (beg end boundary) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (let* ((ret + (mime-editor/translate-region beg end boundary)) + (ctype (car ret)) + (encoding (nth 1 ret)) + (parts (nth 3 ret)) + (pgp-boundary (concat "pgp-" boundary)) + ) + (goto-char beg) + (insert (format "Content-Type: %s\n" ctype)) + (if encoding + (insert (format "Content-Transfer-Encoding: %s\n" encoding)) + ) + (insert "\n") + (if (null + (progn + (goto-char beg) + (insert "=\n") + (prog1 + (let ((mail-header-separator "=")) + (call-interactively 'mc-encrypt) + ) + (goto-char beg) + (and (search-forward "=\n") + (replace-match "")) + ))) + (throw 'mime-editor/error 'pgp-error) + ) + (goto-char beg) + (insert (format "--[[multipart/encrypted; + boundary=\"%s\"; + protocol=\"application/pgp-encrypted\"][7bit]] +--%s +Content-Type: application/pgp-encrypted + +--%s +Content-Type: application/octet-stream +Content-Transfer-Encoding: 7bit + +" pgp-boundary pgp-boundary pgp-boundary)) + (goto-char (point-max)) + (insert (format "\n--%s--\n" pgp-boundary)) + )) + )) + +(defun mime-editor/process-pgp-kazu (type beg end boundary) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (let* ((ret + (mime-editor/translate-region beg end boundary)) + (ctype (car ret)) + (encoding (nth 1 ret)) + (parts (nth 3 ret)) + ) + (goto-char beg) + (insert (format "Content-Type: %s\n" ctype)) + (if encoding + (insert (format "Content-Transfer-Encoding: %s\n" encoding)) + ) + (insert "\n") + (if (null + (progn + (goto-char beg) + (insert "=\n") + (prog1 + (let ((mail-header-separator "=")) + (call-interactively type) + ) + (goto-char beg) + (and (search-forward "=\n") + (replace-match "")) + ))) + (throw 'mime-editor/error 'pgp-error) + ) + (goto-char beg) + (insert + "--[[application/pgp; format=mime][7bit]]\n") + )) + )) (defun mime-editor/translate-body () "Encode the tagged MIME body in current buffer in MIME compliant message." (interactive) (save-excursion (let ((boundary - (concat mime-multipart-boundary " " (current-time-string))) + (concat mime-multipart-boundary "_" + (replace-space-with-underline (current-time-string)) + )) (i 1) - (time (current-time-string)) ret) (while (mime-editor/process-multipart-1 - (format "%s %s-%d" mime-multipart-boundary time i)) + (format "%s-%d" boundary i)) (setq i (1+ i)) ) (save-restriction @@ -1407,7 +1788,7 @@ while if FLAG is `\\^M' (control-M) the text is hidden." (point)))) (setq ret (mime-editor/translate-region beg end - (format "%s %s-%d" mime-multipart-boundary time i))) + (format "%s-%d" boundary i))) )) (let ((contype (car ret)) ;Content-Type (encoding (nth 1 ret)) ;Content-Transfer-Encoding @@ -1435,7 +1816,8 @@ while if FLAG is `\\^M' (control-M) the text is hidden." (defun mime-editor/translate-region (beg end &optional boundary multipart) (if (null boundary) (setq boundary - (concat mime-multipart-boundary " " (current-time-string))) + (concat mime-multipart-boundary "_" + (replace-space-with-underline (current-time-string)))) ) (save-excursion (save-restriction @@ -1480,7 +1862,7 @@ while if FLAG is `\\^M' (control-M) the text is hidden." ) ;; Define Content-Type as "multipart/mixed". (setq contype - (concat "multipart/mixed; boundary=\"" boundary "\"")) + (concat "multipart/mixed;\n boundary=\"" boundary "\"")) ;; Content-Transfer-Encoding must be "7bit". ;; The following encoding can be `nil', but is ;; specified as is since there is no way that a user @@ -1543,7 +1925,10 @@ while if FLAG is `\\^M' (control-M) the text is hidden." ;; Point is now on current tag. ;; Define encoding and encode text if necessary. (if (null encoding) ;Encoding is not specified. - (let* ((encoding (mime-editor/choose-encoding)) + (let* ((encoding + (cdr + (assoc charset mime/charset-default-encoding-alist) + )) (beg (mime-editor/content-beginning)) (end (mime-editor/content-end)) (body (buffer-substring beg end)) @@ -1594,12 +1979,6 @@ while if FLAG is `\\^M' (control-M) the text is hidden." ;; Emacs 18 implementations -(defun mime-body-charset-chooser-for-emacs18 (begin end) - "Return a cons of charset and encoding of a message in a given region. -Encoding name must be a canonical name, such as `base64'." - '("US-ASCII" . nil) ;Default charset of MIME. - ) - (defun mime-string-encoder-for-emacs18 (method string) "For given METHOD that is a cons of charset and encoding, encode a STRING." (let ((charset (car method)) @@ -1613,18 +1992,6 @@ Encoding name must be a canonical name, such as `base64'." ;; Emacs 19 implementations -(defun mime-body-charset-chooser-for-emacs19 (begin end) - "Return a cons of charset and encoding of a message in a given region. -Encoding name must be a canonical name, such as `base64'. -US-ASCII and ISO-8859-1 are supported on Emacs 19." - (cond ((save-excursion - (goto-char begin) - (re-search-forward "[\200-\377]" end t)) - '("ISO-8859-1" . "quoted-printable")) - (t - '("US-ASCII" . nil)) ;Default charset of MIME. - )) - (defun mime-string-encoder-for-emacs19 (method string) "For given METHOD that is a cons of charset and encoding, encode a STRING." (let ((charset (car method)) @@ -1638,22 +2005,6 @@ US-ASCII and ISO-8859-1 are supported on Emacs 19." ;; NEmacs implementations -(defun mime-body-charset-chooser-for-nemacs (begin end) - "Return a cons of charset and encoding of a message in a given region. -Encoding name must be a canonical name, such as `base64'. -US-ASCII and ISO-2022-JP are supported on NEmacs." - (cond ((check-region-kanji-code begin end) - ;; The following are safe encoding methods for use in - ;; USENET News systems that strip off all ESCs. - ;; '("ISO-2022-JP" . "quoted-printable") - ;; '("ISO-2022-JP" . "base64") - ;; The following expects transport systems are all MIME - ;; compliants. For instance, ESCs are never stripped off. - '("ISO-2022-JP" . nil)) - (t - '("US-ASCII" . nil)) ;Default charset of MIME. - )) - (defun mime-string-encoder-for-nemacs (method string) "For given METHOD that is a cons of charset and encoding, encode a STRING. US-ASCII and ISO-2022-JP are supported on NEmacs." @@ -1677,50 +2028,6 @@ US-ASCII and ISO-2022-JP are supported on NEmacs." ;; Thanks to contributions by wkenji@flab.fujitsu.co.jp (Kenji ;; WAKAMIYA) and handa@etl.go.jp (Kenichi Handa). -(defun mime-body-charset-chooser-for-mule (begin end) - "Return a cons of charset and encoding of a message in a given -region. Encoding name must be a canonical name, such as `base64'. -US-ASCII, ISO-8859-* (except for ISO-8859-6), ISO-2022-JP, -ISO-2022-JP-2 and ISO-2022-INT-1 are supported on Mule. Either of -charset ISO-2022-JP-2 or ISO-2022-INT-1 is used for multilingual text -in Mule." - (let ((lclist (find-charset-region begin end))) - (cond ((null lclist) - '("US-ASCII" . nil)) ;Default charset of MIME. - ;; Multilingual capability requred. - ((and (> (length lclist) 1) - (boundp '*iso-2022-int-1*)) - '("ISO-2022-INT-1" . nil)) - ((> (length lclist) 1) - '("ISO-2022-JP-2" . nil)) - ;; Simple charset. - ((memq lc-ltn1 lclist) - '("ISO-8859-1" . "quoted-printable")) - ((memq lc-ltn2 lclist) - '("ISO-8859-2" . "quoted-printable")) - ((memq lc-ltn3 lclist) - '("ISO-8859-3" . "quoted-printable")) - ((memq lc-ltn4 lclist) - '("ISO-8859-4" . "quoted-printable")) - ((memq lc-crl lclist) - '("ISO-8859-5" . "quoted-printable")) - ;;((memq lc-arb lclist) - ;; '("ISO-8859-6" . "quoted-printable")) - ((memq lc-grk lclist) - '("ISO-8859-7" . "quoted-printable")) - ((memq lc-hbw lclist) - '("ISO-8859-8" . "quoted-printable")) - ((memq lc-ltn5 lclist) - '("ISO-8859-9" . "quoted-printable")) - ((memq lc-jp lclist) - '("ISO-2022-JP" . nil)) - ;; Unknown charset. - ((boundp '*iso-2022-int-1*) - '("ISO-2022-INT-1" . nil)) - (t - '("ISO-2022-JP-2" . nil)) - ))) - (defun mime-string-encoder-for-mule (method string) "For given METHOD that is a cons of charset and encoding, encode a STRING. US-ASCII, ISO-8859-* (except for ISO-8859-6), ISO-2022-JP, @@ -1742,6 +2049,7 @@ text." ("ISO-8859-9" . *iso-8859-9*) ("ISO-2022-JP" . *junet*) ("ISO-2022-JP-2" . *iso-2022-ss2-7*) + ("ISO-2022-KR" . *korean-mail*) ("ISO-2022-INT-1" . *iso-2022-int-1*) ))))) ;; In bilingual environment it may be unnecessary to convert the @@ -1833,6 +2141,8 @@ a recording host instead of local host." (let ((header-start (point)) (case-fold-search t) beg end) + ;; for Emacs 18 + ;; (if (re-search-forward "^$" (marker-position (mark-marker))) (if (re-search-forward "^$" (mark t)) (narrow-to-region header-start (match-beginning 0)) ) @@ -1846,68 +2156,6 @@ a recording host instead of local host." ) )))) -;;; mime.el ends here - -(defun mime-editor/find-inmost () - (goto-char (point-min)) - (if (re-search-forward mime-editor/multipart-beginning-regexp nil t) - (let ((bb (match-beginning 0)) - (be (match-end 0)) - (type (buffer-substring (match-beginning 1)(match-end 1))) - end-exp eb ee) - (setq end-exp (format "^--}-<<%s>>\n" type)) - (widen) - (if (re-search-forward end-exp nil t) - (progn - (setq eb (match-beginning 0)) - (setq ee (match-end 0)) - ) - (setq eb (point-max)) - (setq ee (point-max)) - ) - (narrow-to-region be eb) - (goto-char be) - (if (re-search-forward mime-editor/multipart-beginning-regexp nil t) - (let (ret) - (narrow-to-region (match-beginning 0)(point-max)) - (mime-editor/find-inmost) - ) - (widen) - ;;(delete-region eb ee) - (list type bb be eb) - )))) - -(defun mime-editor/process-multipart-1 (boundary) - (let ((ret (mime-editor/find-inmost))) - (if ret - (let ((type (car ret)) - (bb (nth 1 ret))(be (nth 2 ret)) - (eb (nth 3 ret)) - ) - (narrow-to-region bb eb) - (delete-region bb be) - (setq bb (point-min)) - (setq eb (point-max)) - (widen) - (goto-char eb) - (if (looking-at mime-editor/multipart-end-regexp) - (let ((beg (match-beginning 0)) - (end (match-end 0)) - ) - (delete-region beg end) - (if (and (not (looking-at mime-editor/single-part-tag-regexp)) - (not (eobp))) - (insert (concat (mime-make-text-tag) "\n")) - ))) - (setq boundary - (nth 2 (mime-editor/translate-region bb eb - boundary t))) - (goto-char bb) - (insert - (format "--[[multipart/%s; boundary=\"%s\"][7bit]]\n" - type boundary)) - boundary)))) - ;;; @ multipart enclosure ;;; @@ -1959,6 +2207,109 @@ a recording host instead of local host." (mime-editor/enclose-region "alternative" beg end) ) +(defun mime-editor/enclose-signed-region (beg end) + (interactive "*r") + (if mime-editor/signing-type + (mime-editor/enclose-region "signed" beg end) + (message "Please specify signing type.") + )) + +(defun mime-editor/enclose-encrypted-region (beg end) + (interactive "*r") + (if mime-editor/signing-type + (mime-editor/enclose-region "encrypted" beg end) + (message "Please specify encrypting type.") + )) + +(defun mime-editor/insert-key (&optional arg) + "Insert a pgp public key." + (interactive "P") + (mime-editor/insert-tag "application" "pgp-keys") + (mime-editor/define-encoding "7bit") + (mc-insert-public-key) + ) + + +;;; @ flag setting +;;; + +(defun mime-editor/set-split (arg) + (interactive + (list + (y-or-n-p "Do you want to enable split?") + )) + (setq mime-editor/split-message arg) + (if arg + (message "This message is enabled to split.") + (message "This message is not enabled to split.") + )) + + +;;; @ pgp +;;; + +(defun mime-editor/set-sign (arg) + (interactive + (list + (y-or-n-p "Do you want to sign?") + )) + (if arg + (progn + (setq mime-editor/pgp-processing 'sign) + (message "This message will be signed.") + ) + (if (eq mime-editor/pgp-processing 'sign) + (setq mime-editor/pgp-processing nil) + ) + (message "This message will not be signed.") + )) + +(defun mime-editor/set-encrypt (arg) + (interactive + (list + (y-or-n-p "Do you want to encrypt?") + )) + (if arg + (progn + (setq mime-editor/pgp-processing 'encrypt) + (message "This message will be encrypt.") + ) + (if (eq mime-editor/pgp-processing 'encrypt) + (setq mime-editor/pgp-processing nil) + ) + (message "This message will not be encrypt.") + )) + +(defvar mime-editor/pgp-processing nil) +(make-variable-buffer-local 'mime-editor/pgp-processing) + +(defun mime-editor/call-mc (command) + (let* ((header (rfc822/get-header-string-except + "^Content-Type:" mail-header-separator))) + (goto-char (point-min)) + (if (search-forward mail-header-separator) + (replace-match "") + ) + (goto-char (point-min)) + (insert header) + (insert "Content-Type: application/pgp; format=mime\n") + (insert mail-header-separator) + (insert "\n") + (if (null (call-interactively command)) + (throw 'mime-editor/error 'pgp-error) + ) + )) + +(defun mime-editor/pgp-processing () + (let ((command + (cdr (assq mime-editor/pgp-processing + '((sign . mc-sign) + (encrypt . mc-encrypt) + ))))) + (and command + (mime-editor/call-mc command) + ))) + ;;; @ split ;;; @@ -1974,8 +2325,142 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" id number total separator)) ) -(defun mime-editor/split-and-send (&optional cmd) +(defun mime-editor/split-and-send + (&optional cmd lines mime-editor/message-max-length) (interactive) + (or lines + (setq lines + (count-lines (point-min) (point-max))) + ) + (or mime-editor/message-max-length + (setq mime-editor/message-max-length + (or (cdr (assq major-mode mime-editor/message-max-length-alist)) + mime-editor/message-default-max-length)) + ) + (let* ((mime-editor/draft-file-name + (or (buffer-file-name) + (make-temp-name + (expand-file-name "tm-draft" mime/tmp-dir)))) + (separator mail-header-separator) + (config + (eval (cdr (assq major-mode mime-editor/window-config-alist)))) + (id (concat "\"" + (replace-space-with-underline (current-time-string)) + "@" (system-name) "\""))) + (run-hooks 'mime-editor/before-split-hook) + (let* ((header (rfc822/get-header-string-except + mime-editor/split-ignored-field-regexp separator)) + (subject (mail-fetch-field "subject")) + (total (+ (/ lines mime-editor/message-max-length) + (if (> (mod lines mime-editor/message-max-length) 0) + 1))) + (the-buf (current-buffer)) + (buf (get-buffer "*tmp-send*")) + (command + (or cmd + (cdr + (assq major-mode + mime-editor/split-message-sender-alist)) + (cdr + (assq major-mode + mime-editor/message-default-sender-alist)) + )) + data) + (goto-char (point-min)) + (if (re-search-forward (concat "^" (regexp-quote separator) "$") + nil t) + (replace-match "") + ) + (if buf + (progn + (switch-to-buffer buf) + (erase-buffer) + (switch-to-buffer the-buf) + ) + (setq buf (get-buffer-create "*tmp-send*")) + ) + (switch-to-buffer buf) + (make-local-variable 'mail-header-separator) + (setq mail-header-separator separator) + (switch-to-buffer the-buf) + (goto-char (point-min)) + (re-search-forward "^$" nil t) + (let ((mime-editor/partial-number 1)) + (setq data (buffer-substring + (point-min) + (progn + (goto-line mime-editor/message-max-length) + (point)) + )) + (delete-region (point-min)(point)) + (switch-to-buffer buf) + (mime-editor/insert-partial-header + header subject id mime-editor/partial-number total separator) + (insert data) + (save-excursion + (save-restriction + (goto-char (point-min)) + (search-forward (concat "\n" mail-header-separator "\n")) + (narrow-to-region + (match-end 0) + (if (re-search-forward "^$" nil t) + (match-beginning 0) + (point-max) + )) + (goto-char (point-min)) + (while (re-search-forward + mime-editor/split-blind-field-regexp nil t) + (delete-region (match-beginning 0) + (let ((e (rfc822/field-end))) + (if (< e (point-max)) + (1+ e) + e))) + ) + )) + (save-excursion + (message (format "Sending %d/%d..." + mime-editor/partial-number total)) + (call-interactively command) + (message (format "Sending %d/%d... done" + mime-editor/partial-number total)) + ) + (erase-buffer) + (switch-to-buffer the-buf) + (setq mime-editor/partial-number 2) + (while (< mime-editor/partial-number total) + (setq data (buffer-substring + (point-min) + (progn + (goto-line mime-editor/message-max-length) + (point)) + )) + (delete-region (point-min)(point)) + (switch-to-buffer buf) + (mime-editor/insert-partial-header + header subject id mime-editor/partial-number total separator) + (insert data) + (save-excursion + (message (format "Sending %d/%d..." + mime-editor/partial-number total)) + (call-interactively command) + (message (format "Sending %d/%d... done" + mime-editor/partial-number total)) + ) + (erase-buffer) + (switch-to-buffer the-buf) + (setq mime-editor/partial-number + (1+ mime-editor/partial-number)) + ) + (goto-char (point-min)) + (mime-editor/insert-partial-header + header subject id mime-editor/partial-number total separator) + (message (format "Sending %d/%d..." + mime-editor/partial-number total)) + )))) + +(defun mime-editor/maybe-split-and-send (&optional cmd) + (interactive) + (run-hooks 'mime-editor/before-send-hook) (let ((mime-editor/message-max-length (or (cdr (assq major-mode mime-editor/message-max-length-alist)) mime-editor/message-default-max-length)) @@ -1983,126 +2468,8 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" ) (if (and (> lines mime-editor/message-max-length) mime-editor/split-message) - (let* ((mime-editor/draft-file-name - (or (buffer-file-name) - (make-temp-name - (expand-file-name "tm-draft" mime/tmp-dir)))) - (separator mail-header-separator) - (config - (eval (cdr (assq major-mode mime-editor/window-config-alist)))) - (id (concat "\"" - (replace-space-with-underline (current-time-string)) - "@" (system-name) "\""))) - (run-hooks 'mime-editor/before-split-hook) - (let* ((header (rfc822/get-header-string-except - mime-editor/split-ignored-field-regexp separator)) - (subject (mail-fetch-field "subject")) - (total (+ (/ lines mime-editor/message-max-length) - (if (> (mod lines mime-editor/message-max-length) 0) - 1))) - (the-buf (current-buffer)) - (buf (get-buffer "*tmp-send*")) - (command - (or cmd - (cdr - (assq major-mode - mime-editor/split-message-sender-alist)) - (cdr - (assq major-mode - mime-editor/message-default-sender-alist)) - )) - data) - (goto-char (point-min)) - (if (re-search-forward (concat "^" (regexp-quote separator) "$") - nil t) - (replace-match "") - ) - (if buf - (progn - (switch-to-buffer buf) - (erase-buffer) - (switch-to-buffer the-buf) - ) - (setq buf (get-buffer-create "*tmp-send*")) - ) - (switch-to-buffer buf) - (make-variable-buffer-local 'mail-header-separator) - (setq mail-header-separator separator) - (switch-to-buffer the-buf) - (goto-char (point-min)) - (re-search-forward "^$" nil t) - (let ((mime-editor/partial-number 1)) - (setq data (buffer-substring - (point-min) - (progn - (goto-line mime-editor/message-max-length) - (point)) - )) - (delete-region (point-min)(point)) - (switch-to-buffer buf) - (mime-editor/insert-partial-header - header subject id mime-editor/partial-number total separator) - (insert data) - (save-excursion - (save-restriction - (goto-char (point-min)) - (search-forward (concat "\n" mail-header-separator "\n")) - (narrow-to-region - (match-end 0) - (if (re-search-forward "^$" nil t) - (match-beginning 0) - (point-max) - )) - (goto-char (point-min)) - (while (re-search-forward - mime-editor/split-blind-field-regexp nil t) - (delete-region (match-beginning 0) - (let ((e (rfc822/field-end))) - (if (< e (point-max)) - (1+ e) - e))) - ) - )) - (save-excursion - (message (format "Sending %d/%d..." - mime-editor/partial-number total)) - (call-interactively command) - (message (format "Sending %d/%d... done" - mime-editor/partial-number total)) - ) - (erase-buffer) - (switch-to-buffer the-buf) - (setq mime-editor/partial-number 2) - (while (< mime-editor/partial-number total) - (setq data (buffer-substring - (point-min) - (progn - (goto-line mime-editor/message-max-length) - (point)) - )) - (delete-region (point-min)(point)) - (switch-to-buffer buf) - (mime-editor/insert-partial-header - header subject id mime-editor/partial-number total separator) - (insert data) - (save-excursion - (message (format "Sending %d/%d..." - mime-editor/partial-number total)) - (call-interactively command) - (message (format "Sending %d/%d... done" - mime-editor/partial-number total)) - ) - (erase-buffer) - (switch-to-buffer the-buf) - (setq mime-editor/partial-number - (1+ mime-editor/partial-number)) - ) - (goto-char (point-min)) - (mime-editor/insert-partial-header - header subject id mime-editor/partial-number total separator) - (message (format "Sending %d/%d..." - mime-editor/partial-number total)) - )))))) + (mime-editor/split-and-send cmd lines mime-editor/message-max-length) + ))) ;;; @ preview message @@ -2173,7 +2540,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" (defun mime-editor/draft-preview () (interactive) - (let ((sep (assoc-value major-mode mime-editor/draft-header-separator-alist))) + (let ((sep (cdr (assq major-mode mime-editor/draft-header-separator-alist)))) (or (stringp sep) (setq sep (eval sep))) (make-variable-buffer-local 'mime::article/draft-header-separator) (goto-char (point-min)) @@ -2235,3 +2602,5 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" (provide 'tm-edit) (run-hooks 'tm-edit-load-hook) + +;;; tm-edit.el ends here