1

As the title suggests, I have a Winform written in C# .Net Framework 4.8; it calls the MAPISendMail external function from the mapi32.dll to open up a new message window in Outlook for the user, initially populated with a to address and message (and sometimes an attachment):

[DllImport("MAPI32.DLL")]
public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv);

NOTE: If there is anything that you know that could replace MAPI for the usage described, that would be phenomenal.

For whatever reason, every now and again this will end up causing the whole winform to hang for a bit, then close. There is no indication that this is going to happen aside from the aforementioned hanging, and no pattern as far as I can tell; I can go hours without ever encountering it.

Additionally, NO try/catch blocks will be caught when this happens. I have tried catching the standard Exception of course, but also RuntimeWrappedException and that doesn't get triggered either:

try
{
    error = MAPIHelperInterop.MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, MAPI_DIALOG, 0);
}
catch (RuntimeWrappedException rwe)
{
    throw rwe.InnerException;
}
catch (Exception e)
{
    throw e;
}

The only indication that something is wrong is the final line in the Debug output, stating "The program 'PROGRAMNAME' has exited with code 40445582 (0x269268e)". I have googled my hands off trying to find a meaning to this code and have found nothing. Does anyone have any insight on what could be going on here, maybe even a way I can catch this error to prevent the form from closing?

7
  • Read following page : pinvoke.net/default.aspx/mapi32.MAPISendMail Commented Sep 15, 2020 at 21:20
  • 4
    Don't do it. Commented Sep 15, 2020 at 21:37
  • 1
    @CHowell Unfortunately there seemingly isn't any way to do it with attachments as it's considered a security risk. MAPI is a deprecated API, you should avoid using it if at all possible as it's likely to disappear entirely at some point in the future. I appreciate this is unlikely to be problematic for your users if they are used to this functionality, but letting them know you're removing the feature, and then removing it, is a far better solution than waiting for Microsoft to remove it, and then panicking. Commented Sep 16, 2020 at 14:16
  • 1
    The big problem of using the Outlook interop is that it presumably won't work with any email client besides Outlook, whereas MAPI will work (as well as MAPI works) with whatever the system default email client is. If you only care about Outlook, then interop is definitely the way to go - just make sure you use the official NuGet package (nuget.org/packages/Microsoft.Office.Interop.Outlook) instead of trying to hard-link your application to the interop DLLs. The API definitely hasn't changed much so the answer you found should still be good. Commented Sep 16, 2020 at 15:08
  • 1
    In that case, I'm lucky that I KNOW all of my users are using Outlook! Thank you for your help. I would upvote both you AND @HansPassant if I had +15 reputation. Commented Sep 16, 2020 at 15:38

1 Answer 1

3

I was essentially asking the wrong question. Thanks to Hans Passant and Ian Kemp for pointing out MAPI is long deprecated and should be avoided.

In its place, I used Microsoft.Office.Interop.Outlook thanks to this SO question and made a very simple wrapper class:

    public class OutlookEmail
    {
        public OutlookEmail() { }
        public OutlookEmail(params string[] toAddrs)
        {
            To.AddRange(toAddrs);
        }
        private Application OApp = new Application();
        public List<string> To { get; set; } = new List<string>();
        public string Subject { get; set; }
        public string Body { get; set; }
        public List<string> Attachments { get; set; } = new List<string>();
        public void ShowDialog()
        {
            _MailItem oMailItem = (_MailItem)OApp.CreateItem(OlItemType.olMailItem);
            oMailItem.To = string.Join("; ", To);
            // body, bcc etc...
            oMailItem.Subject = Subject;
            oMailItem.Body = Body;
            if(Attachments != null)
            {
                foreach (string path in Attachments)
                {
                    oMailItem.Attachments.Add(path);
                }
            }

            oMailItem.Display(true);
        }
    }

NOTE: this will ONLY work for Outlook; luckily for me, ALL of my users definitely use Outlook.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.