Example #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);
        }
Example #2
0
        public void UpdateChainFields(IDaoFactory daoFactory, int tenant, string user, List <int> ids)
        {
            var daoMailInfo = daoFactory.CreateMailInfoDao(tenant, user);

            var mailInfoList = daoMailInfo.GetMailInfoList(
                SimpleMessagesExp.CreateBuilder(tenant, user, null)
                .SetMessageIds(ids)
                .Build())
                               .ConvertAll(x => new
            {
                id_mailbox = x.MailboxId,
                chain_id   = x.ChainId,
                folder     = x.Folder
            });

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

            foreach (var info in mailInfoList.GroupBy(t => new { t.id_mailbox, t.chain_id, t.folder }))
            {
                uint?userFolder = null;

                if (info.Key.folder == FolderType.UserFolder)
                {
                    var userFolderXmailDao = daoFactory.CreateUserFolderXMailDao(Tenant, User);
                    var item = userFolderXmailDao.Get(ids.First());
                    userFolder = item == null ? (uint?)null : item.FolderId;
                }

                UpdateChain(daoFactory, info.Key.chain_id, info.Key.folder, userFolder, info.Key.id_mailbox, tenant, user);
            }
        }
Example #3
0
        public void DeleteMessageAttachments(int tenant, string user, int messageId, List <int> attachmentIds)
        {
            var engine = new EngineFactory(tenant, user);

            long usedQuota;
            int  attachCount;

            using (var daoFactory = new DaoFactory())
            {
                using (var tx = daoFactory.DbManager.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    var exp = new ConcreteMessageAttachmentsExp(messageId, tenant, user, attachmentIds,
                                                                onlyEmbedded: null);

                    var daoAttachment = daoFactory.CreateAttachmentDao(tenant, user);

                    usedQuota = daoAttachment.GetAttachmentsSize(exp);

                    daoAttachment.SetAttachmnetsRemoved(exp);

                    attachCount = daoAttachment.GetAttachmentsCount(
                        new ConcreteMessageAttachmentsExp(messageId, tenant, user));

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

                    daoMailInfo.SetFieldValue(
                        SimpleMessagesExp.CreateBuilder(tenant, user)
                        .SetMessageId(messageId)
                        .Build(),
                        MailTable.Columns.AttachCount,
                        attachCount);

                    engine.ChainEngine.UpdateMessageChainAttachmentsFlag(daoFactory, tenant, user, messageId);

                    tx.Commit();
                }
            }

            if (attachCount == 0)
            {
                var data = new MailWrapper
                {
                    HasAttachments = false
                };

                engine.IndexEngine.Update(data, s => s.Where(m => m.Id, messageId), wrapper => wrapper.HasAttachments);
            }

            if (usedQuota <= 0)
            {
                return;
            }

            engine.QuotaEngine.QuotaUsedDelete(usedQuota);
        }
        // Constructor
        public MailboxMessagesIterator(MailBoxData mailBoxData)
        {
            MailEngine = new EngineFactory(mailBoxData.TenantId, mailBoxData.UserId);
            var range = MailEngine
                        .MessageEngine
                        .GetRangeMessages(
                SimpleMessagesExp.CreateBuilder(mailBoxData.TenantId)
                .SetMailboxId(mailBoxData.MailBoxId)
                .Build());

            _minMessageId = range.Item1;
            _maxMessageId = range.Item2;
        }
Example #5
0
        public List <MailInfo> GetChainedMessagesInfo(DaoFactory daoFactory, List <int> ids)
        {
            var daoMailInfo = daoFactory.CreateMailInfoDao(Tenant, User);

            var chainsInfo = daoMailInfo.GetMailInfoList(
                SimpleMessagesExp.CreateBuilder(Tenant, User)
                .SetMessageIds(ids)
                .Build());

            var chainArray = chainsInfo.Select(r => r.ChainId).Distinct().ToArray();

            const int max_query_count = 25;
            var       i = 0;
            var       unsortedMessages = new List <MailInfo>();

            do
            {
                var partChains = chainArray.Skip(i).Take(max_query_count).ToList();

                if (!partChains.Any())
                {
                    break;
                }

                var selectedMessages = daoMailInfo.GetMailInfoList(
                    SimpleMessagesExp.CreateBuilder(Tenant, User)
                    .SetChainIds(partChains)
                    .Build());

                unsortedMessages.AddRange(selectedMessages);

                i += max_query_count;
            } while (true);

            var result = unsortedMessages
                         .Where(r => chainsInfo.FirstOrDefault(c =>
                                                               c.ChainId == r.ChainId &&
                                                               c.MailboxId == r.MailboxId &&
                                                               ((r.Folder == FolderType.Inbox || r.Folder == FolderType.Sent)
                        ? c.Folder == FolderType.Inbox || c.Folder == FolderType.Sent
                        : c.Folder == r.Folder)) != null)
                         .ToList();

            return(result);
        }
Example #6
0
        private void GetValidForUserMessages(IDaoFactory daoFactory, List <int> messagesIds, out List <int> validIds,
                                             out List <ChainInfo> chains)
        {
            var daoMailInfo = daoFactory.CreateMailInfoDao(Tenant, User);

            var mailInfoList = daoMailInfo.GetMailInfoList(
                SimpleMessagesExp.CreateBuilder(Tenant, User)
                .SetMessageIds(messagesIds)
                .Build());

            validIds = new List <int>();
            chains   = new List <ChainInfo>();

            foreach (var mailInfo in mailInfoList)
            {
                validIds.Add(mailInfo.Id);
                chains.Add(new ChainInfo
                {
                    Id        = mailInfo.ChainId,
                    Folder    = mailInfo.Folder,
                    MailboxId = mailInfo.MailboxId
                });
            }
        }
        public MailMessage Save(MailComposeBase compose)
        {
            var embededAttachmentsForSaving = FixHtmlBodyWithEmbeddedAttachments(compose);

            var message = compose.ToMailMessage();

            var engine = new EngineFactory(compose.Mailbox.TenantId, compose.Mailbox.UserId);

            var addIndex = compose.Id == 0;

            var attachmentsToRestore = message.Attachments.Where(att => att.streamId != message.StreamId || att.isTemp).ToList();

            var needRestoreAttachments = attachmentsToRestore.Any();

            if (needRestoreAttachments)
            {
                message.Attachments.ForEach(
                    attachment =>
                    engine.AttachmentEngine.StoreAttachmentCopy(compose.Mailbox.TenantId, compose.Mailbox.UserId,
                                                                attachment, compose.StreamId));
            }

            MessageEngine.StoreMailBody(compose.Mailbox, message, Log);

            long usedQuota;

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

                using (var tx = db.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    compose.Id = engine.MessageEngine.MailSave(daoFactory, compose.Mailbox, message, compose.Id, message.Folder, message.Folder, null,
                                                               string.Empty, string.Empty, false, out usedQuota);

                    message.Id = compose.Id;

                    if (compose.AccountChanged)
                    {
                        engine.ChainEngine.UpdateChain(daoFactory, message.ChainId, message.Folder, null, compose.PreviousMailboxId,
                                                       compose.Mailbox.TenantId, compose.Mailbox.UserId);
                    }

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

                    if (compose.Id > 0 && needRestoreAttachments)
                    {
                        var daoAttachment       = daoFactory.CreateAttachmentDao(compose.Mailbox.TenantId, compose.Mailbox.UserId);
                        var existingAttachments = daoAttachment.GetAttachments(
                            new ConcreteMessageAttachmentsExp(compose.Id, compose.Mailbox.TenantId, compose.Mailbox.UserId));

                        foreach (var attachment in message.Attachments)
                        {
                            if (existingAttachments.Any(x => x.Id == attachment.fileId))
                            {
                                continue;
                            }

                            var attach = attachment.ToAttachmnet(compose.Id);
                            attach.Id = 0;

                            var newId = daoAttachment.SaveAttachment(attach);
                            attachment.fileId = newId;
                        }

                        if (message.Attachments.Any())
                        {
                            var count = daoAttachment.GetAttachmentsCount(
                                new ConcreteMessageAttachmentsExp(compose.Id, compose.Mailbox.TenantId, compose.Mailbox.UserId));

                            daoMailInfo.SetFieldValue(
                                SimpleMessagesExp.CreateBuilder(compose.Mailbox.TenantId, compose.Mailbox.UserId)
                                .SetMessageId(compose.Id)
                                .Build(),
                                MailTable.Columns.AttachCount,
                                count);
                        }
                    }

                    if (compose.Id > 0 && embededAttachmentsForSaving.Any())
                    {
                        var daoAttachment = daoFactory.CreateAttachmentDao(compose.Mailbox.TenantId, compose.Mailbox.UserId);

                        foreach (var attachment in embededAttachmentsForSaving)
                        {
                            var newId = daoAttachment.SaveAttachment(attachment.ToAttachmnet(compose.Id));
                            attachment.fileId = newId;
                        }

                        if (message.Attachments.Any())
                        {
                            var count = daoAttachment.GetAttachmentsCount(
                                new ConcreteMessageAttachmentsExp(compose.Id, compose.Mailbox.TenantId, compose.Mailbox.UserId));

                            daoMailInfo.SetFieldValue(
                                SimpleMessagesExp.CreateBuilder(compose.Mailbox.TenantId, compose.Mailbox.UserId)
                                .SetMessageId(compose.Id)
                                .Build(),
                                MailTable.Columns.AttachCount,
                                count);
                        }
                    }

                    engine.ChainEngine.UpdateChain(daoFactory, message.ChainId, message.Folder, null, compose.Mailbox.MailBoxId, compose.Mailbox.TenantId,
                                                   compose.Mailbox.UserId);

                    if (compose.AccountChanged)
                    {
                        var daoCrmLink = daoFactory.CreateCrmLinkDao(compose.Mailbox.TenantId, compose.Mailbox.UserId);

                        daoCrmLink.UpdateCrmLinkedMailboxId(message.ChainId, compose.PreviousMailboxId,
                                                            compose.Mailbox.MailBoxId);
                    }

                    tx.Commit();
                }
            }

            if (usedQuota > 0)
            {
                engine.QuotaEngine.QuotaUsedDelete(usedQuota);
            }

            if (addIndex)
            {
                engine.IndexEngine.Add(message.ToMailWrapper(compose.Mailbox.TenantId, new Guid(compose.Mailbox.UserId)));
            }
            else
            {
                engine.IndexEngine.Update(new List <MailWrapper>
                {
                    message.ToMailWrapper(compose.Mailbox.TenantId,
                                          new Guid(compose.Mailbox.UserId))
                });
            }

            try
            {
                var tempStorage = MailDataStore.GetDataStore(compose.Mailbox.TenantId);

                tempStorage.DeleteDirectory("attachments_temp", compose.Mailbox.UserId + "/" + compose.StreamId + "/");
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("Clearing temp storage failed with exception: {0}", ex.ToString());
            }

            return(message);
        }
Example #8
0
        public MailAttachmentData AttachFile(int tenant, string user, MailMessageData message,
                                             string name, Stream inputStream, long contentLength, string contentType = null, bool needSaveToTemp = false)
        {
            if (message == null)
            {
                throw new AttachmentsException(AttachmentsException.Types.MessageNotFound, "Message not found.");
            }

            if (string.IsNullOrEmpty(message.StreamId))
            {
                throw new AttachmentsException(AttachmentsException.Types.MessageNotFound, "StreamId is empty.");
            }

            var messageId = message.Id;

            var engine = new EngineFactory(tenant, user);

            var totalSize =
                engine.AttachmentEngine.GetAttachmentsSize(new ConcreteMessageAttachmentsExp(messageId, tenant, user));

            totalSize += contentLength;

            if (totalSize > Defines.ATTACHMENTS_TOTAL_SIZE_LIMIT)
            {
                throw new AttachmentsException(AttachmentsException.Types.TotalSizeExceeded,
                                               "Total size of all files exceeds limit!");
            }

            var fileNumber =
                engine.AttachmentEngine.GetAttachmentNextFileNumber(new ConcreteMessageAttachmentsExp(messageId, tenant,
                                                                                                      user));

            var attachment = new MailAttachmentData
            {
                fileName       = name,
                contentType    = string.IsNullOrEmpty(contentType) ? MimeMapping.GetMimeMapping(name) : contentType,
                needSaveToTemp = needSaveToTemp,
                fileNumber     = fileNumber,
                size           = contentLength,
                data           = inputStream.ReadToEnd(),
                streamId       = message.StreamId,
                tenant         = tenant,
                user           = user,
                mailboxId      = message.MailboxId
            };

            engine.QuotaEngine.QuotaUsedAdd(contentLength);

            try
            {
                var storage = new StorageManager(tenant, user);
                storage.StoreAttachmentWithoutQuota(attachment);
            }
            catch
            {
                engine.QuotaEngine.QuotaUsedDelete(contentLength);
                throw;
            }

            if (!needSaveToTemp)
            {
                int attachCount;

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

                    using (var tx = db.BeginTransaction())
                    {
                        var daoAttachment = daoFactory.CreateAttachmentDao(tenant, user);

                        attachment.fileId = daoAttachment.SaveAttachment(attachment.ToAttachmnet(messageId));

                        attachCount = daoAttachment.GetAttachmentsCount(
                            new ConcreteMessageAttachmentsExp(messageId, tenant, user));

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

                        daoMailInfo.SetFieldValue(
                            SimpleMessagesExp.CreateBuilder(tenant, user)
                            .SetMessageId(messageId)
                            .Build(),
                            MailTable.Columns.AttachCount,
                            attachCount);

                        engine.ChainEngine.UpdateMessageChainAttachmentsFlag(daoFactory, tenant, user, messageId);

                        tx.Commit();
                    }
                }

                if (attachCount == 1)
                {
                    var data = new MailWrapper
                    {
                        HasAttachments = true
                    };

                    engine.IndexEngine.Update(data, s => s.Where(m => m.Id, messageId), wrapper => wrapper.HasAttachments);
                }
            }

            return(attachment);
        }
Example #9
0
        private void ReleaseSendingDraftOnSuccess(MailDraftData draft, MailMessage message)
        {
            var engine = new EngineFactory(draft.Mailbox.TenantId, draft.Mailbox.UserId);

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

                using (var tx = db.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    // message was correctly send - lets update its chains id
                    var draftChainId = message.ChainId;
                    // before moving message from draft to sent folder - lets recalculate its correct chain id
                    var chainInfo = engine.MessageEngine.DetectChain(daoFactory, draft.Mailbox,
                                                                     message.MimeMessageId, message.MimeReplyToId, message.Subject);

                    message.ChainId = chainInfo.Id;

                    if (message.ChainId.Equals(message.MimeMessageId))
                    {
                        message.MimeReplyToId = null;
                    }

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

                    if (!draftChainId.Equals(message.ChainId))
                    {
                        daoMailInfo.SetFieldValue(
                            SimpleMessagesExp.CreateBuilder(Tenant, User)
                            .SetMessageId(message.Id)
                            .Build(),
                            MailTable.Columns.ChainId,
                            message.ChainId);

                        engine.ChainEngine.UpdateChain(daoFactory, draftChainId, FolderType.Sending, null, draft.Mailbox.MailBoxId,
                                                       draft.Mailbox.TenantId, draft.Mailbox.UserId);

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

                        daoCrmLink.UpdateCrmLinkedChainId(draftChainId, draft.Mailbox.MailBoxId, message.ChainId);
                    }

                    engine.ChainEngine.UpdateChain(daoFactory, message.ChainId, FolderType.Sending, null, draft.Mailbox.MailBoxId,
                                                   draft.Mailbox.TenantId, draft.Mailbox.UserId);

                    var listObjects = engine.ChainEngine.GetChainedMessagesInfo(daoFactory, new List <int> {
                        draft.Id
                    });

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

                    engine.MessageEngine.SetFolder(daoFactory, listObjects, FolderType.Sent);

                    daoMailInfo.SetFieldValue(
                        SimpleMessagesExp.CreateBuilder(Tenant, User)
                        .SetMessageId(draft.Id)
                        .Build(),
                        MailTable.Columns.FolderRestore,
                        FolderType.Sent);

                    tx.Commit();
                }
            }
        }
Example #10
0
        private List <MailMessageData> GetFilteredConversations(IDaoFactory daoFactory, MailSearchFilterData filter, out bool hasMore)
        {
            var conversations = new List <MailMessageData>();
            var skipFlag      = false;
            var chunkIndex    = 0;

            if (filter.FromDate.HasValue && filter.FromMessage.HasValue && filter.FromMessage.Value > 0)
            {
                skipFlag = true;
            }

            var prevFlag   = filter.PrevFlag.GetValueOrDefault(false);
            var tenantInfo = CoreContext.TenantManager.GetTenant(Tenant);
            var utcNow     = DateTime.UtcNow;
            var pageSize   = filter.PageSize.GetValueOrDefault(25);

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

            while (conversations.Count < pageSize + 1)
            {
                filter.PageSize = CHUNK_SIZE * pageSize;

                IMessagesExp exp = null;

                if (!filter.IsDefault() && FactoryIndexer <MailWrapper> .Support && FactoryIndexer.CheckState(false))
                {
                    filter.Page = chunkIndex * CHUNK_SIZE * pageSize; // Elastic Limit from {index of last message} to {count of messages}

                    List <MailWrapper> mailWrappers;
                    if (FilterChainMessagesExp.TryGetFullTextSearchChains(filter, User, out mailWrappers))
                    {
                        if (!mailWrappers.Any())
                        {
                            break;
                        }

                        var ids = mailWrappers.Select(c => c.Id).ToList();

                        var query = SimpleMessagesExp.CreateBuilder(Tenant, User)
                                    .SetMessageIds(ids)
                                    .SetOrderBy(filter.Sort);

                        if (prevFlag)
                        {
                            query.SetOrderAsc(!(filter.SortOrder == Defines.ASCENDING));
                        }
                        else
                        {
                            query.SetOrderAsc(filter.SortOrder == Defines.ASCENDING);
                        }

                        exp = query
                              .Build();
                    }
                }
                else
                {
                    filter.Page = chunkIndex; // MySQL Limit from {page by size} to {size}

                    exp = new FilterChainMessagesExp(filter, Tenant, User);
                }

                chunkIndex++;

                var listMessages = daoMailInfo.GetMailInfoList(exp, true)
                                   .ConvertAll(m => MessageEngine.ToMailMessage(m, tenantInfo, utcNow));

                if (0 == listMessages.Count)
                {
                    break;
                }

                if (skipFlag && filter.FromMessage.HasValue)
                {
                    var messageData = listMessages.FirstOrDefault(m => m.Id == filter.FromMessage.Value);

                    if (messageData != null)
                    {
                        // Skip chain messages by FromMessage.
                        listMessages =
                            listMessages.Where(
                                m => !(m.ChainId.Equals(messageData.ChainId) && m.MailboxId == messageData.MailboxId))
                            .ToList();
                    }

                    skipFlag = false;
                }

                foreach (var messageData in listMessages)
                {
                    var existingChainIndex =
                        conversations.FindIndex(
                            c => c.ChainId == messageData.ChainId && c.MailboxId == messageData.MailboxId);

                    if (existingChainIndex > -1)
                    {
                        if (conversations[existingChainIndex].Date < messageData.Date)
                        {
                            conversations[existingChainIndex] = messageData;
                        }
                    }
                    else
                    {
                        conversations.Add(messageData);
                    }
                }

                if (conversations.Count > pageSize)
                {
                    break;
                }
            }

            hasMore = conversations.Count > pageSize;

            if (hasMore)
            {
                conversations = conversations.Take(pageSize).ToList();
            }

            if (prevFlag)
            {
                conversations.Reverse();
            }

            return(conversations);
        }
Example #11
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);
            }
        }
Example #12
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);
        }
Example #13
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);
            }
        }
Example #14
0
        public void LinkChainToCrm(int messageId, List <CrmContactData> contactIds, string httpContextScheme)
        {
            using (var scope = DIHelper.Resolve())
            {
                var factory = scope.Resolve <CRM.Core.Dao.DaoFactory>();
                foreach (var crmContactEntity in contactIds)
                {
                    switch (crmContactEntity.Type)
                    {
                    case CrmContactData.EntityTypes.Contact:
                        var crmContact = factory.ContactDao.GetByID(crmContactEntity.Id);
                        CRMSecurity.DemandAccessTo(crmContact);
                        break;

                    case CrmContactData.EntityTypes.Case:
                        var crmCase = factory.CasesDao.GetByID(crmContactEntity.Id);
                        CRMSecurity.DemandAccessTo(crmCase);
                        break;

                    case CrmContactData.EntityTypes.Opportunity:
                        var crmOpportunity = factory.DealDao.GetByID(crmContactEntity.Id);
                        CRMSecurity.DemandAccessTo(crmOpportunity);
                        break;
                    }
                }
            }

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

                var daoMail = daoFactory.CreateMailDao(Tenant, User);

                var mail = daoMail.GetMail(new ConcreteUserMessageExp(messageId, Tenant, User));

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

                var chainedMessages = daoMailInfo.GetMailInfoList(
                    SimpleMessagesExp.CreateBuilder(Tenant, User)
                    .SetChainId(mail.ChainId)
                    .Build());

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

                var linkingMessages = new List <MailMessageData>();

                var engine = new EngineFactory(Tenant, User);

                foreach (var chainedMessage in chainedMessages)
                {
                    var message = engine.MessageEngine.GetMessage(chainedMessage.Id,
                                                                  new MailMessageData.Options
                    {
                        LoadImages    = true,
                        LoadBody      = true,
                        NeedProxyHttp = false
                    });

                    message.LinkedCrmEntityIds = contactIds;

                    linkingMessages.Add(message);
                }

                var daoCrmLink = daoFactory.CreateCrmLinkDao(Tenant, User);

                using (var tx = db.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    daoCrmLink.SaveCrmLinks(mail.ChainId, mail.MailboxId, contactIds);

                    foreach (var message in linkingMessages)
                    {
                        try
                        {
                            AddRelationshipEvents(message, httpContextScheme);
                        }
                        catch (ApiHelperException ex)
                        {
                            if (!ex.Message.Equals("Already exists"))
                            {
                                throw;
                            }
                        }
                    }

                    tx.Commit();
                }
            }
        }
Example #15
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();
                }
            }
        }
Example #16
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);
        }
Example #17
0
        public MailMessage Save(MailComposeBase draft)
        {
            var embededAttachmentsForSaving = FixHtmlBodyWithEmbeddedAttachments(draft);

            var message = draft.ToMailMessage();

            var engine = new EngineFactory(draft.Mailbox.TenantId, draft.Mailbox.UserId);

            var addIndex = draft.Id == 0;

            var needRestoreAttachments = draft.Id == 0 && message.Attachments.Any();

            if (needRestoreAttachments)
            {
                message.Attachments.ForEach(
                    attachment =>
                    engine.AttachmentEngine.StoreAttachmentCopy(draft.Mailbox.TenantId, draft.Mailbox.UserId,
                                                                attachment, draft.StreamId));
            }

            MessageEngine.StoreMailBody(draft.Mailbox, message, Log);

            long usedQuota;

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

                using (var tx = db.BeginTransaction(IsolationLevel.ReadUncommitted))
                {
                    draft.Id = engine.MessageEngine.MailSave(daoFactory, draft.Mailbox, message, draft.Id, message.Folder, message.Folder, null,
                                                             string.Empty, string.Empty, false, out usedQuota);

                    message.Id = draft.Id;

                    if (draft.AccountChanged)
                    {
                        engine.ChainEngine.UpdateChain(daoFactory, message.ChainId, message.Folder, null, draft.PreviousMailboxId,
                                                       draft.Mailbox.TenantId, draft.Mailbox.UserId);
                    }

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

                    if (draft.Id > 0 && needRestoreAttachments)
                    {
                        var daoAttachment = daoFactory.CreateAttachmentDao(draft.Mailbox.TenantId, draft.Mailbox.UserId);

                        foreach (var attachment in message.Attachments)
                        {
                            var attach = attachment.ToAttachmnet(draft.Id);
                            attach.Id = 0;

                            var newId = daoAttachment.SaveAttachment(attach);
                            attachment.fileId = newId;
                        }

                        if (message.Attachments.Any())
                        {
                            var count = daoAttachment.GetAttachmentsCount(
                                new ConcreteMessageAttachmentsExp(draft.Id, draft.Mailbox.TenantId, draft.Mailbox.UserId));

                            daoMailInfo.SetFieldValue(
                                SimpleMessagesExp.CreateBuilder(draft.Mailbox.TenantId, draft.Mailbox.UserId)
                                .SetMessageId(draft.Id)
                                .Build(),
                                MailTable.Columns.AttachCount,
                                count);
                        }
                    }

                    if (draft.Id > 0 && embededAttachmentsForSaving.Any())
                    {
                        var daoAttachment = daoFactory.CreateAttachmentDao(draft.Mailbox.TenantId, draft.Mailbox.UserId);

                        foreach (var attachment in embededAttachmentsForSaving)
                        {
                            var newId = daoAttachment.SaveAttachment(attachment.ToAttachmnet(draft.Id));
                            attachment.fileId = newId;
                        }

                        if (message.Attachments.Any())
                        {
                            var count = daoAttachment.GetAttachmentsCount(
                                new ConcreteMessageAttachmentsExp(draft.Id, draft.Mailbox.TenantId, draft.Mailbox.UserId));

                            daoMailInfo.SetFieldValue(
                                SimpleMessagesExp.CreateBuilder(draft.Mailbox.TenantId, draft.Mailbox.UserId)
                                .SetMessageId(draft.Id)
                                .Build(),
                                MailTable.Columns.AttachCount,
                                count);
                        }
                    }

                    engine.ChainEngine.UpdateChain(daoFactory, message.ChainId, message.Folder, null, draft.Mailbox.MailBoxId, draft.Mailbox.TenantId,
                                                   draft.Mailbox.UserId);

                    if (draft.AccountChanged)
                    {
                        var daoCrmLink = daoFactory.CreateCrmLinkDao(draft.Mailbox.TenantId, draft.Mailbox.UserId);

                        daoCrmLink.UpdateCrmLinkedMailboxId(message.ChainId, draft.PreviousMailboxId,
                                                            draft.Mailbox.MailBoxId);
                    }

                    tx.Commit();
                }
            }

            if (usedQuota > 0)
            {
                engine.QuotaEngine.QuotaUsedDelete(usedQuota);
            }

            if (addIndex)
            {
                engine.IndexEngine.Add(message.ToMailWrapper(draft.Mailbox.TenantId, new Guid(draft.Mailbox.UserId)));
            }
            else
            {
                engine.IndexEngine.Update(new List <MailWrapper>
                {
                    message.ToMailWrapper(draft.Mailbox.TenantId,
                                          new Guid(draft.Mailbox.UserId))
                });
            }

            return(message);
        }