We're sorry Aspose doesn't work properply without JavaScript enabled.

Free Support Forum - aspose.com

Aspose.Email Version 17.2 Evaluation

I am evaluating Aspose.Email on the Java platform, in order to decide if we should use Aspose for our e-mail archiving solution.

If someone could please address the following queries, it would help me complete the evaluation.

Here’s our code snippet for how we are using Aspose’ library to parse emails using Aspose’ library.

To be clear, AsposeMailWrapper is our custom wrapper class over MapiMessage


PersonalStorage pst = PersonalStorage.fromStream(inputStream,false);
FolderInfoCollection folderInfoCollection = pst.getRootFolder().getSubFolders();
    
for(FolderInfo folderInfo:MiscUtil.emptyIfNull(folderInfoCollection))
{
    MessageInfoCollection msgInfoCollection = folderInfo.getContents();

    for(MessageInfo msgInfo: MiscUtil.emptyIfNull(msgInfoCollection))
	{
        if(msgInfo==null) 
		{
            continue;
        }
	
        AsposeMailWrapper msg = new AsposeMailWrapper(pst.extractMessage(msgInfo));
        mailList.add(Mail.builder().mail(msg).build());
    }
}
  1. Attachments:

a. Binary Data:

We would like a handle to the byte[] or a stream for the byte[] because we are manipulating the attachment in memory.

MapiAttachment.getBinaryData() returns the content for some attachments, but for others (particularly,attachments in the .eml format) it returns null and .getObject().getData() is not the correct byte[] either. I have attached an example, with the .eml file extension changed to .doc.

b. File and Extension Names:

We would like some clarity on the difference between the following interfaces to get the attachment’s name: getLongFileName(), getDisplayName(), get FileName()

The results from these methods are inconsistent with how my Outlook (version 15.32 for Mac) handles the attachments.

Similarly, it would help if the getExtension() method worked – it’s results are also inconsistent and differ from the actual file names.

c. Spurious/Non-Existent Data:

MapiMessage.getAttachments() is returning an attachment collection that has an attachment populated with “null” values, and an attachment called Attach.txt that doesn’t exist in the actual e-mail. While we can work around this, it would be good to hear if there are reasons why we are getting this.

  1. TimeZone

How can we get the Time Zone info (offset, zone id, etc.) for the PersonalStorage or the MapiMessage

  1. Encoding

How can we find whether a MapiMessage has encoding and how it is encoded?

  1. E-mail Size:

How can we find the size of a MapiMessage?

  1. Message identifiers:

We would have liked to get identifiers for the emails such as journal message id, message id, descriptor node id, conversation/thread id etc.

The only interface we can see is the MapiMessage.getInternetMessageId(), which is returning an empty string ? How can we get this addressed

  1. Body Type

We are able to figure if the body type is HTML, RTF or plain text based on int MapiMessage.getBodyType() –

Is there an Aspose enum (similar to MapiRecipientType) that we could use in order to future proof our code, should the int mapping change?

  1. Subject Vs Normalized subject

Could you please clarify the difference between MapiMessage.getSubject() and getNormalizedSubject()?

  1. Reading .eml and EML<-> MapiMessage conversions

The GitHub project doesn’t seem to have an example for reading eml files and for converting MapiMessage to .eml format. Any pointers on this would be useful

  1. .olm support:

Do you provide any support for reading .olm mail format, which is the archiving format for outlook in Mac?

Regards,

Shankar

Hi Shankar,

Thank you for contacting Aspose support team.

Following are the comments on your requirements:

(a) Could you please provide sample MSG files for both the cases? We will analyze them and provide assistance accordingly.

(b)

  • DisplayName Returns or sets a String representing the name, which does not need to be the actual file name, displayed below the icon representing the embedded attachment. Read/write.
  • FileName Returns a String representing the file name of the attachment.
  • LongFileName is extracted from MapiPropertyTag.PR_ATTACH_LONG_FILENAME which represents the presence of attachment’s long file name

© Could you please provide sample files for this case? We will analyze them and provide assistance accordingly.

  1. If we convert MapiMessage to MailMessage, there it contains the TimeZoneOffset property.

  2. We have requested the product team to provide their comments for this requirement.

  3. I am afraid that no such option is available to get the MapiMessage size.

  4. We have requested the product team to provide their comments for this requirement.

  5. BodyContentType enumerator is available which contains following values:

public static final int PlainText = 0;

public static final int Html = 1;

public static final int Rtf = 2;

  1. The normalized subject contains the message subject with any prefix removed.

Subject can be like : “FW: Some subject”

Normalized subject can be like: ”Normalized subject”

Here is the description of normalized subject.

Email file can be read using MailMessage as follows:

MailMessage mail = MailMessage.load("sample.eml", options);

Mapi message can be converted to EML as follows:

MapiMessage msg = new MapiMessage();

msg.save("output.eml" , SaveOptions.getDefaultEml());

MailConversionOptions options = new MailConversionOptions();

options.setConvertAsTnef(false);

MailMessage mail2 = msg.toMailMessage(options);

mail2.save("output2.eml" , SaveOptions.getDefaultEml());

EML can be converted to MapiMessage as follows:

EmlLoadOptions options = new EmlLoadOptions();

MailMessage mail2 = MailMessage.load("sample.eml" , options);

MapiMessage mapi2 = MapiMessage.fromMailMessage(mail2);

Hi Kashif,

Thanks for the response.

  1. Attachments:

You can download my test pst from here: [https://s3.eu-west-2.amazonaws.com/steel-eye-test-pst/New_Pst_Format_Test.pst ](https://s3.eu-west-2.amazonaws.com/steel-eye-test-pst/New_Pst_Format_Test.pst)

There are 8 mails within this pst (1 in Deleted Items, and 7 in Inbox).

Please take a look at the e-mail with Subject:“Rich Test Attachments Test” in the deleted Items folder, which has 5 attachments (including 2.eml files)

a) The MapiAttachment.getBinaryData() for both the .eml files are returning null, and the .getObject().getData() doesn’t return the correct content either.

c) MapiAttachment.getAttachments() for this mail returns 2 non-existent attachments, one with “null” for all values, and an empty file called “Attach.txt”

  1. EML Support

Thanks for providing code snippets for conversions between MailMessage and MapiMessage. Can you also please let me know how we can create MapiMessage and/or MailMessage from the byte[] of the .msg file content

You can consider the following items closed: 1b, 2, 6, 7

I look forward to your response on 1a, 1c, 3, 5, 8 and 9.

1a- Unable to read some attachments

1c- Dealing with spurious attachments

3 - Finding if MapiMessage is encoded and the method of encoding

5 - Getting Message identifiers - msg id, journal msg id, conversation/thread id

8 - Creating MapiMessage and/or MailMessage from byte[] of the .eml file content

9 - Support for .olm format?

Regards,

Shankar

Hi Kashif,


In addition to the list of open questions above, could you please address the below questions as well?

10. Finding Values based on Property ID:
if there is any way I can find an attribute based on the standard MS Tag’s Property ID. For e.g. You mentioned that you do not provide an interface to read the size of the mail (question #4 above), however this value is present in the pst file as <span style=“font-size: 9pt; font-family: “Verdana,Bold”;”>Property ID: 0x0E08 (MS property field mapping: https://msdn.microsoft.com/en-us/library/ff385210(v=office.12).aspx)

11. MailMessage.getHeader() and MapiMessage.getTransportHeader() do not return all the header fields (and sometimes they are null) in the test data. Is there some other API that I should be looking at?

Regards,
Shankar

Hi Shankar,

Following are responses against the open issues:

1a.

This is the expected behavior that for EML and MSG attachments, binary data is NULL, whereas object data contains value. I am afraid that I could not compare the Object contents of EML/MSG attachment. Could you please explain, how to identify that object data is not correctly read by Aspose.Email as compared to any other third party tool. It will help us to observe the issue and provide assistance accordingly.

1c.

These two attachments are present in the source message as can be seen using third party tool MFCMapi. There it can be seen that either the properties are not present or they are null, that is why Aspose.Email also shows null values for all the properties.

Using same tool MFCMapi, it can be seen that “Attach.txt” attachment is present and therefore it is not an issue with Aspose.Email. “Attach.txt” can be seen in Outlook as well.

3 and 5

We have requested our product team to provide comments, however it may take couple of days to respond as they are busy in some high priority task. You will be notified once any update is received in this regard.

A sample random byte array is initialized which is not actual mail to demonstrate the code sytax only.

byte[] byteArr = new byte[] { 0xC, 0xA, 0xF, 0xE };
MailMessage mailMessage = MailMessage.load(new ByteArrayInputStream(byteArr), new EmlLoadOptions());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
mailMessage.save(bos, SaveOptions.getDefaultEml());

byte[] byteArr2 = new byte[] { 0xC, 0xA, 0xF, 0xE };
MapiMessage mapiMessage = MapiMessage.fromStream( new ByteArrayInputStream(byteArr));
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
mapiMessage.save(bos2, SaveOptions.getDefaultMsgUnicode());

We are sorry but there are no open specifications available for OLM file format. The requirement was reported earlier as well but could not be fulfilled. Hence, we won’t be able to provide this feature in near future until there are some specifications available for implementation of this feature.

Following function may be used to retrieve the required information.

PersonalStorage.extractProperty(entryId,tag);

I am afraid that no such API is known, however you may check MFCMapi if that can be used to observe the value

It is requested that you may please create separate threads for more queries (if you have any) instead of adding to the same thread. It helps us to maintain each issue separately and provide assistance accordingly.

Hi Kashif,

Thanks for your reply.

Contents of .eml attachments:

1 (a) I perform the following action on the file content (binary data or the object data, whichever is available)

FileOutputStream os = new FileOutputStream(outputFile);
os.write(attachment’s content);
os.flush();
os.close();

When I attempt to open the file, it fails for the .eml attachments.

If I compare the contents of the .eml file derived from object data against the content of the original .eml file in outlook I can see that the bytes are different.

Here are two e-mails with the original and extracted data for your reference.

https://s3.eu-west-2.amazonaws.com/steel-eye-test-data/HTML+body_original.eml

https://s3.eu-west-2.amazonaws.com/steel-eye-test-data/HTML+body_extracted.eml

https://s3.eu-west-2.amazonaws.com/steel-eye-test-data/Delivered+Re+transition_extracted.eml

https://s3.eu-west-2.amazonaws.com/steel-eye-test-data/Delivered-+Re-+transition_original.eml

1c I am unable to see attach.txt or null in outlook for mac. So, I am not sure what’s going on here.

I shall open a new thread for any other question/concern.

Regards,

Shankar

Hi Kashif,


I have been able to resolve 1 a) by creating a MapiMessage object out of the MapiObjectProperty and then converting the MapiMessage to a byte[] using the save(OutputStream). This output matches the expected value. So, unless you see an issue with this, you can consider this issue closed.

I look forward to hearing your team’s thoughts on 3) and 5).

Regards,
Shankar



Hi Shankar,


Thank you for sharing the additional information. We’ll update you here once information is available about points 3 and 5. We appreciate your patience in this regard.

Hi Kashif,


Hope you are well.

Just a follow up to check if your product team has any updates on points 3 and 5.

Regards,
Shankar

Hi Shankar,


This is to update you about these two points as per your request.

3. There is a MapiMessage.IsStoreUnicodeOk() method, that returns true, if message is Unicode encoded, or returns false, if message encoding is ASCII-compatible. If message encoding is ASCII-compatible, you can use the CodePage property for getting a localized message encoding:

Encoding.GetEncoding(msg.CodePage).

5. We can get the item id (entryId) only if message is in the PST storage, as this id is not stored in a mapi property collection. But the conversation/thread id stored in PR_CONVERSATION_INDEX mapi property and may be obtained by the following example:

byte[] conversationId = msg.Properties[MapiPropertyTag.PR_CONVERSATION_INDEX].Data.

Hi Kashif,


Thanks for your reply.

Re encoding: I have also stumbled on the MailMessage.getBodyEncoding() method, am I correct in assuming that I could use this as well?

Re Conversation Index: unfortunately, PR_CONVERSATION_INDEX is returning an empty string so we are not sure how to identify a conversation at this point even though we can see that outlook is able to bunch these mails in the same conversation.

Similarly, we are not able to get a handle for the message id using MailMessage.getMessageId() and MapiMessage.getInternetMessageId(). It would be great if you could provide any other ways for handling conversation id and message id.

Please let me know if you would prefer that I raise these questions in a new thread.

Regards,
Shankar

Hi Shankar,

MailMessage.getBodyEncoding() method can be used to get the body encoding. If it does not work as per your expectation, please send us the sample message and complete code to analyze it.

Regarding the conversation index issue, please send us the sample PST along with the code which can be used to re-produce the problem and provide assistance accordingly. I am afraid that there is no other way to handle the conversations.