Setting properties of MapiMessage

I’ve searched the forum, but having trouble finding exactly what I need.

I’m trying to set many of the properties of a MapiMessage with data we’ve already extracted from a Lotus NotesDocument. The problem is, I don’t know how to work with MapiProperty correctly to set these values as byte[]. Please note, we are not reading another MapiMessage. I am trying to create one from scratch.

How do I do the following below?

MapiMessage msg = new MapiMessage();
MapiProperty property;
property = new MapiProperty(MapiPropertyTag.PR_CREATION_TIME, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_LAST_MODIFICATION_TIME, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_LAST_ACCESS_TIME, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_RECEIPT_TIME, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_CLIENT_SUBMIT_TIME, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_READ_RECEIPT_REQUESTED, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_CONVERSATION_INDEX, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_CONVERSATION_TOPIC, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_PROOF_OF_DELIVERY_REQUESTED, ???);
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_MESSAGE_CLASS, ???);
msg.SetProperty(property);

Also, what about the msg.Headers[]? How can I set those as well?

This post doesn’t help because it’s a custom property:
Setting a Custom MAPI property that is persisted after save as MSG

Hi,


Thank you for considering Aspose.

Please check the below source code to set some of the MapiProperties. This will give you a pretty good idea on how to set the remaining ones.

C#

var message = new Aspose.Email.Outlook.MapiMessage("from@domain.com","to@domain.com",“Subject”,“Body”);
var property = new MapiProperty(MapiPropertyTag.PR_SUBJECT, Encoding.Unicode.GetBytes(“New Subject”));
message.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_CREATION_TIME, convertDateTime(new DateTime(2012, 4, 10)));
message.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_LAST_MODIFICATION_TIME, convertDateTime(new DateTime(2012, 4, 11)));
message.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_MESSAGE_CLASS, Encoding.Unicode.GetBytes(“IPM.Note”));
message.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_CONVERSATION_INDEX, new byte[1]{255});
message.SetProperty(property);
message.Save(“output.msg”);

private static byte [] convertDateTime(DateTime t) { long filetime = t.ToFileTime(); byte[] d = new byte[8]; d[0] = (byte)(filetime & 0xFF); d[1] = (byte)((filetime & 0xFF00) >> 8); d[2] = (byte)((filetime & 0xFF0000) >> 16); d[3] = (byte)((filetime & 0xFF000000) >> 24); d[4] = (byte)((filetime & 0xFF00000000) >> 32); d[5] = (byte)((filetime & 0xFF0000000000) >> 40); d[6] = (byte)((filetime & 0xFF000000000000) >> 48); d[7] = (byte)(((ulong)filetime & 0xFF00000000000000) >> 56); return d; }

Setting the Headers is as simple as below, but unfortunately this method is not working as expected for a newly created message. I am still looking into it and I will keep you posted with updates on this.

C#
message.Headers.Add("MyHeader", "MyValue");

Regards,

Thanks very much, Babar.

The properties are working perfectly.

The headers, as you mentioned, are not actually adding to the collection. I tried both of these ways, but the Headers collection is still empty.
msg.Headers.Add(“To”, data);
msg.Headers[“To”] = data;

Hi,


Thank you for your feedback.

In reference to the problem of adding headers to a newly created MapiMessage, I have logged a ticket (NETWORKNET-33236) in our bug tracking system and sought help from the development end. As soon as I get any news, I will post here for your reference.

We are sorry for your inconvenience.

Regards,

Babar, I just wanted to express the urgency of the Headers[] collection, because we are rolling out our software very soon as we really need the ability to generate messages with proper Headers, so that users can open them in Outlook and the Headers look correct.

We need the fix for setting/getting Header values as expressed here in these two posts:
Setting properties of MapiMessage

Do you have any thoughts as to when that might be fixed?

Hi

I would like to inform you that please give a try to the latest Aspose.Email for .NET 1.7.1. This issue is resolved and following is a sample code to verify the feature.

// Create sample MapiMessage
var message = new Aspose.Email.Outlook.MapiMessage("from@domain.com", "to@domain.com", “Subject”, “Body”);

// Add sample headers
message.Headers.Add(“Header01”, “HeaderValue01”);
message.Headers.Add(“Header02”, “HeaderValue02”);
message.Headers.Add(“Header03”, “HeaderValue03”);

// Display available headers
foreach (string HeaderTitle in message.Headers.AllKeys)
{
Console.WriteLine(HeaderTitle + " :" + message.Headers.Get(HeaderTitle) + “\n”);
}
Console.ReadKey();

Please try this and let us know if it has resolved your issue.

Best Regards

Thank you, SH.

I can see that when setting Headers, the MapiMessage retains the value now. Unfortunately though, when I save the MapiMessage out, the resulting .msg still does not have the Headers when viewed in Outlook. This is the functionality we really need.

Is there something else we should be doing? We are setting the msg.Headers as you recommended, but should we be also setting msg.SenderEmailAddress, msg.To, etc.?

Hi,


Thank you for your continues support and help.

We have tried on our end by creating a new MapiMessage from scratch (as mentioned in your original post) and then add custom headers to it. The resultant message seems to retain the headers even after saving it to the disk.

Could you please share your complete source code and sample file if you are using any? This request is to understand how are you creating or loading the MapiMessage, and setting the custom headers.

Regarding the ticket (NETWORKNET-33236) attached to this request. I have checked the status and I can see that the ticket has been marked “Fixed” by the development team. We hope to publish the fix with upcoming release of Aspose.Email for .NET v1.8.0. Please note, next release is scheduled for the first quarter of upcoming month (June).

Regards,

Hi


In addition to Babar’s answer, I would like to provide a code snippet to test. Please inform about the result if it satisfies your requirements.

Also I am attaching an image showing this resultant MapiMessage opened in Outlook.

// Generate Mail Message
MailMessage msg = new MailMessage();

// Add From Info
msg.From = "from@domain.com";

// Add list of To(s)
msg.To.Add("to1@domain.com");
msg.To.Add("to2@domain.com");
msg.To.Add("to3@domain.com");

// Add list of CCs
msg.CC.Add("to4@domain.com");
msg.CC.Add("to5@domain.com");

// Add list of BCCs
msg.Bcc.Add("to6@domain.com");
msg.Bcc.Add("to7@domain.com");

// Add subject and body
msg.Subject = “Subject of the mail”;
msg.Body = “Body of the mail”;

// Create MapiMessage from MailMessage
var mapiMsg = Aspose.Email.Outlook.MapiMessage.FromMailMessage(msg);

// Save Mapi Message
mapiMsg.Save(“TestHeaders2.msg”);

Best Regards


Thank you very much for the response.

Babar, we are using the method of loading a MapiMessage from a saved message from Outlook, as per your suggestion at the bottom of this thread:
Setting a Custom MAPI property that is persisted after save as MSG
Recall that some of MapiMessage’s internal variables were not setup properly unless we used this work around to load an Outlook created .msg. This method has worked well for us, and we are not inclined to change it at this point.

SH, we went back and forth between MailMessage and MapiMessage several times, creating one from the other, etc., and eventually found that MapiMessage was our best solution, as it gives us more power than MailMessage, as we have the need to set both existing and custom MAPI properties.

Our codebase is very large, much of which has nothing to do with Aspose, so I cannot send anything like that, however, I will attach one file that has functionality to create a MapiMessage object from a Lotus Notes NotesDocument object. You will not be able to compile this, as there are dependent classes that I am not including, but at least you can have an idea of how we are using MapiMessage in this particular case. I have also attached the template.msg file that we are using to create a simple/empty MapiMessage.

Basically, here we are creating an Outlook .msg file from a Lotus Notes NotesDocument object. We try to retain as much information as possible from the NotesDocument and put it into the MapiMessage, so that we can save out a semi-equivalent .msg file. There is more information to be captured at a later date. After much work, we are very close; the only major issue we are having is that the Headers are not showing up in the resulting saved out .msg file. Of course, I have document and posted about other issues, but those are of less importance.

Below are the important parts of the attached code, relevant to this conversation, though of course we are setting additional existing and custom MAPI properties, as well as parameters like Subject, SetBodyContent(), adding to Attachments list, etc.

// Create MapiMessage from template file:
using (MemoryStream stream = new MemoryStream(Properties.Resources.template_msg))
{
msg = MapiMessage.FromStream(stream);
}

// Set Header property (“To”, “From”, “CC”, “BCC”):
if (!String.IsNullOrEmpty(value))
msg.Headers.Add(header, value);

// Save MapiMessage to file:
MapiMessage msg = LotusHelper.NotesDocumentToMapiMessage(session, document);
msg.Save(filepath);

We are using Aspose.Email 1.7.1

If possible, please delete the attachment from this thread once you receive it, as we consider this to be intellectual property of our company and we do not wish to share it.

Hi


First of all I would like to inform that only creator of a post can modify/delete the attachment. As I have downloaded the attachment for further analysis, so you can delete the attachment. I am working on this issue and will share my findings soon.

I want to share that there is option to send such attachments/samples using “Send mail to SH” or “Send SH a private message” rather than attaching it with the post on forum.

I regret the inconvenience caused to you.

Best Regard


No inconvenience; thanks very much for your support!

Hi


I have worked on this issue and sending you a piece of code. In this code I have used a sample message generated from outlook. This sample message contains some recipients, body and subject. This can be shown by opening original sample message named “originalEmptyMessage.msg” in outlook. However its not necessary to create MapiMessage from sample file, and you can create it from scratch.

I opened it as MapiMessage and then changed its properties like Subject, Body, To, CC and BCC. This message is saved and again I opened it in outlook. All new information is visible in outlook.

MapiMessage msg = MapiMessage.FromFile("OriginalEmptyMessage.msg");
// Change Subject
var property = new MapiProperty(MapiPropertyTag.PR_SUBJECT_W, Encoding.Unicode.GetBytes("New Subject"));
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_NORMALIZED_SUBJECT_W, Encoding.Unicode.GetBytes("New Subject"));
msg.SetProperty(property);
property = new MapiProperty(MapiPropertyTag.PR_CONVERSATION_TOPIC_W, Encoding.Unicode.GetBytes("New Subject"));
msg.SetProperty(property);

// Change Body
msg.SetBodyContent("

New Body

", BodyContentType.Html);

// Delete all the recipients
msg.Recipients.Clear();

//Add To, CC, Bcc
msg.Recipients.Add("NewUserTo1@gmail.com", "NewUserTo1", MapiRecipientType.MAPI_TO);
msg.Recipients.Add("NewUserTo2@gmail.com", "NewUserTo2", MapiRecipientType.MAPI_TO);
msg.Recipients.Add("NewUserTo3@gmail.com", "NewUserTo3", MapiRecipientType.MAPI_TO);
msg.Recipients.Add("NewUserCC1@gmail.com", "NewUserCC1", MapiRecipientType.MAPI_CC);
msg.Recipients.Add("NewUserCC2@gmail.com", "NewUserCC2", MapiRecipientType.MAPI_CC);
msg.Recipients.Add("NewUserCC3@gmail.com", "NewUserCC3", MapiRecipientType.MAPI_CC);
msg.Recipients.Add("NewUserBCC1@gmail.com", "NewUserBCC1", MapiRecipientType.MAPI_BCC);
msg.Recipients.Add("NewUserBCC2@gmail.com", "NewUserBCC2", MapiRecipientType.MAPI_BCC);
msg.Recipients.Add("NewUserBCC3@gmail.com", "NewUserBCC3", MapiRecipientType.MAPI_BCC);
msg.Save("Output.msg");

Please inform us if it solves your problem.

Best Regards

Thank you, SH.

As I said, we were creating a MapiMessage from a template because when we created one from scratch (new MapiMessage()) or from MailMessage (MapiMessage.FromMailMessage(new MailMessage())), then setting properties did not work correctly. Maybe this is fixed now, but it certainly did not work when we wrote this code. Please see this thread, as we were instructed to use a template .msg:
Setting a Custom MAPI property that is persisted after save as MSG

Here, I see you are using the Recipients list, not the Headers list. Do we have to use the Recipients list instead? We were not aware of this requirement.

We have a problem with this because the headers we get from Lotus Notes messages are just strings; they are not separated into email address and name. It may be difficult to determine which parts are email addresses and which parts are names because some strings will have both and others will not; some strings will be delimited with commas, and other with semicolons, and some strings will be in LDAP format, which have neither. To us, they are just a string of information.

We need some way to set the Headers list as a string and retain that value. The message will not ever be emailed, it is only for the customer to view the message in Outlook for investigative purposes.

Hi


You told that you get a string of information which has not well-defined format and also you don’t need to parse it as it will never be used to mail the message. You just want to show information to the user in outlook. I have put data as per your format, and its visible as it is in the code below. Does it not fulfill requirement? Please comment on it for further analysis. Also you told that you are not creating MapiMessage from scratch and same is the case with mine example where I have taken an empty message as sample. There we can use your template message. It shows whatever the string is there in To, CC and Bcc separated with , or ; or : yyyyyy etc.

//Add To, CC, Bcc
msg.Recipients.Add(“NewUserTo1@gmail.com, xxxxxxxxxxxxx, NewUserTo3@gmail.com”, “”, MapiRecipientType.MAPI_TO);
msg.Recipients.Add(“NewUserCC1@gmail.com,NewUserCC2@gmail.com,NewUserCC3@gmail.com”, “”, MapiRecipientType.MAPI_CC);
msg.Recipients.Add(“NewUserBCC1@gmail.com;NewUserBCC2@gmail.com,NewUserBCC3@gmail.com”, “”, MapiRecipientType.MAPI_BCC);

Best Regards

SH, that will work wonderful as long as the string looks the same after we save the MapiMessage.

I will try it today and let you know.

Thank you very much for the suggestion.

SH, it works great; thank you very much!

What to do about “From” field though?

I tried all of the following, but none of them seem to populate the “From” field:
msg.Headers.Add(“From”, value);
msg.Recipients.Add(value, String.Empty, MapiRecipientType.MAPI_ORIG);
msg.SenderEmailAddress = value;

Also, I have some exceptions if the data is not in an excepted format. It seems Recipients.Add() expects the address information in a certain format.

Some of the addresses I extract from Lotus come in an LDAP format:

"CN=John Davis/OU=SAN/OU=NA/O=EURORSCG@EURORSCG, CN=Marty A
Gross/OU=SAN/OU=NA/O=EURORSCG@EURORSCG, CN=Walker
Burl/OU=SAN/OU=NA/O=EURORSCG@EURORSCG"

Exception: System.ArgumentException: The address is not in a recognized format.
at Aspose.Email.Outlook.MapiRecipientCollection.Add(String address, String displayName, MapiRecipientType recipientType)

For now I found a workaround for LDAP addresses, and put them in the DisplayName for now.

bool isLDAP = false;
if (value.Contains("=") || value.Contains("/"))
isLDAP = true;

msg.Recipients.Add((isLDAP) ? "LDAP@LDAP.COM" : value, (isLDAP) ? value : String.Empty, MapiRecipientType.MAPI_TO);

Hi


Please try one of the following for setting FROM and let me know the result.

property = new MapiProperty(MapiPropertyTag.PR_ORIGINAL_SENDER_EMAIL_ADDRESS, Encoding.Unicode.GetBytes("sender@domain.com"));
msg.SetProperty(property);

Or try this
property = new MapiProperty(2147483679, Encoding.Unicode.GetBytes("sender@domain.com"));
msg.SetProperty(property);
property = new MapiProperty(2147549215, Encoding.Unicode.GetBytes("sender@domain.com"));
msg.SetProperty(property);

Best Regards