Unable to delete email using MAPI and DeleteMessages

hawthorne_abendsen 1 Reputation point
2022-09-23T09:12:40.573+00:00

I've created Outlook 2019 add-in in C# and trying to use DeleteMessages method from MAPI to delete single email. However I'm always getting E_INVALIDARG as a result (look at code below).

I've checked following article: https://www.codeproject.com/Articles/455823/Managed-MAPI-Part-1-Logon-MAPI-Session-and-Retriev, did some own changes and got the code below (only necessary code for IMAPIFolder and HRESULT, let's assume that I only support x64).

   public interface IMAPIFolder  
   {  
       [return: MarshalAs(UnmanagedType.I4)]  
       [PreserveSig]  
       HRESULT DeleteMessages(IntPtr lpMsgList, uint ulUIParam, IntPtr lpProgress, uint ulFlags);  
   }  


   public enum HRESULT  
   {  
       E_INVALIDARG = 0x80070057  
   }  


   public class EntryID  
   {  
       private byte[] id_;  
         
       public EntryID(byte[] id)   
       {  
           id_ = id;  
       }  
     
       public static EntryID GetEntryID(string entryID)  
       {  
           if (string.IsNullOrEmpty(entryID))  
               return null;  
           int count = entryID.Length / 2;  
           StringBuilder s = new StringBuilder(entryID);  
           byte[] bytes = new byte[count];  
           for (int i = 0; i < count; i++)  
           {  
               if ((2 * i + 2) > s.Length)  
                   return null;  
               string s1 = s.ToString(2 * i, 2);  
               if (!Byte.TryParse(s1, System.Globalization.NumberStyles.HexNumber, null as IFormatProvider, out bytes[i]))  
                   return null;  
           }  
           return new EntryID(bytes);  
       }  
   }  

Code snippets to call DeleteMessages I've tried so far (item is MailItem object):

1.==================

   string mailItemEntryId = ((MailItem)item).EntryID  
   byte[] msgEntryId = EntryID.GetEntryID(mailItemEntryId).AsByteArray;  
     
   int idLen = msgEntryId.Length;  
     
   IntPtr pMsgCom = Marshal.AllocCoTaskMem(16);  
   Marshal.WriteInt64(pMsgCom, 1L);  
   IntPtr pArrayCom = Marshal.AllocCoTaskMem(16);  
   Marshal.WriteInt64(pMsgCom, 8, (long)pArrayCom);  
   Marshal.WriteInt64(pArrayCom, (long)idLen);  
   IntPtr entryBytesCom = Marshal.AllocCoTaskMem(idLen);  
   Marshal.WriteInt64(pArrayCom, 8, (long)entryBytesCom);  
   Marshal.Copy(msgEntryId, 0, entryBytesCom, idLen);  
     
   var mapifolder = (IMAPIFolder)((MAPIFolder)mailItem.Parent).MAPIOBJECT  
   var result = mapifolder.DeleteMessages(pMsgCom, 0, IntPtr.Zero, 0);  

2.==================

   string mailItemEntryId = ((MailItem)item).EntryID  
   byte[] msgEntryId = EntryID.GetEntryID(mailItemEntryId).AsByteArray;  
     
   int idLen = msgEntryId.Length;  
     
   IntPtr pMsgCom = Marshal.AllocCoTaskMem(16);  
   Marshal.WriteInt32(pMsgCom, 1);  
   IntPtr pArrayCom = Marshal.AllocCoTaskMem(16);  
   Marshal.WriteInt64(pMsgCom, 8, (long)pArrayCom);  
   Marshal.WriteInt32(pArrayCom, idLen);  
   IntPtr entryBytesCom = Marshal.AllocCoTaskMem(idLen);  
   Marshal.WriteInt64(pArrayCom, 8, (long)entryBytesCom);  
   Marshal.Copy(msgEntryId, 0, entryBytesCom, idLen);  
     
   var mapifolder = (IMAPIFolder)((MAPIFolder)mailItem.Parent).MAPIOBJECT  
   var result = mapifolder.DeleteMessages(pMsgCom, 0, IntPtr.Zero, 0);  

3.==================

   [StructLayout(LayoutKind.Sequential)]  
   public struct SBinary  
   {  
   	public uint cb;  
   	public IntPtr lpb;  
     
   	public static SBinary SBinaryCreate(byte[] data)  
   	{  
   		SBinary b;  
   		b.cb = (uint)data.Length;  
   		b.lpb = Marshal.AllocHGlobal((int)b.cb);  
   		for (int i = 0; i < b.cb; i++)  
   		{  
   			Marshal.WriteByte(b.lpb, i, data[i]);  
   		}  
   		return b;  
   	}  
   }  
     
   [StructLayout(LayoutKind.Sequential)]  
   internal struct SBinaryArray  
   {  
   	public uint cValues;  
   	public IntPtr lpbin;  
     
   	public static SBinaryArray SBinaryArrayCreate(uint length, IntPtr buffer)  
   	{  
   		SBinaryArray b;  
   		b.cValues = length;  
   		b.lpbin = buffer;  
   		return b;  
   	}  
   }  
     
   string mailItemEntryId = ((MailItem)item).EntryID  
   byte[] msgEntryId = EntryID.GetEntryID(mailItemEntryId).AsByteArray;  
     
   SBinary messageBin = SBinary.SBinaryCreate(msgEntryId);  
   IntPtr messageBinPtr = Marshal.AllocHGlobal(Marshal.SizeOf(messageBin));  
   Marshal.StructureToPtr(messageBin, messageBinPtr, false);  
     
   SBinaryArray messageBinArray = SBinaryArray.SBinaryArrayCreate(1, messageBinPtr);  
   IntPtr messageBinArrayPtr = Marshal.AllocHGlobal(Marshal.SizeOf(messageBinArray));  
   Marshal.StructureToPtr(messageBinArray, messageBinArrayPtr, false);  
     
   var mapifolder = (IMAPIFolder)((MAPIFolder)mailItem.Parent).MAPIOBJECT  
   var result = mapifolder.DeleteMessages(messageBinArrayPtr, 0, IntPtr.Zero, 0);  

 

I also tried to use OpenEntry (from MAPISession) and then Marshal.GetObjectForIUnknown to get IMAPIFolder object. However the result was the same and got E_INVALIDARG for DeleteMessages. Any ideas why DeleteMessages returns E_INVALIDARG?

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,521 questions
Office Development
Office Development
Office: A suite of Microsoft productivity software that supports common business tasks, including word processing, email, presentations, and data management and analysis.Development: The process of researching, productizing, and refining new or existing technologies.
3,657 questions
0 comments No comments
{count} votes