bool
PersistentAccount::DeleteObject(boost::shared_ptr<Account> pAccount)
{
    __int64 iID = pAccount->GetID();
    assert(iID);

    if (iID <= 0)
        return false;

    // Delete messages connected to this account.
    DeleteMessages(pAccount);

    // Force delete the inbox as well. DeleteMessages above does not delete it.
    boost::shared_ptr<IMAPFolder> inbox = pAccount->GetFolders()->GetFolderByName("Inbox");
    if (inbox)
        PersistentIMAPFolder::DeleteObject(inbox, true);

    pAccount->GetRules()->DeleteAll();

    // Delete fetch accounts connected to this account.
    PersistentFetchAccount::DeleteByAccountID(iID);

    // Delete references from groups...
    PersistentGroupMember::DeleteByAccount(iID);

    PersistentACLPermission::DeleteOwnedByAccount(iID);

    SQLCommand deleteCommand("delete from hm_accounts where accountid = @ACCOUNTID");
    deleteCommand.AddParameter("@ACCOUNTID", iID);

    bool bRet = Application::Instance()->GetDBManager()->Execute(deleteCommand);

    // Delete folder from data directory
    String sAccountFolder = IniFileSettings::Instance()->GetDataDirectory() + "\\" + StringParser::ExtractDomain(pAccount->GetAddress()) + "\\" + StringParser::ExtractAddress(pAccount->GetAddress());
    FileUtilities::DeleteDirectory(sAccountFolder);

    // Refresh caches.
    Cache<Account, PersistentAccount>::Instance()->RemoveObject(pAccount);

    return bRet;
}
   IMAPResult
   IMAPCommandEXPUNGE::ExecuteCommand(std::shared_ptr<IMAPConnection> pConnection, std::shared_ptr<IMAPCommandArgument> pArgument)
   {
      if (!pConnection->IsAuthenticated())
         return IMAPResult(IMAPResult::ResultNo, "Authenticate first");

      if (pConnection->GetCurrentFolderReadOnly())
      {
         return IMAPResult(IMAPResult::ResultNo, "Expunge command on read-only folder.");
      }

      // Iterate through mail boxes and delete messages marked for deletion.
      std::shared_ptr<IMAPFolder> pCurFolder = pConnection->GetCurrentFolder();   

      if (!pCurFolder)
         return IMAPResult(IMAPResult::ResultNo, "No folder selected.");

      if (!pConnection->CheckPermission(pCurFolder, ACLPermission::PermissionExpunge))
         return IMAPResult(IMAPResult::ResultBad, "ACL: Expunge permission denied (Required for EXPUNGE command).");

      std::vector<__int64> expunged_messages_uid;
      std::vector<__int64> expunged_messages_index;

      std::function<bool(int, std::shared_ptr<Message>)> filter = [&expunged_messages_index, &expunged_messages_uid](int index, std::shared_ptr<Message> message)
      {
         if (message->GetFlagDeleted())
         {
            expunged_messages_index.push_back(index);
            expunged_messages_uid.push_back(message->GetID());
            return true;
         }

         return false;
      };

      auto messages = MessagesContainer::Instance()->GetMessages(pCurFolder->GetAccountID(), pCurFolder->GetID());
      messages->DeleteMessages(filter);

      auto iterExpunged = expunged_messages_index.begin();

      String sResponse;
      while (iterExpunged != expunged_messages_index.end())
      {
         String sTemp;
         sTemp.Format(_T("* %d EXPUNGE\r\n"), (*iterExpunged));
         sResponse += sTemp;
         iterExpunged++;
      }

      pConnection->SendAsciiData(sResponse);

      if (!expunged_messages_uid.empty())
      {
         auto recent_messages = pConnection->GetRecentMessages();

         for (__int64 messageUid : expunged_messages_uid)
         {
            auto recent_messages_it = recent_messages.find(messageUid);
            if (recent_messages_it != recent_messages.end())
               recent_messages.erase(recent_messages_it);
         }
         

         // Messages have been expunged
         // Notify the mailbox notifier that the mailbox contents have changed.
         std::shared_ptr<ChangeNotification> pNotification = 
            std::shared_ptr<ChangeNotification>(new ChangeNotification(pCurFolder->GetAccountID(), pCurFolder->GetID(), ChangeNotification::NotificationMessageDeleted, expunged_messages_index));

         Application::Instance()->GetNotificationServer()->SendNotification(pConnection->GetNotificationClient(), pNotification);
      }


      // We're done.
      sResponse = pArgument->Tag() + " OK EXPUNGE Completed\r\n";
      pConnection->SendAsciiData(sResponse);   

      return IMAPResult();
   }