Closed AlexPeek01 closed 10 months ago
I added a property to get the conversation id but that is doing almost the same as what you did. So there probably isn't an id inside the msg file to get. If you want you can sent me the file (zip it before sending) so that I can look inside it to see if the id is even in there.
You can sent the file to sicos2002@hotmail.com (ZIP the file before sending !!)
What you probably need if you want to chain MSG files together is the ThreadIndex --> https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxomsg/9e994fbb-b839-495f-84e3-2c8c02c7dd9b?redirectedfrom=MSDN
This index is normally in the conversation index property or in case of EML files in the ThreadIndex header. In the past I started to program something to do something with it but there was nu use case at that moment so I never finished it.
using System;
using System.Linq;
/// <summary>
/// Decodeert de opgegeven Base64 Outlook thread index
/// </summary>
public sealed class OutlookThreadIndex
{
#region Properties
/// <summary>
/// Retourneert het <see cref="Guid" /> id van de index
/// </summary>
public Guid Id { get; }
/// <summary>
/// Retourneert de datum/tijd van de thread index
/// </summary>
public DateTime Date { get; }
/// <summary>
/// Retourneert de ruwe thread index string
/// </summary>
public string Raw { get; }
/// <summary>
/// Retourneert <c>true</c> wanneer de thread index valide is
/// </summary>
public bool IsValid => Date == default && Id != default;
#endregion
#region Constructor
/// <summary>
/// Decodeert de opgegeven Base64 Outlook <paramref name="threadIndex" />
/// </summary>
/// <param name="threadIndex"></param>
public OutlookThreadIndex(string threadIndex)
{
Raw = threadIndex;
var bytes = Convert.FromBase64String(threadIndex);
// Thread index length should be 22 plus extra 5 bytes per reply
if (bytes.Length < 22 || (bytes.Length - 22) % 5 != 0)
return;
Id = new Guid(bytes.Skip(6).Take(16).ToArray());
var headerTicks = bytes
.Take(6)
.Select(b => (long)b)
.Aggregate((l1, l2) => (l1 << 8) + l2)
<< 16;
Date = DateTime.FromFileTimeUtc(headerTicks);
//Date = new DateTime(headerTicks, DateTimeKind.Utc).AddYears(1600);
var childBlockCount = (bytes.Length - 22) / 5;
for (var i = 0; i < childBlockCount; i++)
{
var childTicks = bytes
.Skip(22 + i * 5).Take(4)
.Select(b => (long)b)
.Aggregate((l1, l2) => (l1 << 8) + l2)
<< 18;
childTicks &= ~((long)1 << 50);
Date = Date.AddTicks(childTicks);
}
}
#endregion
#region ToString
/// <summary>
/// Retourneerd een leesvriendelijke weergave van de thread index
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"Id: {Id}, Date: {Date.ToLocalTime()}, Valid: {IsValid}";
}
#endregion
}
First off, thanks for the quick and detailed responses it has helped us a lot. I was under the impression that the Conversation Index was the same as the Conversation Index which Microsoft Graph returns, but these appear to be different. It looks like as you mentioned that we can simply use the ConversationIndex/ThreadIndex for our problem.
Thanks again! Alex
Prima en succes met de rest :-)
Bedankt :D
Hi Sicos,
For a project I'm working on I need to obtain the ConversationId from Outlook messages to group them by e-mail chain. Ideally we don't want to use Microsoft Graph or something similar to obtain these since we want users to be able to upload .msg and .eml files even after deleting the original e-mails from their mailbox.
I saw that the ConversationTopic and ConversationIndex were available, but couldn't find the Id. I tried obtaining these through the GetMapiProperty and GetNamedMapiProperty methods, but this kept returning null. The values that I tried for these methods were: 0x0071, 0x0071001E, 0x0070, 0x0070001E, 0x3013001E, PidTagConversationId and PR_CONVERSATION_INDEX. Could you provide any guidance or insights on if this can be done and if so how? If this is not possible do you happen to know of any alternative properties that could provide the same functionality.
Thanks in advance!
Kind regards, Alex