* mime-edit.el (mime-edit-insert-file): Make it work with Emacs.
[elisp/semi.git] / mime-edit.el
index a5a06e1..7dc21fb 100644 (file)
 
 ;;; Code:
 
+(eval-when-compile (require 'static))
+
 (require 'sendmail)
 (require 'mail-utils)
 (require 'mel)
   "S/MIME encryption of current region.")
 (autoload 'smime-sign-region "smime"
   "S/MIME signature of current region.")
+(defvar smime-output-buffer)
+(defvar smime-errors-buffer)
 
 
 ;;; @ version
@@ -287,7 +291,7 @@ To insert a signature file automatically, call the function
      nil
      "attachment"      (("filename" . file)))
 
-    ("\\.html$"
+    ("\\.html?$"
      "text"    "html"          nil
      nil
      nil               nil)
@@ -448,7 +452,7 @@ If encoding is nil, it is determined from its contents."
 
 (defcustom mime-edit-attach-at-end-type nil
   "*List of MIME types to be attached at the end of a message.
-Values must be strings indicates MIME types. You can specify
+Values must be strings indicates MIME types.  You can specify
 either type/subtype or type only."
   :group 'mime-edit
   :type '(choice (const :tag "Nothing" nil)
@@ -480,8 +484,13 @@ either type/subtype or type only."
     (iso-2022-jp-2     7 "base64")
     (iso-2022-int-1    7 "base64")))
 
-(defvar mime-transfer-level 7
-  "*A number of network transfer level.  It should be bigger than 7.")
+(defcustom mime-transfer-level 7
+  "*A number of network transfer level.  It should be bigger than 7.
+Currently it has no effect except mode-line display."
+  :group 'mime-edit
+  :type '(choice (const 7)
+                (const 8)
+                (const :tag "Binary" 9)))
 (make-variable-buffer-local 'mime-transfer-level)
 
 (defsubst mime-encoding-name (transfer-level &optional not-omit)
@@ -491,10 +500,9 @@ either type/subtype or type only."
 
 (defvar mime-transfer-level-string
   (mime-encoding-name mime-transfer-level 'not-omit)
-  "A string formatted version of mime-transfer-level")
+  "A string formatted version of `mime-transfer-level'.")
 (make-variable-buffer-local 'mime-transfer-level-string)
 
-
 ;;; @@ about content transfer encoding
 
 (defvar mime-content-transfer-encoding-priority-list
@@ -503,17 +511,13 @@ either type/subtype or type only."
 ;;; @@ about message inserting
 ;;;
 
-(defvar mime-edit-yank-ignored-field-list
+(defcustom mime-edit-yank-ignored-field-list
   '("Received" "Approved" "Path" "Replied" "Status"
     "Xref" "X-UIDL" "X-Filter" "X-Gnus-.*" "X-VM-.*")
-  "Delete these fields from original message when it is inserted
-as message/rfc822 part.
-Each elements are regexp of field-name.")
-
-(defvar mime-edit-yank-ignored-field-regexp
-  (concat "^"
-         (apply (function regexp-or) mime-edit-yank-ignored-field-list)
-         ":"))
+  "List of ignored header fields when inserting message/rfc822.
+Each elements are regexp of field-name."
+  :group 'mime-edit
+  :type '(repeat regexp))
 
 (defvar mime-edit-message-inserter-alist nil)
 (defvar mime-edit-mail-inserter-alist nil)
@@ -527,15 +531,15 @@ Each elements are regexp of field-name.")
   :group 'mime-edit
   :type 'boolean)
 
-(defcustom mime-edit-message-default-max-lines 1000
+(defcustom mime-edit-message-default-max-lines 5000
   "*Default maximum lines of a message."
   :group 'mime-edit
   :type 'integer)
 
 (defcustom mime-edit-message-max-lines-alist
   '((news-reply-mode . 500))
-  "Alist of major-mode vs maximum lines of a message.
-If it is not specified for a major-mode,
+  "Alist of `major-mode' vs maximum lines of a message.
+If it is not specified for a `major-mode',
 `mime-edit-message-default-max-lines' is used."
   :group 'mime-edit
   :type 'list)
@@ -581,11 +585,11 @@ If it is not specified for a major-mode,
             mime-edit-multipart-beginning-regexp
             mime-edit-multipart-end-regexp))
 
-(defvar mime-tag-format "--[[%s]]"
-  "*Control-string making a MIME tag.")
+(defconst mime-tag-format "--[[%s]]"
+  "Control-string making a MIME tag.")
 
-(defvar mime-tag-format-with-encoding "--[[%s][%s]]"
-  "*Control-string making a MIME tag with encoding.")
+(defconst mime-tag-format-with-encoding "--[[%s][%s]]"
+  "Control-string making a MIME tag with encoding.")
 
 
 ;;; @@ multipart boundary
@@ -598,8 +602,10 @@ If it is not specified for a major-mode,
 ;;; @@ optional header fields
 ;;;
 
-(defvar mime-edit-insert-user-agent-field t
-  "*If non-nil, insert User-Agent header field.")
+(defcustom mime-edit-insert-user-agent-field t
+  "*If non-nil, insert User-Agent header field."
+  :group 'mime-edit
+  :type 'boolean)
 
 (defvar mime-edit-user-agent-value
   (concat (mime-product-name mime-user-interface-product)
@@ -669,7 +675,7 @@ inserted into message header.")
 ;;;
 
 (defconst mime-tspecials-regexp "[][()<>@,;:\\\"/?.= \t]"
-  "*Specify MIME tspecials.
+  "Specify MIME tspecials.
 Tspecials means any character that matches with it in header must be quoted.")
 
 (defconst mime-edit-mime-version-value
@@ -677,14 +683,6 @@ Tspecials means any character that matches with it in header must be quoted.")
   "1.0"
   "MIME version number.")
 
-(defconst mime-edit-mime-version-field-for-message/partial
-  (concat "MIME-Version:"
-         (eword-encode-field-body
-          (concat " 1.0 (split by " mime-edit-version ")\n")
-          "MIME-Version:"))
-  "MIME version field for message/partial.")
-
-
 ;;; @ keymap and menu
 ;;;
 
@@ -698,6 +696,7 @@ Tspecials means any character that matches with it in header must be quoted.")
 
 (define-key mime-edit-mode-entity-map "\C-t" 'mime-edit-insert-text)
 (define-key mime-edit-mode-entity-map "\C-i" 'mime-edit-insert-file)
+(define-key mime-edit-mode-entity-map "i"    'mime-edit-insert-text-file)
 (define-key mime-edit-mode-entity-map "\C-e" 'mime-edit-insert-external)
 (define-key mime-edit-mode-entity-map "\C-v" 'mime-edit-insert-voice)
 (define-key mime-edit-mode-entity-map "\C-y" 'mime-edit-insert-message)
@@ -773,43 +772,44 @@ Tspecials means any character that matches with it in header must be quoted.")
     (level     "Toggle transfer-level" mime-edit-toggle-transfer-level))
   "MIME-edit menubar entry.")
 
-(cond ((featurep 'xemacs)
+(static-if (featurep 'xemacs)
        ;; modified by Pekka Marjola <pema@iki.fi>
        ;;      1995/9/5 (c.f. [tm-en:69])
-       (defun mime-edit-define-menu-for-xemacs ()
-        "Define menu for XEmacs."
-        (cond ((featurep 'menubar)
-               (make-local-variable 'current-menubar)
-               (set-buffer-menubar current-menubar)
-               (add-submenu
-                nil
-                (cons mime-edit-menu-title
-                      (mapcar (function
-                               (lambda (item)
-                                 (vector (nth 1 item)(nth 2 item)
-                                         mime-edit-mode-flag)))
-                              mime-edit-menu-list))))))
-
-       ;; modified by Steven L. Baur <steve@miranova.com>
-       ;;      1995/12/6 (c.f. [tm-en:209])
-       (or (boundp 'mime-edit-popup-menu-for-xemacs)
-          (setq mime-edit-popup-menu-for-xemacs
-                (append '("MIME Commands" "---")
-                        (mapcar (function (lambda (item)
-                                            (vector (nth 1 item)
-                                                    (nth 2 item)
-                                                    t)))
-                                mime-edit-menu-list)))))
-      ((>= emacs-major-version 19)
-       (define-key mime-edit-mode-map [menu-bar mime-edit]
-        (cons mime-edit-menu-title
-              (make-sparse-keymap mime-edit-menu-title)))
-       (mapcar (function
-               (lambda (item)
-                 (define-key mime-edit-mode-map
-                   (vector 'menu-bar 'mime-edit (car item))
-                   (cons (nth 1 item)(nth 2 item)))))
-              (reverse mime-edit-menu-list))))
+    (progn
+      (defun mime-edit-define-menu-for-xemacs ()
+       "Define menu for XEmacs."
+       (cond ((featurep 'menubar)
+              (make-local-variable 'current-menubar)
+              (set-buffer-menubar current-menubar)
+              (add-submenu
+               nil
+               (cons mime-edit-menu-title
+                     (mapcar (function
+                              (lambda (item)
+                                (vector (nth 1 item)(nth 2 item)
+                                        mime-edit-mode-flag)))
+                             mime-edit-menu-list))))))
+      ;; modified by Steven L. Baur <steve@miranova.com>
+      ;;       1995/12/6 (c.f. [tm-en:209])
+      (or (boundp 'mime-edit-popup-menu-for-xemacs)
+         (setq mime-edit-popup-menu-for-xemacs
+               (append '("MIME Commands" "---")
+                       (mapcar (function (lambda (item)
+                                           (vector (nth 1 item)
+                                                   (nth 2 item)
+                                                   t)))
+                               mime-edit-menu-list)))))
+      ;; Bogus check.  Nemacs is not supported.
+      ;;(>= emacs-major-version 19)
+  (define-key mime-edit-mode-map [menu-bar mime-edit]
+    (cons mime-edit-menu-title
+         (make-sparse-keymap mime-edit-menu-title)))
+  (mapcar (function
+          (lambda (item)
+            (define-key mime-edit-mode-map
+              (vector 'menu-bar 'mime-edit (car item))
+              (cons (nth 1 item)(nth 2 item)))))
+         (reverse mime-edit-menu-list)))
 
 ;;; @ macros
 ;;;
@@ -943,7 +943,7 @@ User customizable variables (not documented all of them):
 
  mime-transfer-level
     A number of network transfer level.  It should be bigger than 7.
-    If you are in 8bit-through environment, please set 8.
+    If you are in 8bit-through environment, please set to 8.
 
  mime-edit-voice-recorder
     Specifies a function to record a voice message and encode it.
@@ -973,19 +973,18 @@ User customizable variables (not documented all of them):
       (turn-on-mime-edit))))
 
 
-(cond ((featurep 'xemacs)
-       (add-minor-mode 'mime-edit-mode-flag
-                      '((" MIME-Edit "  mime-transfer-level-string))
-                      mime-edit-mode-map
-                      nil
-                      'mime-edit-mode))
-      (t
-       (set-alist 'minor-mode-alist
-                 'mime-edit-mode-flag
-                 '((" MIME-Edit "  mime-transfer-level-string)))
-       (set-alist 'minor-mode-map-alist
-                 'mime-edit-mode-flag
-                 mime-edit-mode-map)))
+(static-if (featurep 'xemacs)
+    (add-minor-mode 'mime-edit-mode-flag
+                   '((" MIME-Edit "  mime-transfer-level-string))
+                   mime-edit-mode-map
+                   nil
+                   'mime-edit-mode)
+  (set-alist 'minor-mode-alist
+            'mime-edit-mode-flag
+            '((" MIME-Edit "  mime-transfer-level-string)))
+  (set-alist 'minor-mode-map-alist
+            'mime-edit-mode-flag
+            mime-edit-mode-map))
 
 
 ;;;###autoload
@@ -993,7 +992,7 @@ User customizable variables (not documented all of them):
   "Unconditionally turn on MIME-Edit mode."
   (interactive)
   (if mime-edit-mode-flag
-      (error "You are already editing a MIME message.")
+      (error "You are already editing a MIME message")
     (setq mime-edit-mode-flag t)
 
     ;; Set transfer level into mode line
@@ -1026,12 +1025,13 @@ User customizable variables (not documented all of them):
 
 (defun mime-edit-exit (&optional nomime no-error)
   "Translate the tagged MIME message into a MIME compliant message.
-With no argument encode a message in the buffer into MIME, otherwise
-just return to previous mode."
+When NOMIME is nil, encode a message in the buffer into MIME.
+Otherwise, just returns to previous mode.  If NO-ERROR is non-nil,
+no errors will be signaled even if it is not MIME-Edit mode."
   (interactive "P")
   (if (not mime-edit-mode-flag)
       (if (null no-error)
-         (error "You aren't editing a MIME message."))
+         (error "You aren't editing a MIME message"))
     (if (not nomime)
        (progn
          (run-hooks 'mime-edit-translate-hook)
@@ -1041,7 +1041,7 @@ just return to previous mode."
     (if (and (featurep 'xemacs)
             (featurep 'menubar))
        (delete-menu-item (list mime-edit-menu-title)))
-    (end-of-invisible)
+    (disable-invisible)
     (set-buffer-modified-p (buffer-modified-p))
     (run-hooks 'mime-edit-exit-hook)
     (message "Exit MIME editor mode.")))
@@ -1077,8 +1077,68 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
        (if (boundp 'enriched-mode)
            (enriched-mode -1))))))
 
+(defun mime-edit-insert-text-file (file &optional verbose)
+  "Insert a text message from a FILE.
+Charset is automatically obtained from the `charsets-mime-charset-alist'.
+If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
+  (interactive "fInsert file as a MIME text: \nP")
+  (let*  ((guess (mime-find-file-type file))
+         (type "text")
+         (subtype nil)
+         (parameters (nth 2 guess))
+;;       (encoding (nth 3 guess))
+         (disposition-type (nth 4 guess))
+         (disposition-params (nth 5 guess))
+         string)
+    (setq subtype (mime-prompt-for-subtype type subtype))
+;;    (if (or (interactive-p) verbose)
+;;     (setq encoding (mime-prompt-for-encoding encoding)))
+    (if verbose
+       (setq disposition-type (mime-prompt-for-disposition disposition-type)))
+    (if (or (consp parameters) (stringp disposition-type))
+       (let ((rest parameters) cell attribute value)
+         (setq parameters "")
+         (while rest
+           (setq cell (car rest))
+           (setq attribute (car cell))
+           (setq value (cdr cell))
+           (if (eq value 'file)
+               (setq value (std11-wrap-as-quoted-string
+                            (file-name-nondirectory file))))
+           (setq parameters (concat parameters "; " 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 (std11-wrap-as-quoted-string
+                                  (file-name-nondirectory file))))
+                 (setq parameters
+                       (concat parameters "; " attribute "=" value))
+                 (setq rest (cdr rest)))))))
+    (mime-edit-insert-place
+     (list type subtype)
+     (mime-edit-insert-tag type subtype parameters)
+;;     (if (stringp encoding)
+;;      (mime-edit-define-encoding encoding))
+     (save-excursion
+       (let ((ret (insert-file-contents file)))
+        (forward-char (cadr ret))
+     (if (and (not (eobp))
+             (not (looking-at mime-edit-single-part-tag-regexp)))
+        (insert (mime-make-text-tag) "\n")))))))
+
 (defun mime-edit-insert-file (file &optional verbose)
-  "Insert a message from a file."
+  "Insert a message from a FILE.
+If VERBOSE is non-nil, it will prompt for Content-Type,
+Content-Transfer-Encoding and Content-Disposition headers."
   (interactive "fInsert file as MIME message: \nP")
   (let*  ((guess (mime-find-file-type file))
          (type (nth 0 guess))
@@ -1086,7 +1146,8 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
          (parameters (nth 2 guess))
          (encoding (nth 3 guess))
          (disposition-type (nth 4 guess))
-         (disposition-params (nth 5 guess)))
+         (disposition-params (nth 5 guess))
+         string)
     (if verbose
        (setq type    (mime-prompt-for-type type)
              subtype (mime-prompt-for-subtype type subtype)))
@@ -1097,6 +1158,36 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
     (if (or (consp parameters) (stringp disposition-type))
        (let ((rest parameters) cell attribute value)
          (setq parameters "")
+         (when (string= type "text")
+           (with-temp-buffer
+             (let (candidates candidate eol eol-string)
+             (set-buffer-multibyte nil)
+             (insert-file-contents-as-binary file)
+             (setq candidates (detect-coding-region (point-min) (point-max)))
+             (setq candidate (if (listp candidates)
+                                 (car candidates)
+                               candidates))
+             (setq eol (coding-system-eol-type candidate))
+             (cond ((eq eol
+                        (static-if (featurep 'xemacs)
+                            'lf
+                          0))
+                    (setq eol-string "\n"))
+                   ((eq eol
+                        (static-if (featurep 'xemacs)
+                            'cr
+                          2))
+                    (setq eol-string "\r")))
+             (goto-char (point-min))
+             (when eol-string
+               (while (search-forward eol-string nil t)
+                 (replace-match "\r\n")))
+             (setq string (buffer-string))
+             (setq parameters
+                   (concat parameters "; charset="
+                           (symbol-name
+                            (coding-system-to-mime-charset
+                             candidate)))))))
          (while rest
            (setq cell (car rest))
            (setq attribute (car cell))
@@ -1125,7 +1216,9 @@ If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
     (mime-edit-insert-place
      (list type subtype)
      (mime-edit-insert-tag type subtype parameters)
-     (mime-edit-insert-binary-file file encoding))))
+     (if string
+        (mime-edit-insert-binary-string string encoding)
+       (mime-edit-insert-binary-file file encoding)))))
 
 (defun mime-edit-insert-external ()
   "Insert a reference to external body."
@@ -1233,6 +1326,45 @@ If nothing is inserted, return nil."
       nil                              ;Nothing is created.
       )))
 
+;; #### This should be merged into the function below but for now,
+;; don't change APIs.
+(defun mime-edit-insert-binary-string (string &optional encoding)
+  "Insert binary STRING at point.
+Optional argument ENCODING specifies an encoding method such as base64."
+  (let* ((tagend (1- (point)))         ;End of the tag
+        (hide-p (and mime-auto-hide-body
+                     (stringp encoding)
+                     (not
+                      (let ((en (downcase encoding)))
+                        (or (string-equal en "7bit")
+                            (string-equal en "8bit")
+                            (string-equal en "binary")))))))
+    (save-restriction
+      (narrow-to-region tagend (point))
+      (insert
+       (with-temp-buffer
+        ;; #### @!#$%@!${$@}
+        (set-buffer-multibyte nil)
+        (insert string)
+        ;; #### Why mime-encode-string doesn't exist?
+        (mime-encode-region (point-min) (point-max)
+                            (or encoding "7bit"))
+        (buffer-string)))
+      (if hide-p
+         (progn
+           (invisible-region (point-min) (point-max))
+           (goto-char (point-max)))
+       (goto-char (point-max))))
+    (unless (or (looking-at mime-edit-tag-regexp)
+               (= (point)(point-max)))
+      (insert "\n")
+      (mime-edit-insert-tag "text" "plain"))
+    ;; Define encoding even if it is 7bit.
+    (if (stringp encoding)
+       (save-excursion
+         (goto-char tagend) ; Make sure which line the tag is on.
+         (mime-edit-define-encoding encoding)))))
+
 (defun mime-edit-insert-binary-file (file &optional encoding)
   "Insert binary FILE at point.
 Optional argument ENCODING specifies an encoding method such as base64."
@@ -1252,10 +1384,10 @@ Optional argument ENCODING specifies an encoding method such as base64."
            (invisible-region (point-min) (point-max))
            (goto-char (point-max)))
        (goto-char (point-max))))
-    (or hide-p
-       (looking-at mime-edit-tag-regexp)
-       (= (point)(point-max))
-       (mime-edit-insert-tag "text" "plain"))
+    (unless (or (looking-at mime-edit-tag-regexp)
+               (= (point)(point-max)))
+      (insert "\n")
+      (mime-edit-insert-tag "text" "plain"))
     ;; Define encoding even if it is 7bit.
     (if (stringp encoding)
        (save-excursion
@@ -1335,7 +1467,11 @@ Optional argument ENCODING specifies an encoding method such as base64."
           (mime-create-tag
            (mime-edit-set-parameter
             (mime-edit-get-contype tag)
-            "charset" (upcase (symbol-name charset)))
+            "charset"
+            (let ((comment (get charset 'mime-charset-comment)))
+              (if comment
+                  (concat (upcase (symbol-name charset)) " (" comment ")")
+                (upcase (symbol-name charset)))))
            (mime-edit-get-encoding tag)))))))
 
 (defun mime-edit-define-encoding (encoding)
@@ -1353,7 +1489,7 @@ Optional argument ENCODING specifies an encoding method such as base64."
 (defun mime-make-text-tag (&optional subtype)
   "Make a tag for a text after current point.
 Subtype of text type can be specified by an optional argument SUBTYPE.
-Otherwise, it is obtained from mime-content-types."
+Otherwise, it is obtained from `mime-content-types'."
   (let* ((pritype "text")
         (subtype (or subtype
                      (car (car (cdr (assoc pritype mime-content-types)))))))
@@ -1419,10 +1555,10 @@ Nil if no such parameter."
        ;; Change value
        (concat (substring ctype 0 (match-beginning 1))
                parameter "=" value
-               (substring contype (match-end 1))
-               opt-fields)
-      (concat ctype "; " parameter "=" value opt-fields)
-      )))
+               (substring contype (match-end 1)))
+      ;; This field makes two CDP header when charset parameter is present.
+;;             opt-fields)
+      (concat ctype "; " parameter "=" value opt-fields))))
 
 (defun mime-strip-parameters (contype)
   "Return primary content-type and subtype without parameters for CONTYPE."
@@ -1668,11 +1804,13 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
        (let ((tag (buffer-substring (match-beginning 0)(match-end 0))))
          (replace-match (concat "-" (substring tag 2))))))))
 
+(defvar mime-edit-pgp-user-id nil)
+
 (defun mime-edit-sign-pgp-mime (beg end boundary)
   (save-excursion
     (save-restriction
       (let* ((from (std11-field-body "From" mail-header-separator))
-            (ret (progn 
+            (ret (progn
                    (narrow-to-region beg end)
                    (mime-edit-translate-region beg end boundary)))
             (ctype    (car ret))
@@ -1684,9 +1822,9 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
        (if encoding
            (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
        (insert "\n")
-       (or (let ((pgg-default-user-id 
+       (or (let ((pgg-default-user-id
                   (or mime-edit-pgp-user-id
-                      (if from 
+                      (if from
                           (nth 1 (std11-extract-address-components from))
                         pgg-default-user-id))))
              (pgg-sign-region (point-min)(point-max)))
@@ -1694,9 +1832,9 @@ Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
        (setq micalg
              (cdr (assq 'hash-algorithm
                         (cdar (with-current-buffer pgg-output-buffer
-                                (pgg-parse-armor-region 
+                                (pgg-parse-armor-region
                                  (point-min)(point-max))))))
-             micalg 
+             micalg
              (if micalg
                  (concat "; micalg=pgp-" (downcase (symbol-name micalg)))
                ""))
@@ -1766,17 +1904,17 @@ Content-Transfer-Encoding: 7bit
               (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
           (insert "\n")
          (eword-encode-header)
-         (or (let ((pgg-default-user-id 
+         (or (let ((pgg-default-user-id
                     (or mime-edit-pgp-user-id
-                        (if from 
+                        (if from
                             (nth 1 (std11-extract-address-components from))
-                          pgg-default-user-id))))                   
-               (pgg-encrypt-region 
-                (point-min) (point-max) 
+                          pgg-default-user-id))))
+               (pgg-encrypt-region
+                (point-min) (point-max)
                 (mapcar (lambda (recipient)
                           (nth 1 (std11-extract-address-components
                                   recipient)))
-                        (split-string recipients 
+                        (split-string recipients
                                       "\\([ \t\n]*,[ \t\n]*\\)+"))))
              (throw 'mime-edit-error 'pgp-error))
          (delete-region (point-min)(point-max))
@@ -1844,7 +1982,7 @@ Content-Transfer-Encoding: 7bit
 (defun mime-edit-sign-smime (beg end boundary)
   (save-excursion
     (save-restriction
-      (let* ((ret (progn 
+      (let* ((ret (progn
                    (narrow-to-region beg end)
                    (mime-edit-translate-region beg end boundary)))
             (ctype    (car ret))
@@ -1885,7 +2023,7 @@ Content-Description: S/MIME Cryptographic Signature
 (defun mime-edit-encrypt-smime (beg end boundary)
   (save-excursion
     (save-restriction
-      (let* ((ret (progn 
+      (let* ((ret (progn
                    (narrow-to-region beg end)
                    (mime-edit-translate-region beg end boundary)))
             (ctype    (car ret))
@@ -2102,7 +2240,7 @@ Content-Description: S/MIME Encrypted Message][base64]]\n")
                    ;;                        (point)
                    ;;                        'hard t)))
                   ;; End patch for hard newlines
-                  (enriched-encode beg end)
+                  (enriched-encode beg end nil)
                   (goto-char beg)
                   (if (search-forward "\n\n")
                       (delete-region beg (match-end 0)))))))
@@ -2223,7 +2361,10 @@ and insert data encoded as ENCODING."
            (narrow-to-region header-start (match-beginning 0)))
        (goto-char header-start)
        (while (and (re-search-forward
-                    mime-edit-yank-ignored-field-regexp nil t)
+                    (concat "^"
+                            (apply (function regexp-or)
+                                   mime-edit-yank-ignored-field-list)
+                            ":") nil t)
                    (setq beg (match-beginning 0))
                    (setq end (1+ (std11-field-end))))
          (delete-region beg end))))))
@@ -2294,7 +2435,10 @@ and insert data encoded as ENCODING."
   (interactive "P")
   (mime-edit-insert-tag "application" "pgp-keys")
   (mime-edit-define-encoding "7bit")
-  (pgg-insert-key))
+  (pgg-insert-key)
+  (if (and (not (eobp))
+          (not (looking-at mime-edit-single-part-tag-regexp)))
+      (insert (mime-make-text-tag) "\n")))
 
 
 ;;; @ flag setting
@@ -2340,8 +2484,6 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
 (defvar mime-edit-pgp-processing nil)
 (make-variable-buffer-local 'mime-edit-pgp-processing)
 
-(defvar mime-edit-pgp-user-id nil)
-
 (defun mime-edit-set-sign (arg)
   (interactive
    (list
@@ -2349,11 +2491,11 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
   (if arg
       (progn
        (or (memq 'sign mime-edit-pgp-processing)
-           (setq mime-edit-pgp-processing 
-                 (nconc mime-edit-pgp-processing 
+           (setq mime-edit-pgp-processing
+                 (nconc mime-edit-pgp-processing
                         (copy-sequence '(sign)))))
        (message "This message will be signed."))
-    (setq mime-edit-pgp-processing 
+    (setq mime-edit-pgp-processing
          (delq 'sign mime-edit-pgp-processing))
     (message "This message will not be signed.")))
 
@@ -2364,8 +2506,8 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
   (if arg
       (progn
        (or (memq 'encrypt mime-edit-pgp-processing)
-           (setq mime-edit-pgp-processing 
-                 (nconc mime-edit-pgp-processing 
+           (setq mime-edit-pgp-processing
+                 (nconc mime-edit-pgp-processing
                         (copy-sequence '(encrypt)))))
        (message "This message will be encrypt."))
     (setq mime-edit-pgp-processing
@@ -2381,10 +2523,10 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
        (dolist (pgp-processing mime-edit-pgp-processing)
          (case pgp-processing
            (sign
-            (mime-edit-enclose-pgp-signed-region 
+            (mime-edit-enclose-pgp-signed-region
              beg (point-max)))
            (encrypt
-            (mime-edit-enclose-pgp-encrypted-region 
+            (mime-edit-enclose-pgp-encrypted-region
              beg (point-max))))))))
 
 
@@ -2395,7 +2537,7 @@ Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
                                               id number total separator)
   (insert fields)
   (insert (format "Subject: %s (%d/%d)\n" subject number total))
-  (insert mime-edit-mime-version-field-for-message/partial)
+  (insert (format "Mime-Version: %s\n" mime-edit-mime-version-value))
   (insert (format "\
 Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                  id number total separator)))
@@ -2410,10 +2552,11 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
       (setq mime-edit-message-max-length
            (or (cdr (assq major-mode mime-edit-message-max-lines-alist))
                mime-edit-message-default-max-lines)))
-  (let* ((mime-edit-draft-file-name
-         (or (buffer-file-name)
-             (make-temp-name
-              (expand-file-name "mime-draft" temporary-file-directory))))
+  (let* (
+;;      (mime-edit-draft-file-name
+;;       (or (buffer-file-name)
+;;           (make-temp-name
+;;            (expand-file-name "mime-draft" temporary-file-directory))))
         (separator mail-header-separator)
         (id (concat "\""
                     (replace-space-with-underline (current-time-string))
@@ -2607,20 +2750,20 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
                           (goto-char (point-min))
                           (re-search-forward "^-+BEGIN PGP MESSAGE-+$"
                                              nil t))
-                        (prog1 
+                        (prog1
                             (save-window-excursion
                               (pgg-decrypt-region (match-beginning 0)
                                                   (point-max)))
                           (delete-region (point-min)(point-max))))
                    (insert-buffer-substring pgg-output-buffer)
-                   (mime-edit-decode-message-in-buffer 
+                   (mime-edit-decode-message-in-buffer
                     nil not-decode-text)
                    (delete-region (goto-char (point-min))
                                   (if (search-forward "\n\n" nil t)
                                       (match-end 0)
                                     (point-min)))
                    (goto-char (point-max))))
-                (t 
+                (t
                  (mime-edit-decode-message-in-buffer
                   (if (eq subtype 'digest)
                       (eval-when-compile