1 /* mailitem-events.h - Event handling for mails.
2 * Copyright (C) 2015 by Bundesamt für Sicherheit in der Informationstechnik
3 * Software engineering by Intevation GmbH
5 * This file is part of GpgOL.
7 * GpgOL is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * GpgOL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "eventsink.h"
24 #include "eventsinks.h"
26 #include "mymapitags.h"
29 #include "windowmessages.h"
32 #include "gpgoladdin.h"
33 #include "wks-helper.h"
36 #define _(a) utf8_gettext (a)
38 const wchar_t *prop_blacklist[] = {
41 L"To", /* Somehow this is done when a mail is opened */
47 L"OutlookInternalVersion",
55 AttachmentAdd = 0xF00B,
56 AttachmentRead = 0xF00C,
57 AttachmentRemove = 0xFBAE,
58 BeforeAttachmentAdd = 0xFBB0,
59 BeforeAttachmentPreview = 0xFBAF,
60 BeforeAttachmentRead = 0xFBAB,
61 BeforeAttachmentSave = 0xF00D,
62 BeforeAttachmentWriteToTempFile = 0xFBB2,
63 BeforeAutoSave = 0xFC02,
64 BeforeCheckNames = 0xF00A,
65 BeforeDelete = 0xFA75,
68 CustomAction = 0xF006,
69 CustomPropertyChange = 0xF008,
72 PropertyChange = 0xF009,
74 ReadComplete = 0xFC8F,
82 /* Mail Item Events */
83 BEGIN_EVENT_SINK(MailItemEvents, IDispatch)
84 /* We are still in the class declaration */
87 Mail * m_mail; /* The mail object related to this mailitem */
90 MailItemEvents::MailItemEvents() :
99 MailItemEvents::~MailItemEvents()
102 m_pCP->Unadvise(m_cookie);
104 gpgol_release (m_object);
107 static bool propchangeWarnShown = false;
108 static bool attachRemoveWarnShown = false;
111 do_delayed_locate (LPVOID arg)
114 do_in_ui_thread (RECIPIENT_ADDED, arg);
118 /* The main Invoke function. The return value of this
119 function does not appear to have any effect on outlook
120 although I have read in an example somewhere that you
121 should return S_OK so that outlook continues to handle
122 the event I have not yet seen any effect by returning
123 error values here and no MSDN documentation about the
126 EVENT_SINK_INVOKE(MailItemEvents)
131 m_mail = Mail::getMailForItem (m_object);
134 log_error ("%s:%s: mail event without mail object known. Bug.",
140 bool is_reply = false;
145 log_oom_extra ("%s:%s: Open : %p",
146 SRCNAME, __func__, m_mail);
148 if (!opt.encrypt_default && !opt.sign_default)
152 LPMESSAGE message = get_oom_base_message (m_object);
155 log_error ("%s:%s: Failed to get message.",
159 if (opt.encrypt_default)
163 if (opt.sign_default)
167 set_gpgol_draft_info_flags (message, draft_flags);
168 gpgol_release (message);
173 log_oom_extra ("%s:%s: BeforeRead : %p",
174 SRCNAME, __func__, m_mail);
175 if (m_mail->preProcessMessage_m ())
177 log_error ("%s:%s: Pre process message failed.",
184 log_oom_extra ("%s:%s: Read : %p",
185 SRCNAME, __func__, m_mail);
186 if (!m_mail->isCryptoMail ())
188 log_debug ("%s:%s: Non crypto mail %p opened. Updating sigstatus.",
189 SRCNAME, __func__, m_mail);
190 /* Ensure that no wrong sigstatus is shown */
191 CloseHandle(CreateThread (NULL, 0, delayed_invalidate_ui, (LPVOID) 300, 0,
195 if (m_mail->setUUID_o ())
197 log_debug ("%s:%s: Failed to set uuid.",
199 delete m_mail; /* deletes this, too */
202 if (m_mail->decryptVerify_o ())
204 log_error ("%s:%s: Decrypt message failed.",
207 if (!opt.enable_smime && m_mail->isSMIME_m ())
209 /* We want to save the mail when it's an smime mail and smime
210 is disabled to revert it. */
211 log_debug ("%s:%s: S/MIME mail but S/MIME is disabled."
214 m_mail->setNeedsSave (true);
220 if (!parms || parms->cArgs != 1 ||
221 parms->rgvarg[0].vt != VT_BSTR ||
222 !parms->rgvarg[0].bstrVal)
224 log_error ("%s:%s: Unexpected params.",
228 const wchar_t *prop_name = parms->rgvarg[0].bstrVal;
229 if (!m_mail->isCryptoMail ())
231 if (!opt.autoresolve)
235 if (m_mail->hasOverrideMimeData())
237 /* This is a mail created by us. Ignore propchanges. */
240 if (!wcscmp (prop_name, L"To") /* ||
241 !wcscmp (prop_name, L"BCC") ||
242 !wcscmp (prop_name, L"CC")
243 Testing shows that Outlook always sends these three in a row
246 if (opt.autosecure || (m_mail->needs_crypto_m () & 1))
248 /* XXX Racy race. This is a fix for crashes
249 that happend if a resolved recipient is copied an pasted.
250 If we then access the recipients object in the Property
251 Change event we crash. Thus we do the delay dance. */
252 HANDLE thread = CreateThread (NULL, 0, do_delayed_locate,
260 for (const wchar_t **cur = prop_blacklist; *cur; cur++)
262 if (!wcscmp (prop_name, *cur))
264 log_oom ("%s:%s: Message %p propchange: %ls discarded.",
265 SRCNAME, __func__, m_object, prop_name);
269 log_oom ("%s:%s: Message %p propchange: %ls.",
270 SRCNAME, __func__, m_object, prop_name);
272 if (!wcscmp (prop_name, L"SendUsingAccount"))
274 bool sent = get_oom_bool (m_object, "Sent");
277 log_debug ("%s:%s: Ignoring SendUsingAccount change for sent %p ",
278 SRCNAME, __func__, m_object);
281 log_debug ("%s:%s: Message %p looks like send again.",
282 SRCNAME, __func__, m_object);
283 m_mail->setIsSendAgain (true);
287 /* We have tried several scenarios to handle propery changes.
288 Only save the property in MAPI and call MAPI SaveChanges
289 worked and did not leak plaintext but this caused outlook
290 still to break the attachments of PGP/MIME Mails into two
291 attachments and add them as winmail.dat so other clients
294 Alternatively reverting the mail, saving the property and
295 then decrypt again also worked a bit but there were some
296 weird side effects and breakages. But this has the usual
297 problem of a revert that the mail is created by outlook and
298 e.g. multipart/signed signatures from most MUA's are broken.
300 Some things to try out might be the close approach and then
301 another open or a selection change. But for now we just warn.
303 As a workardound a user should make property changes when
304 the mail was not read by us. */
305 if (propchangeWarnShown)
310 wchar_t *title = utf8_to_wchar (_("Sorry, that's not possible, yet"));
312 gpgrt_asprintf (&fmt, _("GpgOL has prevented the change to the \"%s\" property.\n"
313 "Property changes are not yet handled for crypto messages.\n\n"
314 "To workaround this limitation please change the property when the "
315 "message is not open in any window and not selected in the "
316 "messagelist.\n\nFor example by right clicking but not selecting the message.\n"),
317 wchar_to_utf8(prop_name));
319 wchar_t *msg = utf8_to_wchar (fmt);
321 MessageBoxW (get_active_hwnd(), msg, title,
322 MB_ICONINFORMATION | MB_OK);
325 propchangeWarnShown = true;
328 case CustomPropertyChange:
330 log_oom_extra ("%s:%s: CustomPropertyChange : %p",
331 SRCNAME, __func__, m_mail);
337 /* This is the only event where we can cancel the send of a
338 mailitem. But it is too early for us to encrypt as the MAPI
339 structures are not yet filled. Crypto based on the
340 Outlook Object Model data did not work as the messages
341 were only sent out empty. See 2b376a48 for a try of
344 This is why we store send_seen and invoke a save which
345 may result in an error but only after triggering all the
346 behavior we need -> filling mapi structures and invoking the
347 AfterWrite handler where we encrypt.
349 If this encryption is successful and we pass the send
350 as then the encrypted data is sent.
352 log_oom_extra ("%s:%s: Send : %p",
353 SRCNAME, __func__, m_mail);
354 if (!m_mail->needs_crypto_m () && m_mail->cryptState () == Mail::NoCryptMail)
356 log_debug ("%s:%s: No crypto neccessary. Passing send for %p obj %p",
357 SRCNAME, __func__, m_mail, m_object);
361 if (parms->cArgs != 1 || parms->rgvarg[0].vt != (VT_BOOL | VT_BYREF))
363 log_debug ("%s:%s: Uncancellable send event.",
368 if (m_mail->cryptState () == Mail::NoCryptMail &&
369 m_mail->needs_crypto_m ())
371 log_debug ("%s:%s: Send event for crypto mail %p saving and starting.",
372 SRCNAME, __func__, m_mail);
374 if (!m_mail->isAsyncCryptDisabled())
376 /* Obtain a reference of the current item. This prevents
377 * an early unload which would crash Outlook 2013
379 * As it didn't crash when the mail was opened in Outlook Spy this
380 * mimics that the mail is inspected somewhere else. */
381 m_mail->refCurrentItem ();
384 // First contact with a mail to encrypt update
385 // state and oom data.
386 m_mail->updateOOMData_o ();
388 m_mail->setCryptState (Mail::NeedsFirstAfterWrite);
390 // Check inline response state before the write.
391 m_mail->check_inline_response ();
393 invoke_oom_method (m_object, "Save", NULL);
395 if (!m_mail->isAsyncCryptDisabled ())
397 // The afterwrite in the save should have triggered
398 // the encryption. We cancel send for our asyncness.
400 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
405 if (m_mail->cryptState () == Mail::NoCryptMail)
407 // Crypto failed or was canceled
408 log_debug ("%s:%s: Message %p mail %p cancelling send - "
409 "Crypto failed or canceled.",
410 SRCNAME, __func__, m_object, m_mail);
411 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
414 // For inline response we can't trigger send programatically
415 // so we do the encryption in sync.
416 if (m_mail->cryptState () == Mail::NeedsUpdateInOOM)
418 m_mail->updateCryptOOM_o ();
420 if (m_mail->cryptState () == Mail::NeedsSecondAfterWrite)
422 m_mail->setCryptState (Mail::WantsSendMIME);
424 if (m_mail->getDoPGPInline () && m_mail->cryptState () != Mail::WantsSendInline)
426 log_debug ("%s:%s: Message %p mail %p cancelling send - "
428 SRCNAME, __func__, m_object, m_mail);
429 gpgol_bug (m_mail->getWindow (),
430 ERR_INLINE_BODY_INV_STATE);
431 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
437 if (m_mail->cryptState () == Mail::WantsSendInline)
439 if (!m_mail->hasCryptedOrEmptyBody_o ())
441 log_debug ("%s:%s: Message %p mail %p cancelling send - "
442 "not encrypted or not empty body detected.",
443 SRCNAME, __func__, m_object, m_mail);
444 gpgol_bug (m_mail->getWindow (),
445 ERR_WANTS_SEND_INLINE_BODY);
446 m_mail->setCryptState (Mail::NoCryptMail);
447 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
450 log_debug ("%s:%s: Passing send event for no-mime message %p.",
451 SRCNAME, __func__, m_object);
452 WKSHelper::instance()->allow_notify (1000);
456 if (m_mail->cryptState () == Mail::WantsSendMIME)
458 if (!m_mail->hasCryptedOrEmptyBody_o ())
460 /* The safety checks here trigger too often. Somehow for some
461 users the body is not empty after the encryption but when
462 it is sent it is still sent with the crypto content because
463 the encrypted MIME Structure is used because it is
464 correct in MAPI land.
466 For safety reasons enabling the checks might be better but
467 until we figure out why for some users the body replacement
468 does not work we have to disable them. Otherwise GpgOL
469 is unusuable for such users. GnuPG-Bug-Id: T3875
471 #define DISABLE_SAFTEY_CHECKS
472 #ifndef DISABLE_SAFTEY_CHECKS
473 gpgol_bug (m_mail->getWindow (),
474 ERR_WANTS_SEND_MIME_BODY);
475 log_debug ("%s:%s: Message %p mail %p cancelling send mime - "
476 "not encrypted or not empty body detected.",
477 SRCNAME, __func__, m_object, m_mail);
478 m_mail->setCryptState (Mail::NoCryptMail);
479 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
482 log_debug ("%s:%s: Message %p mail %p - "
483 "not encrypted or not empty body detected - MIME.",
484 SRCNAME, __func__, m_object, m_mail);
487 /* Now we adress T3656 if Outlooks internal S/MIME is somehow
488 * mixed in (even if it is enabled and then disabled) it might
489 * cause strange behavior in that it sends the plain message
490 * and not the encrypted message. Tests have shown that we can
491 * bypass that by calling submit message on our base
494 * We do this conditionally as our other way of using OOM
495 * to send is proven to work and we don't want to mess
498 // Get the Message class.
500 LPSPropValue propval = NULL;
502 // It's important we use the _not_ base message here.
503 LPMESSAGE message = get_oom_message (m_object);
504 hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
505 gpgol_release (message);
508 log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
509 SRCNAME, __func__, hr);
510 gpgol_release (message);
513 if (propval->Value.lpszA && !strstr (propval->Value.lpszA, "GpgOL"))
515 // Does not have a message class by us.
516 log_debug ("%s:%s: Message %p - No GpgOL Message class after encryption. cls is: '%s'",
517 SRCNAME, __func__, m_object, propval->Value.lpszA);
518 log_debug ("%s:%s: Message %p - Activating T3656 Workaround",
519 SRCNAME, __func__, m_object);
520 message = get_oom_base_message (m_object);
521 // It's important we use the _base_ message here.
522 mapi_save_changes (message, KEEP_OPEN_READWRITE | FORCE_SAVE);
523 message->SubmitMessage(0);
524 gpgol_release (message);
527 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
529 // Close the composer and trigger unloads
530 CloseHandle(CreateThread (NULL, 0, close_mail, (LPVOID) m_mail, 0,
533 MAPIFreeBuffer (propval);
534 if (*(parms->rgvarg[0].pboolVal) == VARIANT_TRUE)
538 log_debug ("%s:%s: Passing send event for mime-encrypted message %p.",
539 SRCNAME, __func__, m_object);
540 WKSHelper::instance()->allow_notify (1000);
545 log_debug ("%s:%s: Message %p cancelling send - "
546 "crypto or second save failed.",
547 SRCNAME, __func__, m_object);
548 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
554 log_oom_extra ("%s:%s: Write : %p",
555 SRCNAME, __func__, m_mail);
556 /* This is a bit strange. We sometimes get multiple write events
557 without a read in between. When we access the message in
558 the second event it fails and if we cancel the event outlook
559 crashes. So we have keep the m_needs_wipe state variable
560 to keep track of that. */
561 if (parms->cArgs != 1 || parms->rgvarg[0].vt != (VT_BOOL | VT_BYREF))
563 /* This happens in the weird case */
564 log_debug ("%s:%s: Uncancellable write event.",
569 if (m_mail->isAboutToBeMoved())
571 log_debug ("%s:%s: Mail is about to be moved. Passing write for %p",
572 SRCNAME, __func__, m_mail);
576 if (m_mail->isCryptoMail () && !m_mail->needsSave ())
578 Mail *last_mail = Mail::getLastMail ();
579 if (Mail::isValidPtr (last_mail))
581 /* We want to identify here if there was a mail created that
582 should receive the contents of this mail. For this we check
583 for a write in the same loop as a mail creation.
584 Now when switching from one mail to another this is also what
585 happens. The new mail is loaded and the old mail is written.
586 To distinguish the two we check that the new mail does not have
587 an entryID, a Subject and No Size. Maybe just size or entryID
588 would be enough but better save then sorry.
590 Security consideration: Worst case we pass the write here but
591 an unload follows before we get the scheduled revert. This
592 would leak plaintext. But does not happen in our tests.
594 Similarly if we crash or Outlook is closed before we see this
595 revert. But as we immediately revert after the write this should
597 const std::string lastSubject = last_mail->getSubject_o ();
598 char *lastEntryID = get_oom_string (last_mail->item (), "EntryID");
599 int lastSize = get_oom_int (last_mail->item (), "Size");
600 std::string lastEntryStr;
603 lastEntryStr = lastEntryID;
607 if (!lastSize && !lastEntryStr.size () && !lastSubject.size ())
609 log_debug ("%s:%s: Write in the same loop as empty load."
610 " Pass but schedule revert.",
613 /* This might be a forward. So don't invalidate yet. */
615 // Mail::clearLastMail ();
617 do_in_ui_thread_async (REVERT_MAIL, m_mail);
621 /* We cancel the write event to stop outlook from excessively
623 if smime support is disabled and we still have an smime
624 mail we also don't want to cancel the write event
625 to enable reverting this mails.
627 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
628 log_debug ("%s:%s: Canceling write event.",
633 if (m_mail->isCryptoMail () && m_mail->needsSave () &&
636 /* An error cleaning the mail should not happen normally.
637 But just in case there is an error we cancel the
639 log_debug ("%s:%s: Failed to remove plaintext.",
641 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
644 if (!m_mail->isCryptoMail () && m_mail->is_forwarded_crypto_mail () &&
645 !m_mail->needs_crypto_m () && m_mail->cryptState () == Mail::NoCryptMail)
647 /* We are sure now that while this is a forward of an encrypted
648 * mail that the forward should not be signed or encrypted. So
649 * it's not constructed by us. We need to remove our attachments
650 * though so that they are not included in the forward. */
651 log_debug ("%s:%s: Writing unencrypted forward of crypt mail. "
652 "Removing attachments. mail: %p item: %p",
653 SRCNAME, __func__, m_mail, m_object);
654 if (m_mail->removeOurAttachments_o ())
656 // Worst case we forward some encrypted data here not
657 // a security problem, so let it pass.
658 log_error ("%s:%s: Failed to remove our attachments.",
661 /* Remove marker because we did this now. */
662 m_mail->setIsForwardedCryptoMail (false);
665 log_debug ("%s:%s: Passing write event.",
667 m_mail->setNeedsSave (false);
672 log_oom_extra ("%s:%s: AfterWrite : %p",
673 SRCNAME, __func__, m_mail);
674 if (m_mail->cryptState () == Mail::NeedsFirstAfterWrite)
676 /* Seen the first after write. Advance the state */
677 m_mail->setCryptState (Mail::NeedsActualCrypt);
678 if (m_mail->encryptSignStart_o ())
680 log_debug ("%s:%s: Encrypt sign start failes.",
682 m_mail->setCryptState (Mail::NoCryptMail);
686 if (m_mail->cryptState () == Mail::NeedsSecondAfterWrite)
688 m_mail->setCryptState (Mail::NeedsUpdateInMAPI);
689 m_mail->updateCryptMAPI_m ();
696 log_oom_extra ("%s:%s: Close : %p",
697 SRCNAME, __func__, m_mail);
698 if (m_mail->isCryptoMail ())
700 /* Close. This happens when an Opened mail is closed.
701 To prevent the question of wether or not to save the changes
702 (Which would save the decrypted data without an event to
703 prevent it) we cancel the close and then either close it
704 with discard changes or revert / save it.
705 Contrary to documentation we can invoke close from
708 if (parms->cArgs != 1 || parms->rgvarg[0].vt != (VT_BOOL | VT_BYREF))
710 /* This happens in the weird case */
711 log_debug ("%s:%s: Uncancellable close event.",
715 if (m_mail->getCloseTriggered ())
717 /* Our close with discard changes, pass through */
718 m_mail->setCloseTriggered (false);
721 *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
722 log_oom_extra ("%s:%s: Canceling close event.",
724 if (Mail::close(m_mail))
726 log_debug ("%s:%s: Close request failed.",
734 log_oom_extra ("%s:%s: Unload : %p",
735 SRCNAME, __func__, m_mail);
736 log_debug ("%s:%s: Removing Mail for message: %p.",
737 SRCNAME, __func__, m_object);
739 log_oom_extra ("%s:%s: deletion done",
752 log_oom_extra ("%s:%s: %s : %p",
753 SRCNAME, __func__, is_reply ? "reply" : "forward", m_mail);
755 if (opt.encrypt_default)
759 if (opt.sign_default)
763 bool is_crypto_mail = m_mail->isCryptoMail ();
765 /* If it is a crypto mail and the settings should not be taken
766 * from the crypto mail and always encrypt / sign is on. Or
767 * If it is not a crypto mail and we have automaticalls sign_encrypt. */
768 if ((is_crypto_mail && !opt.reply_crypt && draft_flags) ||
769 (!is_crypto_mail && draft_flags))
771 /* Check if we can use the dispval */
772 if (parms->cArgs == 2 && parms->rgvarg[1].vt == (VT_DISPATCH) &&
773 parms->rgvarg[0].vt == (VT_BOOL | VT_BYREF))
775 LPMESSAGE msg = get_oom_base_message (parms->rgvarg[1].pdispVal);
778 set_gpgol_draft_info_flags (msg, draft_flags);
783 log_error ("%s:%s: Failed to get base message.",
789 log_error ("%s:%s: Unexpected parameters.",
796 /* Replys to non crypto mails do not interest us anymore. */
800 Mail *last_mail = Mail::getLastMail ();
801 if (Mail::isValidPtr (last_mail))
803 /* We want to identify here if there was a mail created that
804 should receive the contents of this mail. For this we check
805 for a forward in the same loop as a mail creation.
807 We need to do it this complicated and can't just use
808 get_mail_for_item because the mailitem pointer we get here
809 is a different one then the one with which the mail was loaded.
811 char *lastEntryID = get_oom_string (last_mail->item (), "EntryID");
812 int lastSize = get_oom_int (last_mail->item (), "Size");
813 std::string lastEntryStr;
816 lastEntryStr = lastEntryID;
820 if (!lastSize && !lastEntryStr.size ())
824 log_debug ("%s:%s: Forward in the same loop as empty "
825 "load Marking %p (item %p) as forwarded.",
826 SRCNAME, __func__, last_mail,
829 last_mail->setIsForwardedCryptoMail (true);
833 log_debug ("%s:%s: Reply in the same loop as empty "
834 "load Marking %p (item %p) as reply.",
835 SRCNAME, __func__, last_mail,
838 if (m_mail->isBlockHTML ())
840 std::string caption = _("GpgOL") + std::string (": ");
841 caption += is_reply ? _("Dangerous reply") :
842 _("Dangerous forward");
843 std::string buf = _("Unsigned S/MIME mails are not integrity "
849 buf += _("For security reasons no decrypted contents"
850 " are included in this reply.");
854 buf += _("For security reasons no decrypted contents"
855 " are included in the forwarded mail.");
858 gpgol_message_box (get_active_hwnd (), buf.c_str(),
861 do_in_ui_thread_async (CLEAR_REPLY_FORWARD, last_mail, 1000);
864 // We can now invalidate the last mail
865 Mail::clearLastMail ();
868 log_oom_extra ("%s:%s: Reply Forward ReplyAll: %p",
869 SRCNAME, __func__, m_mail);
870 if (!opt.reply_crypt)
874 int crypto_flags = 0;
875 if (!(crypto_flags = m_mail->getCryptoFlags ()))
879 if (parms->cArgs != 2 || parms->rgvarg[1].vt != (VT_DISPATCH) ||
880 parms->rgvarg[0].vt != (VT_BOOL | VT_BYREF))
882 /* This happens in the weird case */
883 log_debug ("%s:%s: Unexpected args %i %x %x named: %i",
884 SRCNAME, __func__, parms->cArgs, parms->rgvarg[0].vt, parms->rgvarg[1].vt,
888 LPMESSAGE msg = get_oom_base_message (parms->rgvarg[1].pdispVal);
891 log_debug ("%s:%s: Failed to get base message",
895 set_gpgol_draft_info_flags (msg, crypto_flags);
899 case AttachmentRemove:
901 log_oom_extra ("%s:%s: AttachmentRemove: %p",
902 SRCNAME, __func__, m_mail);
903 if (!m_mail->isCryptoMail () || attachRemoveWarnShown ||
904 m_mail->attachmentRemoveWarningDisabled ())
908 gpgol_message_box (get_active_hwnd (),
909 _("Attachments are part of the crypto message.\nThey "
910 "can't be permanently removed and will be shown again the next "
911 "time this message is opened."),
912 _("Sorry, that's not possible, yet"), MB_OK);
913 attachRemoveWarnShown = true;
918 log_oom_extra ("%s:%s: Message:%p Unhandled Event: %lx \n",
919 SRCNAME, __func__, m_object, dispid);
923 END_EVENT_SINK(MailItemEvents, IID_MailItemEvents)