/*
*/
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