MNO Playing around with the tcom extension after the inspiration of some Python code at http://disgruntled-programmer.com/notes/emacs-with-outlook.html , I came up with the following:-
It basically allows a running NTEmacs editor to grab the text of an email reply/forward etc. from Outlook and edit it in Emacs. It is then possible to transfer the edited text back to the outlook window and send it from there.
Currently only tested with Outlook 2000, ActiveTcl 8.4.3 and NTEmacs 21.3.1 under Windows 2000.
PLEASE READ THE LAST POINT UNDER "KNOWN ISSUES" BELOW BEFORE USING THIS CODE!
Installation
Usage
Known Issues
The Code
The Emacs-Lisp file outlookedit.el
;;; outlookedit.el ;; use a couple of Tcl scripts to invoke my Tcl scripts to do COM ;; related actions on Outlook to get and replace text in the ;; reply/compose boxes allowing it to be edited in Emacs ;; (defvar mno-get-outlook-body "tclsh C:\\Userdata\\Tcl\\grabOutlookMessage.tcl") (defvar mno-put-outlook-body "tclsh C:\\Userdata\\Tcl\\putMessageInOutlook.tcl") (defvar mno-outlook-default-justification 'full) (global-set-key "\C-coe" 'mno-edit-outlook-message) (global-set-key "\C-cos" 'mno-save-outlook-message) (defun mno-edit-outlook-message () "* Slurp an outlook message into a new buffer ready for editing The message must be in the active Outlook window. Typically the user would press the Reply or Reply-all button in Outlook then switch to Emacs and invoke \\[mno-edit-outlook-message] Once all edits are done, the function mno-save-outlook-message (invoked via \\[mno-save-outlook-message]) can be used to send the newly edited text back into the Outlook window. It is important that the same Outlook window is current in outlook as was current when the edit was started when this command is invoked." (interactive) (save-excursion (let ((buf (get-buffer-create "*Outlook Message*")) (body (shell-command-to-string mno-get-outlook-body))) (switch-to-buffer buf) (message-mode) ; enables automagic reflowing of text in quoted ; sections (setq default-justification mno-outlook-default-justification) (setq body (replace-regexp-in-string "\r" "" body)) (delete-region (point-min) (point-max)) (insert body) (goto-char (point-min))))) (defun mno-save-outlook-message () "* Send the outlook message buffer contents back to Outlook current window Unfortunately, Outlook 2000 then renders this text as Rich Text format rather than plain text, overriding any user preference for plain text. The user then needs to select Format->Plain text in the outlook compose window to reverse this. Outlook 2002 apparently has a BodyFormat parameter to control this." (interactive) (save-excursion (let ((buf (get-buffer "*Outlook Message*"))) (set-buffer buf) (shell-command-on-region (point-min) (point-max) mno-put-outlook-body) (set-buffer-modified-p 'nil) ; now kill-buffer won't complain! (kill-buffer "*Outlook Message*")))) (provide 'outlookedit) ;;;end of file outlookedit.el
The grab and put functions used above.
#!/bin/sh # Emacs please open this in -*-Tcl-*- mode # do not remove this backslash! -> \ exec tclsh $1 ${1+"$@"} # # loosely based on Python code from # http://disgruntled-programmer.com/notes/emacs-with-outlook.html # package require tcom set body [read stdin] # # find Outlook:- if { [catch {::tcom::ref getactiveobject Outlook.Application} o] } { puts "Couldn't find Outlook via COM: $o" exit 1 } # get the current item:- if { [catch {$o -get ActiveInspector} a] } { puts "Couldn't get the ActiveInspector for Outlook via COM: $a" exit 2 } if { [catch {$a -get CurrentItem} i] } { puts "Couldn't get the CurrentItem for Outlook via COM: $i" exit 3 } # and finally replace its body if { [catch {$i -set Body $body} err] } { puts "Couldn't replace the Body via COM: $err" exit 4 } # The following (untested) might convert back from RTF in Outlook 2002 catch {$i -set BodyFormat 1} # that's it
and,
#!/bin/sh # Emacs please open this in -*-Tcl-*- mode # do not remove this backslash! -> \ exec tclsh $1 ${1+"$@"} # # loosely based on Python code from # http://disgruntled-programmer.com/notes/emacs-with-outlook.html # package require tcom # # find Outlook:- if { [catch {::tcom::ref getactiveobject Outlook.Application} o] } { puts "Couldn't find Outlook via COM: $o" exit 1 } # get the current item:- if { [catch {$o -get ActiveInspector} a] } { puts "Couldn't get the ActiveInspector for Outlook via COM: $a" exit 2 } if { [catch {$a -get CurrentItem} i] } { puts "Couldn't get the CurrentItem for Outlook via COM: $i" exit 3 } # and finally slurp its body if { [catch {$i -get Body} body] } { puts "Couldn't retrieve body from CurrentItem via COM: $body" exit 4 } # # spew it out to stdout # puts $body # that's it