automating Outlook [repost]

Wesley J. Chun wesc at deirdre.org
Wed Aug 28 15:04:35 EDT 2002


klassa at ipass.net wrote in message news:<th7fgbl4lafs82 at corp.supernews.com>...
>
> From: klassa at employees.org
> Newsgroups: comp.lang.python
> Subject: automating Outlook [repost]
> Date: Tue, 29 May 2001 15:19:39 -0000
>
> [ I managed to let this one slip by without a subject last time.
>   Sorry for the repost. ]
> 
> If you're interested in my motivation for this, see the footnote[1].
> 
> Bottom line: I wanted to be able to edit my drafts, in Microsoft
> Outlook, with the editor of my choice.  In this case, Emacs.  The
> following script does this for me...  You tell Outlook to start a
> reply, and then you hit the "Edit" button that this script creates.
> It sucks the text out of Outlook, puts it into Emacs (you need to
> tweak the paths), then puts it back into Outlook when you're finished.
> 
> The thing I'd like to add, still, is the ability to put an icon into
> the system tray, rather than have it be a free-floating application
> with a button.  The sample code I found was a bit hard to grok (given
> that I'm not a Windows programmer, nor more than a novice python
> programmer).  If you know how to do that, and would care to add it in,
> I'd love to hear from you. :-)
> 
> The only snag I've found is that you can't run the script without
> having run makepy.py first, to make the Outlook library available.
> The full dynamic dispatch mechanism doesn't work, for some reason.
> 
> That said, here's the script.  It's undoubtedly ugly, but the
> important stuff is there. :-)
> 
> -- snip --
> 
> import win32com.client
> import os
> import Tkinter
> from Tkconstants import *
> 
> def launch():
> 
>     # Default to an empty body.
> 
>     body = ""
> 
>     # Get a handle to Outlook.
> 
>     o = win32com.client.Dispatch("Outlook.Application")
> 
>     # Work our way down to the reply (a "MailItem").
> 
>     insp = o.ActiveInspector()
>     if insp == None: return
>     item = insp.CurrentItem
>     if item == None: return
> 
>     # Grab the body.
> 
>     body = item.Body
> 
>     # Should make this a guaranteed-unique file...
> 
>     fh = open("c:/temp/editor.txt", "w")
> 
>     # Write the body.  Had to add a try/except because of ASCII
>     # encoding problems when the reply is in one of Outlook's more
>     # funky formats.
> 
>     try:
>         fh.write(body)
>     except:
>         fh.write("")
> 
>     fh.close()
> 
>     # Launch emacs to edit the file.  Should make this configurable.
>     # Note that by default, Emacs seems to come up in Unix mode, and
>     # so the ^M characters are visible.  A persistent, bound-to-a-key
>     # Emacs macro takes care of that nicely, however.
> 
>     os.spawnv(os.P_WAIT,
>               "d:/Editors/emacs-20.7/bin/emacs",
>               ["d:/Editors/emacs-20.7/bin/emacs", "c:/temp/editor.txt"])
> 
>     # Read the result back into memory.
> 
>     fh = open("c:/temp/editor.txt", "r")
>     body = fh.read()
>     fh.close()
> 
>     # Store it as the body of the reply.
> 
>     item.Body = body
> 
> 
> # Create a single button that, when clicked, takes care of the rest.
> 
> if __name__=='__main__':
> 
>     tk = Tkinter.Tk()
> 
>     frame = Tkinter.Frame(tk, relief=RIDGE, borderwidth=2, background="white
> ")
>     frame.pack(fill=BOTH, expand=1)
> 
>     button = Tkinter.Button(frame, text="Edit", command=launch,
>                             background="white")
>     button.pack(fill=BOTH, expand=1)
> 
>     tk.mainloop()    
> 
> -- snip --
> 
> Comments welcomed.
> 
> John
> 
> [1] Every so often, I make it a point to try some other language or
> tool, so as to widen my perspective a bit.  For example, I'm an ardent
> emacs fan, but I've learned vi so that I'm able to edit anywhere
> (well, on any Unix machine), and so as to appreciate other ways to
> edit files.
> 
> In this same way, I decided to try Microsoft Outlook.  I'm an exmh
> hacker/fan (have been, for years), but thought I'd try Outlook just to
> see what my business/marketing/managements friends have to deal
> with. :-)
> 
> My one biggest gripe is that you can't use the editor of your choice
> when you edit your drafts.  The Outlook editor is okay...  I mean,
> it's like every other Microsoft editor -- that is, reasonable, but
> lacking features (like the ability to reflow your text).
> 
> So, I decided to give Outlook the ability to use the editor of my
> choice.  I'm also a perl fan, but discovered that what I wanted to do
> was a lot harder (or at least seemed to be) in perl.  So, I turned to
> python.  Python seems to have a lot of nice Win32 support...  This is
> maybe my fifth or sixth small python script, and I'm liking it
> (python) more and more.


scrolling forward a year and a quarter...

i've taken John's cool tool and added a ton more comments for
those of you who *really* want to get to the meat of the matter
as well as some important code to map characters to Emacs/Vi*.
below's the 0.2 release of outlook.pyw.

it's a nice tool for those forced to use a Win32 env. at work.
feedback, improvements, suggestions, and comments welcomed!

-wesley

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

"Core Python Programming", Prentice Hall, 2001
    http://starship.python.net/crew/wesc/cpp/

Silicon Valley-San Francisco Bay Area Python Users Group (BayPIGgies)
    http://www.baypiggies.net

wesley.j.chun :: wesc at deirdre.org
cyberweb.consulting : henderson, nv : cyberweb at rocketmail.com
http://roadkill.com/~wesc/cyberweb/

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#!/bin/env python
'''
outlook.pyw (OutLook editor launcher) -- allows one to edit an open e-mail
	mesg from Outlook using Emacs or *Vi* rather than "Notepad--".  :-)
	NOTE:  requires Python 1.6 and newer (use of string methods)

created by John Klassa (klassa at employees.org) on 2001 May 29
updated by Wesley Chun (cyberweb at rocketmail.com) on 2002 Feb 28

$Id: outlook.pyw,v 0.2 2002/08/28 18:04:06 wesc Exp wesc $
'''

from os import spawnv, P_WAIT, unlink
from tempfile import mktemp
from Tkinter import Tk, Button, Frame, Label
from Tkconstants import *
from win32com.client import Dispatch

def launch():
    '''launch() spawns your favorite editor to edit the Outlook compose 
    window (either new or reply), then returns that data to Outlook...
    change the 'ed' variable to switch editors.'''

    # Get a handle to Outlook.
    o = Dispatch("Outlook.Application")

    # Work our way down to the reply (a "MailItem").
    insp = o.ActiveInspector()
    if insp == None: return
    item = insp.CurrentItem
    if item == None: return

    # Grab the message body in the reply.
    body = item.Body
    
    # Write the body... need to "encode" the string because Outlook uses
    # Unicode with bunch of unprintables (ASCII chars > 128).  Also, since
    # we are going from DOS2UNIX2DOS, we have the \r\n vs \n issue, re-
    # sulting in those fabulous ^M characters.  A persistent, bound-to-a-
    # key Emacs macro takes care of that nicely, but the solution imple-
    # mented here is to just wipe the '\r's now, then add them back when
    # we reread this file back before returning the body to Outlook.
    tmp = mktemp()			# generate a unique tmp filename
    fh = open(tmp, "w")
    fh.write(body.encode('ascii', 'ignore').replace('\r\n', '\n'))
    fh.close()

    # Launch editor to edit the file (should make this configurable).
    #ed = r"d:\emacs-20.7\bin\emacs"		# emacs editor binary
    ed = r"c:\progra~1\vim\vim60\gvim.exe"	# *vi*  editor binary
    spawnv(P_WAIT, ed, [ed, tmp])

    # Read edited file back into memory, restore '\r's, and kill tmp file.
    fh = open(tmp)
    body = fh.read().replace('\n', '\r\n')
    fh.close()
    unlink(tmp)
    
    # Store it as the body of the reply.  Note that we are merely
    # sending this data back to Outlook -- it does not prevent MS from
    # mucking with your message.  For example, it may add your signature
    # again, or it may remove newlines.  MS software... what can you do?
    item.Body = body

# Create the Tk(inter) GUI app with the appropriate label and buttons.
if __name__=='__main__':
    tk = Tk()
    f = Frame(tk, relief=RIDGE, borderwidth=2).pack()
    Label(f, text="Outlook Edit Launcher v0.2").pack()
    Button(f, text="Edit", fg='blue', command=launch).pack(fill=BOTH)
    Button(f, text="Quit", fg='red', command=tk.quit).pack(fill=BOTH)
    tk.mainloop()



More information about the Python-list mailing list