More work on the recipient related chunks, including a helper method to do best-effort finding of the recipients email address

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@897213 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2010-01-08 14:26:27 +00:00
parent 52695c1811
commit 7ae86fab09
7 changed files with 197 additions and 18 deletions

View File

@ -174,6 +174,23 @@ public class MAPIMessage {
} }
/**
* Returns the recipient's email address, checking all the
* likely chunks in search of it.
*/
public String getRecipientEmailAddress() throws ChunkNotFoundException {
if(recipientChunks == null) {
throw new ChunkNotFoundException("No recipients section present");
}
String email = recipientChunks.getRecipientEmailAddress();
if(email != null) {
return email;
} else {
throw new ChunkNotFoundException();
}
}
/** /**
* Gets the conversation topic of the parsed Outlook Message. * Gets the conversation topic of the parsed Outlook Message.
* This is the part of the subject line that is after the RE: and FWD: * This is the part of the subject line that is after the RE: and FWD:

View File

@ -61,4 +61,16 @@ public class ByteChunk extends Chunk {
public void setValue(byte[] value) { public void setValue(byte[] value) {
this.value = value; this.value = value;
} }
/**
* Returns the data, formatted as a string assuming it
* was a non-unicode string.
* If your data isn't in fact stored as basically
* ASCII, don't expect this to return much of any
* sense....
* @return
*/
public String getAs7bitString() {
return StringChunk.parseAs7BitData(value);
}
} }

View File

@ -28,15 +28,62 @@ import java.util.List;
public final class RecipientChunks implements ChunkGroup { public final class RecipientChunks implements ChunkGroup {
public static final String PREFIX = "__recip_version1.0_#"; public static final String PREFIX = "__recip_version1.0_#";
public static final int RECIPIENT_NAME = 0x3001;
public static final int DELIVERY_TYPE = 0x3002;
public static final int RECIPIENT_SEARCH = 0x300B; public static final int RECIPIENT_SEARCH = 0x300B;
public static final int RECIPIENT_EMAIL = 0x39FE; public static final int RECIPIENT_EMAIL = 0x39FE;
/** TODO */ /** TODO */
public ByteChunk recipientSearchChunk; public ByteChunk recipientSearchChunk;
/** TODO */ /**
* The "name", which could be their name if an
* internal person, or their email address
* if an external person
*/
public StringChunk recipientNameChunk;
/**
* The email address of the recipient, but
* isn't always present...
*/
public StringChunk recipientEmailChunk; public StringChunk recipientEmailChunk;
/**
* Normally EX or SMTP. Will generally affect
* where the email address ends up.
*/
public StringChunk deliveryTypeChunk;
/**
* Tries to find their email address, in
* whichever chunk holds it given the
* delivery type.
*/
public String getRecipientEmailAddress() {
if(recipientEmailChunk != null) {
return recipientEmailChunk.getValue();
}
// Probably in the name field
if(recipientNameChunk != null) {
String name = recipientNameChunk.getValue();
if(name.indexOf('@') > -1) {
// Strip leading and trailing quotes if needed
if(name.startsWith("'") && name.endsWith("'")) {
return name.substring(1, name.length()-1);
}
return name;
}
}
// Check the search chunk
if(recipientSearchChunk != null) {
String search = recipientSearchChunk.getAs7bitString();
if(search.indexOf("SMTP:") != -1) {
return search.substring(search.indexOf("SMTP:") + 5);
}
}
// Can't find it
return null;
}
/** Holds all the chunks that were found. */ /** Holds all the chunks that were found. */
private List<Chunk> allChunks = new ArrayList<Chunk>(); private List<Chunk> allChunks = new ArrayList<Chunk>();
@ -56,9 +103,15 @@ public final class RecipientChunks implements ChunkGroup {
// TODO - parse // TODO - parse
recipientSearchChunk = (ByteChunk)chunk; recipientSearchChunk = (ByteChunk)chunk;
break; break;
case RECIPIENT_NAME:
recipientNameChunk = (StringChunk)chunk;
break;
case RECIPIENT_EMAIL: case RECIPIENT_EMAIL:
recipientEmailChunk = (StringChunk)chunk; recipientEmailChunk = (StringChunk)chunk;
break; break;
case DELIVERY_TYPE:
deliveryTypeChunk = (StringChunk)chunk;
break;
} }
// And add to the main list // And add to the main list

View File

@ -54,11 +54,7 @@ public class StringChunk extends Chunk {
switch(type) { switch(type) {
case Types.ASCII_STRING: case Types.ASCII_STRING:
try { tmpValue = parseAs7BitData(data);
tmpValue = new String(data, "CP1252");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Core encoding not found, JVM broken?", e);
}
break; break;
case Types.UNICODE_STRING: case Types.UNICODE_STRING:
tmpValue = StringUtil.getFromUnicodeLE(data); tmpValue = StringUtil.getFromUnicodeLE(data);
@ -99,4 +95,16 @@ public class StringChunk extends Chunk {
public String toString() { public String toString() {
return this.value; return this.value;
} }
/**
* Parses as non-unicode, supposedly 7 bit CP1252 data
* and returns the string that that yields.
*/
protected static String parseAs7BitData(byte[] data) {
try {
return new String(data, "CP1252");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Core encoding not found, JVM broken?", e);
}
}
} }

View File

@ -24,19 +24,19 @@ import org.apache.poi.hsmf.datatypes.*;
import org.apache.poi.hsmf.parsers.*; import org.apache.poi.hsmf.parsers.*;
public final class AllHSMFTests { public final class AllHSMFTests {
public static Test suite() {
public static Test suite() { TestSuite suite = new TestSuite(AllHSMFTests.class.getName());
TestSuite suite = new TestSuite(AllHSMFTests.class.getName()); suite.addTestSuite(TestBasics.class);
suite.addTestSuite(TestBlankFileRead.class); suite.addTestSuite(TestBlankFileRead.class);
suite.addTestSuite(TestSimpleFileRead.class); suite.addTestSuite(TestSimpleFileRead.class);
suite.addTestSuite(TestOutlook30FileRead.class); suite.addTestSuite(TestOutlook30FileRead.class);
suite.addTestSuite(TestFileWithAttachmentsRead.class); suite.addTestSuite(TestFileWithAttachmentsRead.class);
suite.addTestSuite(TestChunkData.class); suite.addTestSuite(TestChunkData.class);
suite.addTestSuite(TestTypes.class); suite.addTestSuite(TestTypes.class);
suite.addTestSuite(TestPOIFSChunkParser.class); suite.addTestSuite(TestPOIFSChunkParser.class);
return suite; return suite;
} }
} }

View File

@ -0,0 +1,77 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hsmf;
import java.io.IOException;
import junit.framework.TestCase;
import org.apache.poi.POIDataSamples;
/**
* Tests to verify that we can perform basic opperations on
* a range of files
*/
public final class TestBasics extends TestCase {
private MAPIMessage simple;
private MAPIMessage quick;
private MAPIMessage outlook30;
private MAPIMessage attachments;
/**
* Initialize this test, load up the blank.msg mapi message.
* @throws Exception
*/
public TestBasics() throws IOException {
POIDataSamples samples = POIDataSamples.getHSMFInstance();
simple = new MAPIMessage(samples.openResourceAsStream("simple_test_msg.msg"));
quick = new MAPIMessage(samples.openResourceAsStream("quick.msg"));
outlook30 = new MAPIMessage(samples.openResourceAsStream("outlook_30_msg.msg"));
attachments = new MAPIMessage(samples.openResourceAsStream("attachment_test_msg.msg"));
}
/**
* Can we always get the recipient's email?
*/
public void testRecipientEmail() throws Exception {
assertEquals("travis@overwrittenstack.com", simple.getRecipientEmailAddress());
assertEquals("kevin.roast@alfresco.org", quick.getRecipientEmailAddress());
assertEquals("randall.scarberry@pnl.gov", outlook30.getRecipientEmailAddress());
assertEquals("nicolas1.23456@free.fr", attachments.getRecipientEmailAddress());
}
/**
* Test subject
*/
public void testSubject() throws Exception {
assertEquals("test message", simple.getSubject());
assertEquals("Test the content transformer", quick.getSubject());
assertEquals("IN-SPIRE servers going down for a bit, back up around 8am", outlook30.getSubject());
assertEquals("test pi\u00e8ce jointe 1", attachments.getSubject());
}
/**
* Test attachments
*/
public void testAttachments() throws Exception {
assertEquals(0, simple.getAttachmentFiles().length);
assertEquals(0, quick.getAttachmentFiles().length);
assertEquals(0, outlook30.getAttachmentFiles().length);
assertEquals(2, attachments.getAttachmentFiles().length);
}
}

View File

@ -105,6 +105,18 @@ public final class TestPOIFSChunkParser extends TestCase {
assertNotNull(msg.getRecipientDetailsChunks()); assertNotNull(msg.getRecipientDetailsChunks());
assertEquals("kevin.roast@alfresco.org", msg.getRecipientDetailsChunks().recipientEmailChunk.getValue()); assertEquals("kevin.roast@alfresco.org", msg.getRecipientDetailsChunks().recipientEmailChunk.getValue());
// Try both SMTP and EX files for recipient
assertEquals("EX", msg.getRecipientDetailsChunks().deliveryTypeChunk.getValue());
assertEquals("kevin.roast@alfresco.org", msg.getRecipientDetailsChunks().recipientEmailChunk.getValue());
msg = new MAPIMessage(new POIFSFileSystem(
new FileInputStream(samples.getFile("simple_test_msg.msg"))
));
assertEquals("SMTP", msg.getRecipientDetailsChunks().deliveryTypeChunk.getValue());
assertEquals(null, msg.getRecipientDetailsChunks().recipientEmailChunk);
assertEquals("travis@overwrittenstack.com", msg.getRecipientDetailsChunks().recipientNameChunk.getValue());
} }
public void testFindsNameId() throws IOException { public void testFindsNameId() throws IOException {