changeset 65664:3d928b5730c9

New file.
author Richard M. Stallman <rms@gnu.org>
date Fri, 23 Sep 2005 18:31:49 +0000
parents a36daa69a131
children 70992428ba25
files lisp/mail/mailclient.el
diffstat 1 files changed, 173 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/mail/mailclient.el	Fri Sep 23 18:31:49 2005 +0000
@@ -0,0 +1,173 @@
+;;; mailclient.el --- mail sending via system's mail client.  -*- byte-compile-dynamic: t -*-
+
+;; Copyright (C) 2005 Free Software Foundation
+
+;; Author: David Reitter <david.reitter@gmail.com>
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This package allows to hand over a buffer to be sent off 
+;; via the system's designated e-mail client. 
+;; Note that the e-mail client will display the contents of the buffer
+;; again for editing.
+;; The e-mail client is taken to be whoever handles a mailto: URL
+;; via `browse-url'. 
+;; Mailto: URLs are composed according to RFC2368.
+
+;; MIME bodies are not supported - we rather expect the mail client
+;; to encode the body and add, for example, a digital signature.
+;; The mailto URL RFC calls for "short text messages that are
+;; actually the content of automatic processing." 
+;; So mailclient.el is ideal for situations where an e-mail is
+;; generated automatically, and the user can edit it in the 
+;; mail client (e.g. bug-reports). 
+
+;; To activate:
+;; (setq send-mail-function 'mailclient-send-it) ; if you use `mail'
+
+;;; Code:
+
+
+(require 'sendmail)   ;; for mail-sendmail-undelimit-header
+(require 'mail-utils) ;; for mail-fetch-field
+
+(defcustom mailclient-place-body-on-clipboard-flag  
+  (fboundp 'w32-set-clipboard-data)
+  "If non-nil, put the e-mail body on the clipboard in mailclient.
+This is useful on systems where only short mailto:// URLs are 
+supported. Defaults to non-nil on Windows, nil otherwise."
+  :type 'boolean
+  :group 'mail)
+
+(defun mailclient-encode-string-as-url (string)
+  "Convert STRING to a URL, using utf-8 as encoding."
+  (apply (function concat)
+	 (mapcar
+	  (lambda (char)
+	    (cond
+	     ((eq char ?\x20) "%20")   ;; space
+	     ((eq char ?\n) "%0D%0A")  ;; newline 
+	     ((string-match "[-a-zA-Z0-9_:/.@]" (char-to-string char))
+	      (char-to-string char))   ;; printable
+	     (t                        ;; everything else
+	      (format "%%%02x" char))))	;; escape
+	  ;; Convert string to list of chars
+	  (append (encode-coding-string string 'utf-8)))))
+
+(defvar mailclient-delim-static "?")
+(defun mailclient-url-delim ()
+  (let ((current mailclient-delim-static))
+    (setq mailclient-delim-static "&") 
+    current))
+
+(defun mailclient-gather-addresses (str &optional drop-first-name)
+  (let ((field (mail-fetch-field str nil t)))
+    (if field
+	(save-excursion
+	  (let ((first t) 
+		(result ""))
+	    (mapc
+	     (lambda (recp)
+	       (setq result 
+		     (concat 
+		      result
+		      (if (and drop-first-name
+			       first)
+			  ""
+			(concat (mailclient-url-delim) str "="))
+		      (mailclient-encode-string-as-url 
+		       recp)))
+	       (setq first nil))
+	     (split-string 
+	      (mail-strip-quoted-names field) "\, *"))
+	    result)))))
+
+;;;###autoload
+(defun mailclient-send-it () 
+  "Pass current buffer on to the system's mail client.
+Suitable value for `send-mail-function'.
+The mail client is taken to be the handler of mailto URLs."
+  (require 'mail-utils)
+  (let ((case-fold-search nil)
+	delimline
+	(mailbuf (current-buffer)))
+    (unwind-protect
+	(with-temp-buffer
+	  (insert-buffer-substring mailbuf)
+	  ;; Move to header delimiter
+	  (mail-sendmail-undelimit-header)
+	  (setq delimline (point-marker))
+	  (if mail-aliases
+	      (expand-mail-aliases (point-min) delimline))
+	  (goto-char (point-min))
+	  ;; ignore any blank lines in the header
+	  (while (and (re-search-forward "\n\n\n*" delimline t)
+		      (< (point) delimline))
+	    (replace-match "\n"))
+	  (let ((case-fold-search t))  
+	    ;; initialize limiter
+	    (setq mailclient-delim-static "?")
+	    ;; construct and call up mailto URL
+	    (browse-url 
+	     (concat 
+	      (save-excursion
+		(narrow-to-region (point-min) delimline)
+		(concat 
+		 "mailto:"
+		 ;; some of the headers according to RFC822
+		 (mailclient-gather-addresses "To"   
+					      'drop-first-name)	         
+		 (mailclient-gather-addresses "cc"  )
+		 (mailclient-gather-addresses "bcc"  )
+		 (mailclient-gather-addresses "Resent-To"  )
+		 (mailclient-gather-addresses "Resent-cc"  )
+		 (mailclient-gather-addresses "Resent-bcc"  )
+		 (mailclient-gather-addresses "Reply-To"  )
+		 ;; The From field is not honored for now: it's
+		 ;; not necessarily configured. The mail client
+		 ;; knows the user's address(es)
+		 ;; (mailclient-gather-addresses "From"  )
+		 ;; subject line
+		 (let ((subj (mail-fetch-field "Subject" nil t)))
+		   (widen) ;; so we can read the body later on
+		   (if subj ;; if non-blank
+		       ;; the mail client will deal with
+		       ;; warning the user etc.
+		       (concat (mailclient-url-delim) "subject=" 
+			       (mailclient-encode-string-as-url subj))
+		     ""))))
+	      ;; body
+	      (concat 
+	       (mailclient-url-delim) "body=" 
+	       (mailclient-encode-string-as-url
+		(if mailclient-place-body-on-clipboard-flag
+		    (progn
+		      (clipboard-kill-ring-save  
+		       (+ 1 delimline) (point-max))
+		      (concat
+		       "*** E-Mail body has been placed on clipboard, "
+		       "please paste them here! ***"))
+		  ;; else
+		  (buffer-substring (+ 1 delimline) (point-max))))))))))))
+
+(provide 'mailclient)
+
+;;; mailclient.el ends here