Sending e-mail from inspector

  • Thread starter Thread starter Mark Smith
  • Start date Start date
M

Mark Smith

I am working in C++. When a new inspector is created, I create a toolbar
for it and hook up callbacks for the buttons and the close event. If the
inspector is viewing a non-sent e-mail, one of the buttons is supposed to
send the e-mail and then export the e-mail to another program.

If I call _MailItem::Send(), I get a security prompt and Outlook crashes.
If I go to MAPI and call SubmitMessage, the message is put in the Outbox to
be sent, but not sent immediately, plus the inspector stays open. If I call
_Inspector::Close(), Outlook crashes.

Neither of these crashes occur at the moment that I call the method, but
sometime after I have returned from the button callback.

I have tried to make sure all references to the inspector and mail item
(except the one used to call the method) are released before calling any of
these methods and all of the callbacks unhooked. This didn't make any
difference in the behavior.

Does anybody know what I might be doing wrong, or a different way of doing
what I am trying to do?

Thanks for any help.
Mark
 
You cannot use Extended MAPi to submit a message being displayed by
Outlook - Outlook will not be aware of your action and will assume that the
message is still valid. You can of course close the inspector first and then
submit the message using Extended MAPI, but the message will stay in the
Outbox unless you are using Exchange.
Simulate a click on the Send button instead: find the button coordinates
using the CommandBars collection, then call mouse_event() to simulate mouse
move, left button down, up, then move back.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
That doesn't seem like a very robust solution, since the toolbar may not be
displayed, or the send button may have been customized by the user or
another add-in. Is there any other way? Or is there a way to identify a
button that can't be customized? That wouldn't help if the toolbar is
hidden, anyway.

Do you know why is it crashing when I call _MailItem::Send() or
_Inspector::Close()?

Is there a way in the add-in to force Outlook to send the messages in its
outbox? Or better yet, a specific message in its outbox?

Mark
 
Below...

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Mark Smith said:
That doesn't seem like a very robust solution, since the toolbar may not
be displayed, or the send button may have been customized by the user or
another add-in. Is there any other way? Or is there a way to identify a
button that can't be customized? That wouldn't help if the toolbar is
hidden, anyway.

That's the best you can do. Or the security prompt.
Do you know why is it crashing when I call _MailItem::Send() or
_Inspector::Close()?

I have no idea since you did not post the relevant portions of your code. I
am 99% that it is a bug in your code. These are widely used methods, I am
not aware of any problems with them.
Is there a way in the add-in to force Outlook to send the messages in its
outbox? Or better yet, a specific message in its outbox?

Exchange: you don't need to
Outlook 2000 or below (C/W): flush the MAPI spooler queues
Outlook 2002 and up without Exchange: simulate a click on the Send/Receive
button or use the Namespace.SyncObjects collection to start the fist sync
(Send/Receive All)
 
Well let me see if I can distill the relevant bits out. This has evolved
into a pretty complicated set of code.

If it matters, I am using IDispEventSimpleImpl::DispEventAdvise and its
partner to hook up and release callbacks.

I have wrapped up the creation and destruction of my toolbar and buttons in
a class, to ensure that it is done properly and robustly. When I get a new
inspector, I create a new instance of my toolbar class:

void __stdcall CAddin::NewInspector(IDispatch* pdispInspector)
{
// Add tool bar
addToolBar(new ToolBar(CComQIPtr<Outlook::_Inspector>(pdispInspector),
this));
}

Again, this class creates the toolbars and hooks up the callbacks for me.
Here is the relevant code of the button callback (note that m_pItem is the
IDispatch pointing to the mail item that was retrieved from m_pInspector via
_Inspector::get_CurrentItem, and m_pInspector is a copy of the _Inspector
pointer created in the NewInspector function above):

void __stdcall ToolBar::OnClickButton(IDispatch* Ctrl, VARIANT_BOOL *
CancelDefault)
{
// Check input
CComQIPtr<Office::_CommandBarButton> pButton(Ctrl);
if (pButton == NULL)
return;

// Send mail item to other program
...

// Send mail item
CComQIPtr<Outlook::_MailItem> pMailItem(m_pItem);
if (pMailItem != NULL) {
/* CComPtr<IMessage> pMessage;
if
(SUCCEEDED(pMailItem->get_MAPIOBJECT(reinterpret_cast<IUnknown**>(&pMessage)))
&& pMessage != NULL) {
pMessage->SubmitMessage(0);
}
*/
// m_pInspector->Close(olSave);
pMailItem->Send();
}
}

This is the stack at the moment of the crash (this is after the button
callback has returned), whether I call _MailItem::Send or _Inspector::Close:

MSO9! 30cbf178()
MSO9! 30acddd3()
MSO9! 30ae0b32()
MSO9! 3096265f()
MSO9! 30902338()
MSO9! 308f4246()
USER32! 77d48709()
USER32! 77d487eb()
USER32! 77d489a5()
USER32! 77d4bccc()
MSO9! 30960086()
OUTLOOK! 30001ccd()
KERNEL32! 7c816d4f()

Thanks so much for your help!
Mark
 
No, don't call SubmitMessage while a message is still being displyed, close
the inspector first and remove all the references to both the inspector (and
its event sink) and the message.
Secondly, it looks like your code will be able to handle only one open
inspector at a time - instead of having a single variable m_pInspector,
you'd need a list of open inspectors.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
Back
Top