Outlook has a feature which allows revocation of aleady sent mails. I do not like this feature as it tampers with reliability of received mails. Thus, I developed a simple mechanism to at least partially keep mails whenever received and whatever Outlook decides to do with them later.

# The feature and a social mini-evaluation of what it does to interaction

Think classic pen-and-paper-mail. The mailman puts a letter into your mailbox. Some minutes later, he returns with a gripper and carefully removes that mail from your mailbox. If you have fetched your mail before he returns, he breaks into your house (he surely has the keys) and grabs it from your desk. That is what Microsoft Outlook's mail recall feature feels like, at least to me.
One may argue, this feature can help reduce unnecessary mails and irritation resulting from such. I argue, it just hides things otherwise needing an explaination, lowering the barrier to cowardness.
If I make a mistake, the grown-up way to deal with it is admitting it and learning from it. Apologize, if necessary. But not hide it -- my two cents and my expectation towards other grown-ups. Unfortunately, there are many Microsoft-based corporate environments with heavy use of Outlook/Exchange ("if it hasn't Exchange, it's not serious business", an better unnamed manager). And where admitting an error seems to be an unusual way to deal with it.

A personal word. Trigger for an article like this could have been a typical workplace incident as it may take place at every workplace at which mistakes occurr. Lucky for me, at my workplace no one (especially managers) makes mistakes -- phew! The hypothetical incident could be a mistake which resulted in colleagues receiving an excel file containing details about personal accounting by means of an e-mail which then is -- instead of admitting the mistake -- silently (and with a tought of "hopfully no one will notice!" revoked). Unfortunately, attachments may survive. Some workers may see saw the mail immediately, open the attached file and kept it open. When the mail is revoced some minutes later, it will be deleted from all e-mail accounts, including attachments. But while Outlook is quite serious when it comes to revoking mails (it closes the window of the said mail if open), it has a problem when it comes to attachments. To open an attachment, the file is stored somewhere locally. And this file is given as parameter to (say) Microsoft Excel. Which then locks the file exclusively. Bra-vo for this taking place in Windows World, where you can't delete an opened document. Fortunately, Outlook is wise enough not to force-kill the Excel instance showing the attachment. Eventually, the document survives.
Applause to the hypothetic person making all this possible, resulting in me swearing this will not happen again. Fool me once, shame on you -- fool me twice...

# Getting things out of Outlook

I want to keep at least a trace of each mail. Something I can take to court or clip under my co-workers wipers.
All it needs is a off-band-copy (off-band as in some location Outlook has no deep knowledge about) of every incoming mail, ideally created at the moment it is received (whatever "receive" means within Exchange protcol world) -- before it can be revoked. As I have no opportunity to fiddle with the exchange-server, the solution has to be found using only the client (i.e. Microsoft Outlook).

Handling incoming Mails? Something "Rules" can be defined for. Unfortunately, saving each incoming Mail to a file is not offered as rule action. There would be "run an application" -- but I cannot install software on my work computer. At least I should not be able to do that. The only thing that's really working is "print". In this case, Outlook will print each incoming mail (and its attachments!) to the system's default printer. We can use this rule/action-combination to get a replica of everything received.

What we have by now is that every mail is printed on the system's default printer. Prepare for the next 500-page PDF sent from the sales guys. But, nevertheless, incoming mails are out of Outlook's reach. Success? Only if you really do like paperwork. You may also solder some piece of hardware which emulates a printer and writes transmitted contents to external storage.... hey, I like that *heats up the soldering iron*.

However, the resulting rule is quite simple:

On receiving a new mail (specify no further criteria), print mail (specify no exceptions).


# Virtual archive printer

OK, this isn't really much of a tough decision, just print things to file and everything will work out great. That's how I continued, too -- I used the built-in XPS printer. It works great, I get a copy of everything incoming. But beware: From this point on, whenever you receive an e-mail, you will be harrassed with a shitty nagging dialog box stealing focus and interrupting your work -- greetings from your virtual printer, where shall the new file be written to exactly? And no, unfortunately you cannot define rules for automatic file name creation.
That is, to say the least, slightly annoying. And there are exactly two options how to get out of this: Either the virtual printer needs to select the file name or you need to change the printer port. Welcome to the dark and scary world of Windows printing details! Honestly, when was the last time you in-depth looked at what Windows exactly does when it comes to printing?

Each print job is processed through a chain of entities (presented not in the correct order -- simpley because the order changes with the way you want to look at it):

• User program, printing a document using the API
• The spooler which then takes the job for the specified printer and keeps it until the printer is ready (otherwise it would mix up with other concurring print jobs)
• The printer driver which converts GDI-calls into something the printer does understand -- this may be some PCL, some printer-specific thin wrapper around the GDI-calls or something common as PostScript. Or XPS.
• The printer port which is the most hardware-level part of printing as it arranges the physical contact between the printer driver and the printer as physical machine on your desk. It can be something as "LPT1:" (good old times) or "FILE:" (which will result in a dialog asking for a file name).
To solve the filename problem, there is more than one way. Either the printer driver itself writes the job to a file whose name it can determine itself (this is what XPS seems to do -- it also presents a real "Save File"-dialog, not just the little input line that comes with FILE: printer port). However, there are two solutions to the orignal problem hidden in printer ports. Use network or use a program connected to a port.

# Network to the rescue!

If you have shell access to a unix system with installed netcat and ps2pdf (yeah, PDF is so much more fun than XPS, sorry Microsoft folks) which you can reach from your Windows machine, you have won. All it needs is to set up a new network printing port which points at, say yourhost:3333 and on yourhost, you can have something among the lines of

while [ true ]
do
nc -l 3333 | ps2pdf - outbuf.tmp
mv outbuf.tmp date +%Y%M%d-%H%m%S-uuidgen.pdF
done

This little piece of poetry will accept network connections on port 3333 TCP and forward their input to good old ps2pdf. Once the connection is closed, the tempfile is moved to a file with receiving timestamp plus a UUID in it. The temporary file is used as otherwise the timestamp would be the timestamp of the moment the command was started -- aka the moment, the listening begun. A date, you probably won't search for. The UUID is added to prevent filename collisions (in case there would be two print jobs within the same second). The windows spooler does not require the "printer" to be capable of paralell connections. In fact, I'm not even sure all printers support those ;)
However, this setup can be made either local or distributed -- but I would not really recommend using it very remote. Especially if things take place in a corporate environment, this would be a massive data leak. Every incoming mail sent unencrypted in PS to some private host -- OPSEC horror 1o1. On a local host (if one has nc and ps2pdf on windows, that is) it could work. It can also be used as a central printlogging facility, without the whole Outlook stuff, just to have a central archive.
However, it's not how I've done it. But it works great (just tested it).

# Redmon and a program to the rescue!

By default, Windows does not provide a printer port which allows for redirection to another program. That's where redmon kicks in. It can be found at http://pages.cs.wisc.edu/~ghost/redmon/ and is provided with numerous free PDF generating programs (e.g. FreePDF http://freepdfxp.de/). If you have this tool ony your computer, you can redirect printer output to aribitrary programs.
Next thing would be the need for a program that takes the printer output from STDIN and writes it to an appropriate file (and ideally converts it to PDF, while we're at it). Since the setting is corporate, you probably won't be allowed to use your homebrew Delphi program for it (unless... nonexec_rundll32.html). But you can always write programs, even under Microsoft Windows. You can write them as PowerShell, Batch, or VBScript. I went for VBScript for good old times sake (my programming journey started with TurboBASIC). It resulted in the following script, which also uses Ghostscript to convert the received PS to PDF:

' Get a GUID, will be used to prevent collisions in file names
Function CreateGUID
Dim TypeLib
Set TypeLib = CreateObject("Scriptlet.TypeLib")
CreateGUID = Mid(TypeLib.Guid, 2, 36)
End Function

Dim Input
Dim Base
Dim dat
Dim cdMon
Dim cdDay
Dim cdHour
Dim cdMin
Dim cdSek
Dim curDate
Dim fso
Dim fldr
Dim UID
Dim PDFFilename
Dim objShell

' Read all from STDIN

' Stubble the filename together
base = "Y:\path\to\printlogs\"

dat = now

cdMon = Month(dat)
cdDay = Day(dat)
cdHour= Hour(dat)
cdMin = Minute(dat)
cdSec = Second(dat)

' Yeah, we will create the filename the really painful way. Think printf() ;)
if (len(cdMonth) < 2) then cdMon = "0" & cdMon
if (len(cdDay) < 2) then cdDay = "0" & cdDay
if (len(cdHour) < 2) then cdHour = "0" & cdHour
if (len(cdMin) < 2) then cdMin = "0" & cdMin
if (len(cdSec) < 2) then cdSec = "0" & cdSec

curDate =  Year(Date) & cdMon & cdDay & "," & cdHour &  cdMin & cdSec

set fso = createobject("Scripting.FileSystemObject")

set fldr = fso.getFolder(base)

UID = createGUID

filename = base & curDate & "--" & UID & ".ps"

' barf stdin to file

set f = fso.createtextfile(filename)
f.write(input)
f.close

' convert to pdf for convenience
' and give parameters not to leave window open...

pdffilename = base & curDate & "--" & UID & ".pdf"

set objShell = WScript.CreateObject("WScript.shell")
objShell.run """C:\path\to\gs\bin\gswin32.exe"" -sDEVICE=pdfwrite -sOutputFile=" & pdffilename & " -dNOPAUSE -dBATCH " & filename

The script is called as cscript.exe scriptname.vbs, use it with a PostScript printer (there are numerous printer drivers, look for those with a "PS" in their model name. You may want to choose a color printer...

The only slightly annoying thing is that every incoming mail is now announced by two windows who steal focus for a reasonable short amount of time: The shell window for the cscript process and a window associated with the GS process in which the conversion progress can be monitored.
However, this Solution works great, too.

# Permissions

Now, the whole thing is set in a corporate environment. Usually, you should not be granted administrative privileges on your computer. Thus the question remains: Can this be set up "silently"?
Seems it can -- you need administrative permissions to install a new printer port class -- not to install a new printer port from an existing class!

# Cave!

If you define a rule to print every incoming e-mail including its attachments, you implicitly define a role to open all incoming attachments. Think of spam and/or virus loaded mails and whether you *really* want to do this. Microsoft Office and Adobe Acrbat will not be able to print something without opening it. OTOH, having just the mail without the attachment in your archive is half the fun. And any good risk acceptance conference should be started with the words "no risk -- no fun."

Be aware that some programs may remember the last printer and reuse it instead of defaulting back to the system's printer. As you may sometimes want to print to a sheet of paper, you may select your real printer and go on. And then you have the trouble: Your sheet is properly printed from a PDF, you forget about it. Then an e-mail with a 200-page PDF attached arrives, the Outlook ruleset kicks in, the mail is printed to the virtual printer, the PDF is handed to Adobe Reader with the command line switch to print it -- and it prints to the last used printer. Which is the noisy, rumbling, paper-chewing box aside your desk. If you're lucky. In a big company, it may also be the printer in NY while you're in LA. Just hope the 200 pages weren't too confidential. Just hope no one will find out it was you, printing that 200 page brochure on, say, "plug'n'play super happy fun devices" with full color on black background.

I would have loved to do this with a simple Text/Generic-Printer (for the sake of greppability of the results) but sadly Outlook seems to have some trouble with Text/Generic printers.

# Side note

rundll32 printui.dll,PrintUIEntry is a charm.

# Update 26.07.2015

Attachments are not opened completely automaticaly in any case. In case of potential dangerous file types (Microsoft Office related file types in any case, that is), a dialog is shown asking whether the file shall acutally be opened to print. The file can of course only be printed if opened. Whatever the case, things turn kind of ugly with zip-files and the like.

Stichworte:

Impressum