/*
*/ import lotus.domino.*; // Notes stuff import java.util.*; // what's your Vector, Victor? import java.io.*; // we're working with files here import net.freeutils.tnef.*; // TNEF decoder ( http://www.freeutils.net/source/jtnef ) import javax.swing.*; // messagebox to the user at the end // these are necessary for the optional getMimeMessage method import net.freeutils.tnef.mime.*; import javax.activation.*; import javax.mail.internet.*; /** * This is a Lotus Notes agent to be placed in mail files and run against selected * docs that were sent from Outlook/Exchange and have all of their attachments and * rich text wrapped up in an unreadable Winmail.dat or ATT####.dat file. * * It extracts the attachments embedded in the winmail.dat or ATT0001.dat (or other * TNEF-formatted files), puts them in a folder, and attaches them to a new message * in the inbox of your mail file. This uses the open-source JTNEF decoder library, * available at http://www.freeutils.net/source/jtnef . You will need to include that jar * file in the agent that contains this code, by using the "Edit Project" button at the * bottom of the agent window. Here's how to set everything up: * * 1. Go to http://www.freeutils.net/source/jtnef and download the jtnef library * 2. Unzip the file on your computer * 3. Open your Notes mail file in Domino Designer * 4. Go to the Agents section and create a new Java agent * 5. At the bottom of the agent screen, click "Edit Project" and browse to the "lib" * directory of the jtnef file you downloaded and unzipped * 6. Click the "Add/Replace All" button to include the jar file with your project * (if you don't see it, you either don't have the "archive" file type checked, or * you're in the wrong directory) * 7. Click OK and go back to the agent * 8. Delete all the code that's there, and copy and paste the contents of this file * 9. Call the agent something meaningful, and make sure it's set to run against "all * selected docs" * 10. Save and close * 11. Go to your inbox in the regular Notes client * 12. Select one or more messages that have that stupid winmail.dat or att0001.dat * file in them * 13. Run your new agent * 14. See if anything happens * * This agent is designed to operate against all selected docs in a view or folder of * your Lotus Notes e-mail database. It will check each doc, and scan all the * attachments in the Body field, and any attachments that are valid TNEF files will * have their contents exported to the location specified in the extractPath variable. * The extracted/converted files will then be attached to a new copy of the original * e-mail message, which will be copied to your Inbox folder. * * I've only tested this with Notes 6.51. The JTNEF code uses javax.mail classes (which * are included with Notes 6 by default), and I added a Swing messagebox, so I'm * not sure if this code will work in R5 or not. If not, you could always remove the * messagebox and try to include an old version of javax.mail (if there is one that's * compatible with jre 1.1.8), and give it a go. * * If you find this agent useful, you should consider making a donation to Amichai * Rothman, the author of the JTNEF library, at http://www.freeutils.net . Without all the * work he did writing that code and making it freely available, none of this would * be possible. It's also worth noting that the JTNEF library has been released under * the GNU General Public License agreement, and you should read the license that * is linked to on the freeutils site if you plan to distribute or modify this code. * * The only change to this code from 1.0 to 1.1 was the addition of the line: * eo.recycle(); * to ensure that the temporary file that gets created when you get the EmbeddedObject * attachment as an InputStream is deleted when you're done with it. Otherwise, you can * end up with a bunch of eo###tm files in your Notes program directory. * * version 1.2 * December 12, 2004 * Julian Robichaux -- http://www.nsftools.com */ public class JavaAgent extends AgentBase { // set the debug level to 1 or 2 for additional output from this agent private final int DEBUG_LEVEL = 0; public void NotesMain() { try { // we'll be telling the user what happens with a Swing dialog box below, // so let's go ahead and set the look and feel to be the system default String nativeLF = UIManager.getSystemLookAndFeelClassName(); try { UIManager.setLookAndFeel(nativeLF); } catch (Exception uie) { } // grab the selected documents Session session = getSession(); AgentContext agentContext = session.getAgentContext(); Database db = agentContext.getCurrentDatabase(); DocumentCollection dc = agentContext.getUnprocessedDocuments(); Document doc = dc.getFirstDocument(); String message = ""; while (doc != null) { // set some of the variable defaults String subject = doc.getItemValueString("Subject"); Vector fileList = new Vector(); int count = 0; // per Wayne Hoar's suggestion (http://www.vulcangroup.com), // make sure that the Subject line isn't null if (subject == null) subject = "No Subject"; // create a nice directory name to store the extracted files to String dirSubject = subject; char[] badDirChars = (new String("\\/?:|*\"<>")).toCharArray(); for (int i = 0; i < badDirChars.length; i++) dirSubject = dirSubject.replace(badDirChars[i], '_'); if (dirSubject.length() > 30) dirSubject = dirSubject.substring(0, 30) + "..."; String extractPath = "C:\\TNEF Files\\" + doc.getNoteID() + " (" + dirSubject + ")\\"; File extractDir = new File(extractPath); // grab the Body field of the current document, and check each attachment RichTextItem body = (RichTextItem)doc.getFirstItem("Body"); Vector v = body.getEmbeddedObjects(); Enumeration e = v.elements(); while (e.hasMoreElements()) { EmbeddedObject eo = (EmbeddedObject)e.nextElement(); if (eo.getType() == EmbeddedObject.EMBED_ATTACHMENT) { // make sure the extractPath directory exists extractDir.mkdirs(); String errorMsg = ""; try { // try to convert the file to a TNEF stream (if the file is not a valid // TNEF file, we'll end up in the catch block). The TNEF.extractContent // method will send all the attachments in the TNEF file to our // extractPath TNEFInputStream in = new TNEFInputStream(eo.getInputStream()); Message tnefMsg = new Message(in); fileList = extractContentCustom(tnefMsg, extractPath, count); // if we're debugging, also output some information about the tnef file if (DEBUG_LEVEL > 0) { String debugFileName = extractPath + eo.getName() + ".info.doc"; FileWriter out = new FileWriter(debugFileName); out.write(tnefMsg.toString()); fileList.add(debugFileName); } // if we're debugging, see what the MIME message would have translated into if (DEBUG_LEVEL > 1) { String mimeFile = getMimeMessage(tnefMsg, extractPath, fileList.size()); if (mimeFile.length() > 0) fileList.add(mimeFile); } count += fileList.size(); in.close(); eo.recycle(); } catch (Exception tne) { System.err.println("Error processing " + eo.getName()); tne.printStackTrace(); errorMsg = tne.getMessage(); } } } // if we ended up extracting any files, we'll forward the e-mail back to ourselves // with the extracted files attached if (count > 0) { try { // create a new copy of the original e-mail Document copyDoc = db.createDocument(); doc.copyAllItems(copyDoc, true); // attach the converted files to the end RichTextItem bodyCopy = (RichTextItem)copyDoc.getFirstItem("Body"); bodyCopy.addNewLine(2); bodyCopy.appendText("==============================================="); bodyCopy.addNewLine(2); bodyCopy.appendText("Here are the files that were extracted from the *.dat attachments"); bodyCopy.addNewLine(2); String[] files = extractDir.list(); for (int i = 0; i < files.length; i++) { bodyCopy.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, extractPath + files[i], null); } // and try to add the new doc to the Inbox folder //doc.send(session.getUserName()); copyDoc.replaceItemValue("Subject", "(Converted) " + subject); copyDoc.save(); copyDoc.putInFolder("($Inbox)"); copyDoc.recycle(); message += "\nCopied message '" + subject + "' to your Inbox, with converted files attached\n"; } catch (Exception se) { message += "\nError copying converted message: " + se + "\n"; } // optionally delete the directory with all the files in it when we're done if (DEBUG_LEVEL == 0) deleteDir(extractDir); } else { // if we didn't end up extracting anything, delete the extractPath that // may have been created deleteDir(extractDir); message += "\nNo valid TNEF attachments found in message '" + subject + "'\n"; } // next doc, please Document nextDoc = dc.getNextDocument(); doc.recycle(); doc = nextDoc; } // tell the user what we did when we're all done if (message.length() == 0) message = "No files were processed"; JOptionPane.showMessageDialog(null, message); } catch(Exception e) { // oops, this can't be good... e.printStackTrace(); try { JOptionPane.showMessageDialog(null, e.getMessage()); } catch (Exception msge) { } } } public static boolean deleteDir(File dir) { // delete a directory and any files or subdirectories beneath it // from http://javaalmanac.com/egs/java.io/DeleteDir.html if (dir.isDirectory()) { String[] children = dir.list(); for (int i=0; i