Retrieve MailMessage from ExchangeServer- change TO- resend via SmtpClient- Attachment Contents Lost

I need to retrieve mail messages from an exchange server, modify the To address, then resend the MailMessage via SmtpClient. The problem is that while I can open the attachments on the original message without a problem, once I resend the MailMessage I retrieved from exchange via the SmtpClient to another Exchange Mailbox, I see the attachment names, but the files sizes are wrong, and if I try and open the attachments they are empty.

Why does this not work, and is there some recommended way of doing what I am trying to do?
I've also tried creating a new MailMessage and copying information from the original, including looping over the Attachments Collection and adding them to the new MailMessage, but that doesn't seem to work either.

Example:
foreach (Attachment a in msg.Attachments)
{
relayMsg.Attachments.Add(a);
}

Instead of just adding attachments from one message to the other, do I need to do I need to actually create a new attachment, and somehow copy the data from the original attachment, then add the new attachment to my new message?

Seems like just changing the To on the original message and resending it should work, but doesn't seem to.

Any assistance would be greatly appreciated.

Thanks,

Rick

Hi Rick,

I can reproduce the issue at my end as well. Our developers will look into it. I have also logged it in our bug tracking system (ID: 14912). We will notify you as soon we make any progress to fix it. Sorry for the inconvenience.

Just to give some additional information...

In order to simply copy a message, with all the attachments, linked resources, etc. it basically required me to individually copy all the properties I wanted to be copied, iterate through all the collections of headers, attachments, LinkedResources, attachment LinkedResources, AlternateViews, etc. creating memorystreams, saving the object to a memory stream, then reseting the memory stream to the beginning, and creating a new object from the memory stream, all 1 at a time, building the new message manually from the original message. If you try writing higher level objects to a stream by saving them, you end up loosing data, because the save for the higher objects in the Aspose.Network.Mail namespace only seems to do a shallow save, instead of a deep save, so if you save a higher level object, you don't get all the data.

Here is an example of the CopyAttachment code:

protected Attachment CopyAttachment(Attachment a)
{
MemoryStream ms;
ms = new MemoryStream();
a.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
Attachment na = new Attachment(ms, a.ContentType);
na.Name = a.Name;
na.NameEncoding = a.NameEncoding;
na.ContentId = a.ContentId;
na.TransferEncoding = a.TransferEncoding;
na.PreferredTextEncoding = a.PreferredTextEncoding;
return na;
}

I had to do a similar thing for all the parts of the message, in order for all the attachments and everything to come through.

I still have an issue with character encoding not coming through correctly in some cases causing certain characters which display in the orginal message to not come through correctly on the copied message, but I haven't figured that out yet.

If the Aspose library worked as expected I wouldn't have to do any of that. I should be able to do an accurate deep copy of a message with a single method call.

The shallow copy problem also extends to the following example.

While any normal user would think that if you call the method:

exchangeClient.SaveMessage(uniqueUri,messageSavePath)

It would give you the same data as:

exchangeClient.FetchMessage(uniqueUri).Save(messageSavePath)

That is anything but the case. The first method seems to work the best, and attempts to save the attachment data as well as the message data, although it still doesn't seem exactly correct. On the other hand, saving the MailMessage to a .eml file does not save any of the attachments. You get attachment names, but the contents are empty. I assume any linked resources are not saved either.

The other problem this creates is that if I want to retrieve a message, process it, and save a copy of it, as I did for my project, I had to retrieve the object from the exchange server twice. Once to fetch the MailMessage, so I could process it, and again to save the message using the ExchangeClient.SaveMessage() because while not perfect, was vastly better than the MailMessage.Save(), which seems almost useless. The doubles the number of hits on the Exchange server and increases network traffic due to having to pull the data from the server twice.

I realize that the entire email system and all the associated standards are complex, and ill conceived on many levels, which is what happens as a system evolves over time without any clear direction, however it is important as sellers of a library to help make sense of the chaos. That is why people buy a library to save them time in dealing with the complexities so they can focus on their particular problem. It therefore is extremely important that your API's not only work, but be consistant in behavior. This is especially important given the lack of any meaningfull and accurate documentation, and the fact that the obfuscated code makes it very difficult to try to figure out what the problem is, or what is going on when things do not work as expected.

The library has great potential, but there some key issues that can really cause users grief.

I have some other issues I've found as well, however I'll put in separate posts.

I'm using Aspose.Network.dll v5.0.0.0 for .NET 3.5

I'll look forward to these issues being resolved.

Thanks,

Rick

Hi Rick,

We are working on these issues. As mentioned by you, save() method must save all the properties of message file including attachments. We will notify you as soon as it is resolved. Sorry for the inconvenience.

In doing some more investigation and testing, I found that if instead of using the exchangeClient.fetchMessage() api, I used the exchangeClient.Save(stream) method to save the message to a memory stream, then used the static MailMessage.Load(stream) to load from the stream, I got a fully populated MailMessage with all the attachments, which I could save, modify, send etc. as one would expect. Basically it is reimplementing fetchMessage as a Save and Load operation.

The issue therefore seems to be that the exchangeClient.fetchMessage() api, does not return a fully populated MailMessage object, it only retrieves a subset of the information from the server. This lazy retrieval may be beneficial in certain client applications where certain parts of the MailMessage like attachments, may not need to be retrieved if the user does not try to open them. The problem is that when a library user accesses a property or method of the object, the class should encapsulate all the work necessary to instantiate or retrieve the data as efficiently and accurately as possible without requiring the library user to have to figure out the inner workings of the object and what it does and does not do, and then work around them.

In any event, I do appreciate you aknowledging the problem and working toward a solution. I'm sure you have too much to do and to little time to do it as well.

Rick

The issues you have found earlier (filed as 14912) have been fixed in [this update](http://www.aspose.com/community/files/51/.net-components/aspose.network-for-.net/entry229369.aspx).

This message was posted using Notification2Forum from Downloads module by aspose.notifier.