#!/usr/bin/ruby -w # # Syntax: # tnef_transform.rb [FILE] # # If FILE is a mail message that contains a winmail.dat, it is unpacked, its # attachments are reattached to the message and the new message is spit to # stdout. # # 2004 by Joshua Kwan . This code is in the public # domain, but it would be cool if you sent me any improvements. # # WARNING: As of Dec 17, 2004, a change to the rmail source is required # for this code to work. See # # http://triplehelix.org/~joshk/message-delete_part.diff require 'rmail'; require 'base64'; require 'mime/types'; fobj = []; if ARGV.size > 0 filename = ARGV[0]; fobj = File.open(filename, 'r'); else fobj = STDIN; end # Back it up so we can spit it back out if necessary. # Otherwise I'd just do Parser.read(fobj) orig = fobj.read; if fobj != STDIN fobj.close; end message = RMail::Parser.read(orig); if not message.multipart? # Do nothing if not multipart (ie no winmail.dat) print orig; exit(0); end j = 0; # Enter a tempdir dirname = ""; dir = []; i = 0; begin dirname = sprintf("/tmp/tnef_transform%d.%d", $$, i); Dir.mkdir(dirname); rescue i += 1; # wtf if i > 65535 STDERR.puts "I give up! I can't create a temporary directory."; print orig; exit(1); end retry; end Dir.chdir(dirname); # Keep track if there were actually any changes (new attachments) to the message. done_something = 0; message.each_part { |part| if part.header['Content-Type'] =~ /^application\/ms-tnef/ tnef_pipe = IO.popen("tnef", "w+"); if not tnef_pipe STDERR.puts "Could not decode, 'tnef' is not available!"; print orig; exit(1); end # TNEF will do its thing and dump everything in our temp dir. tnef_pipe.print(part.decode); tnef_pipe.close; # Now, add the new parts to the message. d = Dir.open("."); d.each { |name| next if name == ".." or name == "."; nfobj = File.open(name, 'r'); # First, base64 encode it :/ encodednf = Base64.encode64(nfobj.read); npart = RMail::Message.new; # Determine MIME type for this. t = MIME::Types.type_for(name); if t.size npart.header.set('Content-Type', t[0], 'name' => name); else # lame fallback, but what can you do? npart.header.set('Content-Type', 'text/plain', 'name' => name); end npart.header.set('Content-Transfer-Encoding', 'base64'); npart.body = encodednf; message.add_part(npart); nfobj.close; File.unlink(name); # Real change to be made done_something = 1; } # delete winmail.dat message.delete_part(j); end j += 1; } # doesn't matter where, we just need to get out Dir.chdir("/"); Dir.rmdir(dirname); if done_something == 1 print message.to_s; else print orig; end