views:

1393

answers:

3

I've been using Mapi32 from a Winforms app to send bring up a new mail message with attachments for a while now, and it's worked really well. (Yes, I'm aware that calling into MAPI32 from C# is not supported.)

Within the last few days, it has stopped working when Outlook is running. However, if Outlook is not running, it will work as expected. This happens in both Vista and XP.

Have any SOer's had this problem? How did you resolve it?

Here's the code I've been using:

public class EmailController
{
    [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)]
    public static extern int MAPISendMail(IntPtr lhSession, IntPtr ulUIParam,
        MapiMessage lpMessage, int flFlags, int ulReserved);
    public const int MAPI_LOGON_UI = 0x00000001;
    private const int MAPI_DIALOG = 0x00000008;

    public static int SendMail(string strAttachmentFileName, string strSubject,string to)
    {

        IntPtr session = new IntPtr(0);
        IntPtr winhandle = new IntPtr(0);

        MapiMessage msg = new MapiMessage();
        msg.subject = strSubject;

        int sizeofMapiDesc = Marshal.SizeOf(typeof(MapiFileDesc));
        IntPtr pMapiDesc = Marshal.AllocHGlobal(sizeofMapiDesc);

        MapiFileDesc fileDesc = new MapiFileDesc();
        fileDesc.position = -1;
        int ptr = (int)pMapiDesc;

        string path = strAttachmentFileName;
        fileDesc.name = Path.GetFileName(path);
        fileDesc.path = path;
        Marshal.StructureToPtr(fileDesc, (IntPtr)ptr, false);

        msg.files = pMapiDesc;
        msg.fileCount = 1;


        List<MapiRecipDesc> recipsList = new List<MapiRecipDesc>();
        MapiRecipDesc recipient = new MapiRecipDesc();

        recipient.recipClass = 1;
        recipient.name = to;
        recipsList.Add(recipient);

        int size = Marshal.SizeOf(typeof(MapiRecipDesc));
        IntPtr intPtr = Marshal.AllocHGlobal(recipsList.Count * size);

        int recipPtr = (int)intPtr;
        foreach (MapiRecipDesc mapiDesc in recipsList)
        {
            Marshal.StructureToPtr(mapiDesc, (IntPtr)recipPtr, false);
            recipPtr += size;
        }

        msg.recips = intPtr;
        msg.recipCount = 1;
        int result = MAPISendMail(session, winhandle, msg, MAPI_LOGON_UI | MAPI_DIALOG, 0);

        return result;
    }
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiMessage
{
    public int reserved;
    public string subject;
    public string noteText;
    public string messageType;
    public string dateReceived;
    public string conversationID;
    public int flags;
    public IntPtr originator;
    public int recipCount;
    public IntPtr recips;
    public int fileCount;
    public IntPtr files;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiFileDesc
{
    public int reserved;
    public int flags;
    public int position;
    public string path;
    public string name;
    public IntPtr type;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiRecipDesc
{
    public int reserved;
    public int recipClass;
    public string name;
    public string address;
    public int eIDSize;
    public IntPtr entryID;
}
A: 

Well, other than the obvious "use supported C# mail-sending methods" comment, I wonder if something happened to the mapi32.dll file - have you tried a "Detect and Repair" in Outlook?

I also read here (http://office.microsoft.com/en-us/outlook/HP011164781033.aspx) that there are some steps you can do (the post and the comments) to get Outlook to repair or replace the dll.

Jared Harley
A: 

"use supported C# mail-sending methods"

I don't have an answer for Outlook/Mapi, but would suggest that it might be faster and less frustrating to rewrite your SendMail method in pure C# than to track down the fix for current implementation.

And as a bonus, your code will be easier to maintain and likely more stable/reliable.

Mark Maslar
Sure, it's not difficult to use .NET to send emails. But the benefits of being able to pop up their default email client are fairly large: They have access to their contacts, it uses their SMTP server (which is key, because this is a very widely distributed app).
Jon Dewees
+1  A: 

int result = MAPISendMail(session, winhandle, msg, MAPI_LOGON_UI | MAPI_DIALOG, 0);

   return result;

What does it return?

andremo