示例#1
0
        private static void UpdateMessageChainFlag(IDaoFactory daoFactory, int tenant, string user, int messageId, string fieldFrom, string fieldTo)
        {
            var daoMail = daoFactory.CreateMailDao(tenant, user);

            var mail = daoMail.GetMail(new ConcreteUserMessageExp(messageId, tenant, user));

            if (mail == null)
            {
                return;
            }

            var daoMailInfo = daoFactory.CreateMailInfoDao(tenant, user);

            var maxValue = daoMailInfo.GetFieldMaxValue <bool>(
                SimpleMessagesExp.CreateBuilder(tenant, user)
                .SetChainId(mail.ChainId)
                .SetMailboxId(mail.MailboxId)
                .SetFolder((int)mail.Folder)
                .Build(),
                fieldFrom);

            var daoChain = daoFactory.CreateChainDao(tenant, user);

            daoChain.SetFieldValue(
                SimpleConversationsExp.CreateBuilder(tenant, user)
                .SetChainId(mail.ChainId)
                .SetMailboxId(mail.MailboxId)
                .SetFolder((int)mail.Folder)
                .Build(),
                fieldTo,
                maxValue);
        }
示例#2
0
        public List <Chain> GetChainsById(string id)
        {
            using (var daoFactory = new DaoFactory())
            {
                var daoChain = daoFactory.CreateChainDao(Tenant, User);

                var exp = SimpleConversationsExp.CreateBuilder(Tenant, User)
                          .SetChainIds(new List <string> {
                    id
                })
                          .Build();

                return(daoChain.GetChains(exp));
            }
        }
        public void UpdateChainTags(IDaoFactory daoFactory, string chainId, FolderType folder, int mailboxId, int tenant, string user)
        {
            var tags = GetChainTags(daoFactory, chainId, folder, mailboxId, tenant, user);

            var daoChain = daoFactory.CreateChainDao(tenant, user);

            daoChain.SetFieldValue(
                SimpleConversationsExp.CreateBuilder(tenant, user)
                .SetChainId(chainId)
                .SetMailboxId(mailboxId)
                .SetFolder((int)folder)
                .Build(),
                ChainTable.Columns.Tags,
                tags);
        }
示例#4
0
        /// <summary>
        /// Set mailbox removed
        /// </summary>
        /// <param name="daoFactory"></param>
        /// <param name="mailBoxData"></param>
        /// <returns>Return freed quota value</returns>
        private static long RemoveMailBoxInfo(IDaoFactory daoFactory, MailBoxData mailBoxData)
        {
            if (mailBoxData.MailBoxId <= 0)
            {
                throw new Exception("MailBox id is 0");
            }

            var daoMailbox = daoFactory.CreateMailboxDao();

            var mailbox = daoMailbox.GetMailBox(
                new СoncreteUserMailboxExp(mailBoxData.MailBoxId, mailBoxData.TenantId, mailBoxData.UserId, null));

            if (mailbox == null)
            {
                throw new Exception(string.Format("MailBox with id = {0} (Tenant={1}, User='******') not found",
                                                  mailBoxData.MailBoxId, mailBoxData.TenantId, mailBoxData.UserId));
            }

            daoMailbox.SetMailboxRemoved(mailbox);

            var daoChain = daoFactory.CreateChainDao(mailBoxData.TenantId, mailBoxData.UserId);

            var folderTypes = Enum.GetValues(typeof(FolderType)).Cast <int>().ToList();

            daoChain.Delete(
                SimpleConversationsExp.CreateBuilder(mailBoxData.TenantId, mailBoxData.UserId)
                .SetFoldersIds(folderTypes)
                .SetMailboxId(mailBoxData.MailBoxId)
                .Build());

            var daoCrmLink = daoFactory.CreateCrmLinkDao(mailBoxData.TenantId, mailBoxData.UserId);

            daoCrmLink.RemoveCrmLinks(mailBoxData.MailBoxId);

            var daoMailInfo = daoFactory.CreateMailInfoDao(mailBoxData.TenantId, mailBoxData.UserId);

            daoMailInfo.SetFieldValue(
                SimpleMessagesExp.CreateBuilder(mailBoxData.TenantId, mailBoxData.UserId)
                .SetMailboxId(mailBoxData.MailBoxId)
                .Build(),
                MailTable.Columns.IsRemoved,
                true);

            var exp = new ConcreteMailboxAttachmentsExp(mailBoxData.MailBoxId, mailBoxData.TenantId, mailBoxData.UserId,
                                                        onlyEmbedded: null);

            var daoAttachment = daoFactory.CreateAttachmentDao(mailBoxData.TenantId, mailBoxData.UserId);

            var totalAttachmentsSize = daoAttachment.GetAttachmentsSize(exp);

            daoAttachment.SetAttachmnetsRemoved(exp);

            var tagDao = daoFactory.CreateTagDao(mailBoxData.TenantId, mailBoxData.UserId);

            var tagMailDao = daoFactory.CreateTagMailDao(mailBoxData.TenantId, mailBoxData.UserId);

            var tagIds = tagMailDao.GetTagIds(mailBoxData.MailBoxId);

            tagMailDao.DeleteByMailboxId(mailBoxData.MailBoxId);

            foreach (var tagId in tagIds)
            {
                var tag = tagDao.GetTag(tagId);

                if (tag == null)
                {
                    continue;
                }

                var count = tagMailDao.CalculateTagCount(tag.Id);

                tag.Count = count;

                tagDao.SaveTag(tag);
            }

            daoFactory.CreateMailboxSignatureDao(mailBoxData.TenantId, mailBoxData.UserId).DeleteSignature(mailBoxData.MailBoxId);

            daoFactory.CreateMailboxAutoreplyDao(mailBoxData.TenantId, mailBoxData.UserId)
            .DeleteAutoreply(mailBoxData.MailBoxId);

            daoFactory.CreateMailboxAutoreplyHistoryDao(mailBoxData.TenantId, mailBoxData.UserId).DeleteAutoreplyHistory(mailBoxData.MailBoxId);

            daoFactory.CreateAlertDao(mailBoxData.TenantId, mailBoxData.UserId).DeleteAlerts(mailBoxData.MailBoxId);

            daoFactory.CreateUserFolderXMailDao(mailBoxData.TenantId, mailBoxData.UserId)
            .RemoveByMailbox(mailBoxData.MailBoxId);

            return(totalAttachmentsSize);
        }
示例#5
0
        // Method for updating chain flags, date and length.
        public void UpdateChain(IDaoFactory daoFactory, string chainId, FolderType folder, uint?userFolderId, int mailboxId,
                                int tenant, string user)
        {
            if (string.IsNullOrEmpty(chainId))
            {
                return;
            }

            var db     = daoFactory.DbManager;
            var engine = new EngineFactory(tenant, user, Log);

            var daoMailInfo = daoFactory.CreateMailInfoDao(tenant, user);

            const string m_alias = "m";

            var getChainQuery = new SqlQuery(MailTable.TABLE_NAME.Alias(m_alias))
                                .SelectCount()
                                .SelectMax(MailTable.Columns.DateSent.Prefix(m_alias))
                                .SelectMax(MailTable.Columns.Unread.Prefix(m_alias))
                                .SelectMax(MailTable.Columns.AttachCount.Prefix(m_alias))
                                .SelectMax(MailTable.Columns.Importance.Prefix(m_alias))
                                .Where(MailTable.Columns.Tenant.Prefix(m_alias), tenant)
                                .Where(MailTable.Columns.User.Prefix(m_alias), user)
                                .Where(MailTable.Columns.IsRemoved.Prefix(m_alias), 0)
                                .Where(MailTable.Columns.ChainId.Prefix(m_alias), chainId)
                                .Where(MailTable.Columns.MailboxId.Prefix(m_alias), mailboxId)
                                .Where(MailTable.Columns.Folder.Prefix(m_alias), (int)folder);

            var chainInfo = db.ExecuteList(getChainQuery)
                            .ConvertAll(x => new
            {
                length       = Convert.ToInt32(x[0]),
                date         = Convert.ToDateTime(x[1]),
                unread       = Convert.ToBoolean(x[2]),
                attach_count = Convert.ToInt32(x[3]),
                importance   = Convert.ToBoolean(x[4])
            })
                            .FirstOrDefault();

            if (chainInfo == null)
            {
                throw new InvalidDataException("Conversation is absent in MAIL_MAIL");
            }

            var daoChain = daoFactory.CreateChainDao(tenant, user);

            var query = SimpleConversationsExp.CreateBuilder(tenant, user)
                        .SetMailboxId(mailboxId)
                        .SetChainId(chainId)
                        .SetFolder((int)folder)
                        .Build();

            var storedChainInfo = daoChain.GetChains(query);

            var chainUnreadFlag = storedChainInfo.Any(c => c.Unread);

            if (0 == chainInfo.length)
            {
                var deletQuery = SimpleConversationsExp.CreateBuilder(tenant, user)
                                 .SetFolder((int)folder)
                                 .SetMailboxId(mailboxId)
                                 .SetChainId(chainId)
                                 .Build();

                var result = daoChain.Delete(deletQuery);

                Log.DebugFormat(
                    "UpdateChain() row deleted from chain table tenant='{0}', user_id='{1}', id_mailbox='{2}', folder='{3}', chain_id='{4}' result={5}",
                    tenant, user, mailboxId, folder, chainId, result);

                var unreadConvDiff = chainUnreadFlag ? -1 : (int?)null;

                engine.FolderEngine.ChangeFolderCounters(daoFactory, folder, userFolderId,
                                                         unreadConvDiff: unreadConvDiff, totalConvDiff: -1);
            }
            else
            {
                //var updateMailQuery = new SqlUpdate(MailTable.TABLE_NAME)
                //    .Where(MailTable.Columns.Tenant, tenant)
                //    .Where(MailTable.Columns.User, user)
                //    .Where(MailTable.Columns.IsRemoved, 0)
                //    .Where(MailTable.Columns.ChainId, chainId)
                //    .Where(MailTable.Columns.MailboxId, mailboxId)
                //    .Where(MailTable.Columns.Folder, (int) folder)
                //    // Folder condition important because chain has different dates in different folders(Ex: Sent and Inbox).
                //    .Set(MailTable.Columns.ChainDate, chainInfo.date);

                //db.ExecuteNonQuery(updateMailQuery);

                var updateQuery = SimpleMessagesExp.CreateBuilder(tenant, user)
                                  .SetChainId(chainId)
                                  .SetMailboxId(mailboxId)
                                  .SetFolder((int)folder)
                                  .Build();

                daoMailInfo.SetFieldValue(updateQuery,
                                          MailTable.Columns.ChainDate,
                                          chainInfo.date);

                var tags = GetChainTags(daoFactory, chainId, folder, mailboxId, tenant, user);

                var chain = new Chain
                {
                    Id             = chainId,
                    Tenant         = tenant,
                    User           = user,
                    MailboxId      = mailboxId,
                    Folder         = folder,
                    Length         = chainInfo.length,
                    Unread         = chainInfo.unread,
                    HasAttachments = chainInfo.attach_count > 0,
                    Importance     = chainInfo.importance,
                    Tags           = tags
                };

                var result = daoChain.SaveChain(chain);

                if (result <= 0)
                {
                    throw new InvalidOperationException(string.Format("Invalid insert into {0}", ChainTable.TABLE_NAME));
                }

                Log.DebugFormat(
                    "UpdateChain() row inserted to chain table tenant='{0}', user_id='{1}', id_mailbox='{2}', folder='{3}', chain_id='{4}'",
                    tenant, user, mailboxId, folder, chainId);

                var unreadConvDiff = (int?)null;
                var totalConvDiff  = (int?)null;

                if (!storedChainInfo.Any())
                {
                    totalConvDiff  = 1;
                    unreadConvDiff = chainInfo.unread ? 1 : (int?)null;
                }
                else
                {
                    if (chainUnreadFlag != chainInfo.unread)
                    {
                        unreadConvDiff = chainInfo.unread ? 1 : -1;
                    }
                }

                engine.FolderEngine.ChangeFolderCounters(daoFactory, folder, userFolderId,
                                                         unreadConvDiff: unreadConvDiff, totalConvDiff: totalConvDiff);
            }
        }
示例#6
0
        public void SetConversationsImportanceFlags(int tenant, string user, bool important, List <int> ids)
        {
            List <MailInfo> mailInfos;

            using (var daoFactory = new DaoFactory())
            {
                mailInfos = GetChainedMessagesInfo(daoFactory, ids);

                var chainsInfo = mailInfos
                                 .Select(m => new
                {
                    m.ChainId,
                    m.MailboxId,
                    m.Folder
                })
                                 .Distinct().ToList();

                if (!chainsInfo.Any())
                {
                    throw new Exception("no chain messages belong to current user");
                }

                using (var tx = daoFactory.DbManager.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    var daoMailInfo = daoFactory.CreateMailInfoDao(tenant, user);

                    var exp    = Exp.Empty;
                    var сhains = new List <Tuple <int, string> >();

                    foreach (var chain in chainsInfo)
                    {
                        var key = new Tuple <int, string>(chain.MailboxId, chain.ChainId);

                        if (сhains.Any() &&
                            сhains.Contains(key) &&
                            (chain.Folder == FolderType.Inbox || chain.Folder == FolderType.Sent))
                        {
                            continue;
                        }

                        var innerWhere = Exp.And(
                            Exp.Eq(MailTable.Columns.ChainId.Prefix(MM_ALIAS), chain.ChainId),
                            Exp.Eq(MailTable.Columns.MailboxId.Prefix(MM_ALIAS), chain.MailboxId));

                        if (chain.Folder == FolderType.Inbox || chain.Folder == FolderType.Sent)
                        {
                            innerWhere &= Exp.Or(
                                Exp.Eq(MailTable.Columns.Folder.Prefix(MM_ALIAS), (int)FolderType.Inbox),
                                Exp.Eq(MailTable.Columns.Folder.Prefix(MM_ALIAS), (int)FolderType.Sent));

                            сhains.Add(key);
                        }
                        else
                        {
                            innerWhere &= Exp.Eq(MailTable.Columns.Folder.Prefix(MM_ALIAS), (int)chain.Folder);
                        }

                        exp |= innerWhere;
                    }

                    daoMailInfo.SetFieldValue(
                        SimpleMessagesExp.CreateBuilder(tenant, user)
                        .SetExp(exp)
                        .Build(),
                        MailTable.Columns.Importance,
                        important);

                    var daoChain = daoFactory.CreateChainDao(tenant, user);

                    foreach (var chain in chainsInfo)
                    {
                        daoChain.SetFieldValue(
                            SimpleConversationsExp.CreateBuilder(tenant, user)
                            .SetChainId(chain.ChainId)
                            .SetMailboxId(chain.MailboxId)
                            .SetFolder((int)chain.Folder)
                            .Build(),
                            ChainTable.Columns.Importance,
                            important);
                    }

                    tx.Commit();
                }
            }

            var factory = new EngineFactory(Tenant, User);

            var data = new MailWrapper
            {
                Importance = important
            };

            factory.IndexEngine.Update(data, s => s.In(m => m.Id, mailInfos.Select(o => o.Id).ToArray()),
                                       wrapper => wrapper.Importance);
        }
示例#7
0
        public List <MailMessageData> GetConversationMessages(int tenant, string user, int messageId,
                                                              bool loadAllContent, bool needProxyHttp, bool needMailSanitazer, bool markRead = false)
        {
            var engine = new EngineFactory(tenant, user);

            using (var daoFactory = new DaoFactory())
            {
                var db = daoFactory.DbManager;

                var daoMailInfo = daoFactory.CreateMailInfoDao(tenant, user);

                var messageInfo = daoMailInfo.GetMailInfoList(
                    SimpleMessagesExp.CreateBuilder(tenant, user)
                    .SetMessageId(messageId)
                    .Build())
                                  .SingleOrDefault();

                if (messageInfo == null)
                {
                    throw new ArgumentException("Message Id not found");
                }

                var searchFolders = new List <int>();

                if (messageInfo.Folder == FolderType.Inbox || messageInfo.Folder == FolderType.Sent)
                {
                    searchFolders.AddRange(new[] { (int)FolderType.Inbox, (int)FolderType.Sent });
                }
                else
                {
                    searchFolders.Add((int)messageInfo.Folder);
                }

                var exp = SimpleMessagesExp.CreateBuilder(tenant, user)
                          .SetMailboxId(messageInfo.MailboxId)
                          .SetChainId(messageInfo.ChainId)
                          .SetFoldersIds(searchFolders)
                          .Build();

                var mailInfoList = daoMailInfo.GetMailInfoList(exp);

                var ids = mailInfoList.Select(m => m.Id).ToList();

                var messages =
                    ids.Select(
                        (id, i) =>
                        engine.MessageEngine.GetMessage(daoFactory, id,
                                                        new MailMessageData.Options
                {
                    LoadImages    = false,
                    LoadBody      = loadAllContent || (id == messageId),
                    NeedProxyHttp = needProxyHttp,
                    NeedSanitizer = needMailSanitazer
                }))
                    .Where(mailInfo => mailInfo != null)
                    .OrderBy(m => m.Date)
                    .ToList();

                if (!markRead)
                {
                    return(messages);
                }

                var unreadMessages = messages.Where(message => message.WasNew).ToList();
                if (!unreadMessages.Any())
                {
                    return(messages);
                }

                var unreadMessagesCountByFolder = new Dictionary <FolderType, int>();

                foreach (var message in unreadMessages)
                {
                    if (unreadMessagesCountByFolder.ContainsKey(message.Folder))
                    {
                        unreadMessagesCountByFolder[message.Folder] += 1;
                    }
                    else
                    {
                        unreadMessagesCountByFolder.Add(message.Folder, 1);
                    }
                }

                var userFolderXmailDao = daoFactory.CreateUserFolderXMailDao(tenant, user);

                uint?userFolder = null;

                if (unreadMessagesCountByFolder.Keys.Any(k => k == FolderType.UserFolder))
                {
                    var item = userFolderXmailDao.Get(ids.First());
                    userFolder = item == null ? (uint?)null : item.FolderId;
                }

                List <int> ids2Update;

                using (var tx = db.BeginTransaction())
                {
                    ids2Update = unreadMessages.Select(x => x.Id).ToList();

                    daoMailInfo.SetFieldValue(
                        SimpleMessagesExp.CreateBuilder(tenant, user)
                        .SetMessageIds(ids2Update)
                        .Build(),
                        MailTable.Columns.Unread,
                        false);

                    var daoChain = daoFactory.CreateChainDao(tenant, user);

                    foreach (var keyPair in unreadMessagesCountByFolder)
                    {
                        var folderType = keyPair.Key;

                        var unreadMessDiff = keyPair.Value != 0 ? keyPair.Value * (-1) : (int?)null;

                        engine.FolderEngine.ChangeFolderCounters(daoFactory, folderType, userFolder,
                                                                 unreadMessDiff, unreadConvDiff: -1);

                        daoChain.SetFieldValue(
                            SimpleConversationsExp.CreateBuilder(tenant, user)
                            .SetChainId(messageInfo.ChainId)
                            .SetMailboxId(messageInfo.MailboxId)
                            .SetFolder((int)keyPair.Key)
                            .Build(),
                            ChainTable.Columns.Unread,
                            false);
                    }

                    if (userFolder.HasValue)
                    {
                        var userFoldersIds = userFolderXmailDao.GetList(mailIds: ids)
                                             .Select(ufxm => (int)ufxm.FolderId)
                                             .Distinct()
                                             .ToList();

                        engine.UserFolderEngine.RecalculateCounters(daoFactory, userFoldersIds);
                    }

                    tx.Commit();
                }

                var data = new MailWrapper
                {
                    Unread = false
                };

                engine.IndexEngine.Update(data, s => s.In(m => m.Id, ids2Update.ToArray()), wrapper => wrapper.Unread);

                return(messages);
            }
        }
示例#8
0
        public List <MailMessageData> GetConversations(MailSearchFilterData filterData, out bool hasMore)
        {
            if (filterData == null)
            {
                throw new ArgumentNullException("filterData");
            }

            var filter = (MailSearchFilterData)filterData.Clone();

            if (filter.UserFolderId.HasValue && Factory.UserFolderEngine.Get((uint)filter.UserFolderId.Value) == null)
            {
                throw new ArgumentException("Folder not found");
            }

            using (var daoFactory = new DaoFactory())
            {
                var filteredConversations = GetFilteredConversations(daoFactory, filter, out hasMore);

                if (!filteredConversations.Any())
                {
                    return(filteredConversations);
                }

                var chainIds = new List <string>();
                filteredConversations.ForEach(x => chainIds.Add(x.ChainId));

                var daoChain = daoFactory.CreateChainDao(Tenant, User);

                var exp = SimpleConversationsExp.CreateBuilder(Tenant, User)
                          .SetChainIds(chainIds)
                          .SetFoldersIds(
                    filter.PrimaryFolder == FolderType.Inbox ||
                    filter.PrimaryFolder == FolderType.Sent
                            ? new List <int> {
                    (int)FolderType.Inbox, (int)FolderType.Sent
                }
                            : new List <int> {
                    (int)filter.PrimaryFolder
                })
                          .Build();

                var extendedInfo = daoChain.GetChains(exp);

                foreach (var chain in filteredConversations)
                {
                    var chainMessages = extendedInfo.FindAll(x => x.MailboxId == chain.MailboxId && x.Id == chain.ChainId);
                    if (!chainMessages.Any())
                    {
                        continue;
                    }
                    chain.IsNew          = chainMessages.Any(x => x.Unread);
                    chain.HasAttachments = chainMessages.Any(x => x.HasAttachments);
                    chain.Important      = chainMessages.Any(x => x.Importance);
                    chain.ChainLength    = chainMessages.Sum(x => x.Length);
                    var firstOrDefault = chainMessages.FirstOrDefault(x => !string.IsNullOrEmpty(x.Tags));
                    chain.LabelsString = firstOrDefault != null ? firstOrDefault.Tags : "";
                }

                return(filteredConversations);
            }
        }
示例#9
0
        public void RecalculateFolders(Action <MailOperationRecalculateMailboxProgress> callback = null)
        {
            using (var db = new DbManager(Defines.CONNECTION_STRING_NAME, Defines.RecalculateFoldersTimeout))
            {
                var daoFactory = new DaoFactory(db);

                var daoFolder = daoFactory.CreateFolderDao(Tenant, User);

                using (var tx = db.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    var folderTypes = Enum.GetValues(typeof(FolderType)).Cast <int>();

                    var daoMailInfo = daoFactory.CreateMailInfoDao(Tenant, User);

                    if (callback != null)
                    {
                        callback(MailOperationRecalculateMailboxProgress.CountUnreadMessages);
                    }

                    var unreadMessagesCountByFolder =
                        daoMailInfo.GetMailCount(
                            SimpleMessagesExp.CreateBuilder(Tenant, User)
                            .SetUnread(true)
                            .Build());

                    if (callback != null)
                    {
                        callback(MailOperationRecalculateMailboxProgress.CountTotalMessages);
                    }

                    var totalMessagesCountByFolder = daoMailInfo.GetMailCount(
                        SimpleMessagesExp.CreateBuilder(Tenant, User)
                        .Build());

                    var daoChain = daoFactory.CreateChainDao(Tenant, User);

                    if (callback != null)
                    {
                        callback(MailOperationRecalculateMailboxProgress.CountUreadConversation);
                    }

                    var unreadConversationsCountByFolder = daoChain.GetChainCount(
                        SimpleConversationsExp.CreateBuilder(Tenant, User)
                        .SetUnread(true)
                        .Build());

                    if (callback != null)
                    {
                        callback(MailOperationRecalculateMailboxProgress.CountTotalConversation);
                    }

                    var totalConversationsCountByFolder = daoChain.GetChainCount(
                        SimpleConversationsExp.CreateBuilder(Tenant, User)
                        .Build());

                    if (callback != null)
                    {
                        callback(MailOperationRecalculateMailboxProgress.UpdateFoldersCounters);
                    }

                    var now = DateTime.UtcNow;

                    var folders = (from folderId in folderTypes
                                   let unreadMessCount =
                                       unreadMessagesCountByFolder.ContainsKey(folderId)
                                ? unreadMessagesCountByFolder[folderId]
                                : 0
                                       let totalMessCount =
                                           totalMessagesCountByFolder.ContainsKey(folderId)
                                ? totalMessagesCountByFolder[folderId]
                                : 0
                                           let unreadConvCount =
                                               unreadConversationsCountByFolder.ContainsKey(folderId)
                                ? unreadConversationsCountByFolder[folderId]
                                : 0
                                               let totalConvCount =
                                                   totalConversationsCountByFolder.ContainsKey(folderId)
                                ? totalConversationsCountByFolder[folderId]
                                : 0
                                                   select new Folder
                    {
                        FolderType = (FolderType)folderId,
                        Tenant = Tenant,
                        UserId = User,
                        UnreadCount = unreadMessCount,
                        UnreadChainCount = unreadConvCount,
                        TotalCount = totalMessCount,
                        TotalChainCount = totalConvCount,
                        TimeModified = now
                    })
                                  .ToList();

                    foreach (var folder in folders)
                    {
                        daoFolder.Save(folder);
                    }

                    var userFolder = folders.FirstOrDefault(f => f.FolderType == FolderType.UserFolder);

                    if (userFolder != null)
                    {
                        var daoUserFolder = daoFactory.CreateUserFolderDao(Tenant, User);

                        var userFolders =
                            daoUserFolder.GetList(
                                SimpleUserFoldersExp.CreateBuilder(Tenant, User)
                                .Build());

                        if (userFolders.Any())
                        {
                            var totalMessagesCountByUserFolder = daoMailInfo.GetMailUserFolderCount();

                            if (callback != null)
                            {
                                callback(MailOperationRecalculateMailboxProgress.CountTotalUserFolderMessages);
                            }

                            var unreadMessagesCountByUserFolder = daoMailInfo.GetMailUserFolderCount(true);

                            if (callback != null)
                            {
                                callback(MailOperationRecalculateMailboxProgress.CountUnreadUserFolderMessages);
                            }

                            var totalConversationsCountByUserFolder = daoChain.GetChainUserFolderCount();

                            if (callback != null)
                            {
                                callback(MailOperationRecalculateMailboxProgress.CountTotalUserFolderConversation);
                            }

                            var unreadConversationsCountByUserFolder = daoChain.GetChainUserFolderCount(true);

                            if (callback != null)
                            {
                                callback(MailOperationRecalculateMailboxProgress.CountUreadUserFolderConversation);
                            }

                            var newUserFolders = (from folder in userFolders
                                                  let unreadMessCount =
                                                      unreadMessagesCountByUserFolder.ContainsKey(folder.Id)
                                        ? unreadMessagesCountByUserFolder[folder.Id]
                                        : 0
                                                      let totalMessCount =
                                                          totalMessagesCountByUserFolder.ContainsKey(folder.Id)
                                        ? totalMessagesCountByUserFolder[folder.Id]
                                        : 0
                                                          let unreadConvCount =
                                                              unreadConversationsCountByUserFolder.ContainsKey(folder.Id)
                                        ? unreadConversationsCountByUserFolder[folder.Id]
                                        : 0
                                                              let totalConvCount =
                                                                  totalConversationsCountByUserFolder.ContainsKey(folder.Id)
                                        ? totalConversationsCountByUserFolder[folder.Id]
                                        : 0
                                                                  select new UserFolder
                            {
                                Id = folder.Id,
                                ParentId = folder.ParentId,
                                Name = folder.Name,
                                FolderCount = folder.FolderCount,
                                Tenant = Tenant,
                                User = User,
                                UnreadCount = unreadMessCount,
                                UnreadChainCount = unreadConvCount,
                                TotalCount = totalMessCount,
                                TotalChainCount = totalConvCount,
                                TimeModified = now
                            })
                                                 .ToList();

                            if (callback != null)
                            {
                                callback(MailOperationRecalculateMailboxProgress.UpdateUserFoldersCounters);
                            }

                            foreach (var folder in newUserFolders)
                            {
                                daoUserFolder.Save(folder);
                            }
                        }
                    }

                    tx.Commit();
                }
            }
        }