I'm extracting content from a SourceOne EMX file, and I'm able to handle MSG and EML data just fine. The file type I'm not familiar with how to parse is OTG (which may also be referred to as ONM files?). These are very old proprietary IBM formats used with Lotus Notes.
I was able to parse out the header information, however I'm stuck on how to decode message bodies. So far, the IBM437 encoding got me the closest, but is far from being fully readable. Here is a snipped of what it looks like:
??Z ? ? ??? ? $'d ? ??L
I'll be sure to give your name as the point of contact on this one. ???Z ? ? ?? ? ? ????@ ----- Forwarded by <redacted>? ? ? ? ??? ???? on 10/06/2020 12:24 PM ? ? ? ? ??? ???? -----? ? ? ? ?????Z ? ? ?? ? ??
???Z @ ? ??@
,d ? ? ???? ? From: ? ___ ? ????/ "<redacted>" <redacted@redacted.com> ???Z @ ? H ??@
,d ? ? ???? ? To: ? ___ ? ????+ "<redacted>" <redacted@redacted.com> ?? ? ???? ?
Please send help!
Finally figured out how to parse the message body. Answer: you can't. After speaking with pro's in the eDiscovery industry, it seems that everyone uses the Notes library to parse it for you. I was able to use the Domino-JNA wrapper API to insert all the OTG properties into an NSF and then convert to EML. Assuming you parsed the OTG file properly, you should have the name, offset, length, flags, and type for each property.
reader.skip(92);
int count;
while ((count = readUInt16(reader)) != 0xFF00) {
if (count < 0){
break;
}
byte[] nameBytes = new byte[count];
reader.read(nameBytes);
String name = new String(nameBytes, StandardCharsets.US_ASCII);
short type = readUInt16(reader);
short flags = readUInt16(reader);
int offset = readUInt32(reader);
int length = readUInt32(reader);
items.add(new OtgProp(name, flags, type, offset, length));
}
After that, just add each property to a NotesNote one by one:
Method appendItemValueMethod = NotesNote.class.getDeclaredMethod("appendItemValue", String.class, EnumSet.class, int.class, DHANDLE.class, int.class);
appendItemValueMethod.setAccessible(true);
appendItemValueMethod.invoke(note, this.name, FromBitmask(this.flags), this.type, (DHANDLE32/64 of the data), this.length + 2);
After all the properties are added, you can write directly to an EML file
note.check();
note.update();
NotesMimeUtils.exportMIMEToEML(note, targetFile);
Hope this helps anyone trying to understand IBM's ancient undocumented proprietary garbage in the future!