question

hawthorneabendsen-6142 avatar image
0 Votes"
hawthorneabendsen-6142 asked

Unable to delete email using MAPI and DeleteMessages

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?

dotnet-csharpoffice-addins-dev
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

0 Answers