public void StoreAttachmentWithoutQuota(int id_tenant, string id_user, MailAttachment attachment, IDataStore storage)
        {
            try
            {
                if (attachment.data == null || attachment.data.Length == 0)
                {
                    return;
                }

                if (string.IsNullOrEmpty(attachment.fileName))
                {
                    attachment.fileName = "attachment.ext";
                }

                var content_disposition = MailStoragePathCombiner.PrepareAttachmentName(attachment.fileName);

                var ext = Path.GetExtension(attachment.fileName);

                attachment.storedName = CreateNewStreamId();

                if (!string.IsNullOrEmpty(ext))
                {
                    attachment.storedName = Path.ChangeExtension(attachment.storedName, ext);
                }

                attachment.fileNumber =
                    !string.IsNullOrEmpty(attachment.contentId) //Upload hack: embedded attachment have to be saved in 0 folder
                        ? 0
                        : attachment.fileNumber;

                var attachment_path = MailStoragePathCombiner.GerStoredFilePath(attachment);

                using (var reader = new MemoryStream(attachment.data))
                {
                    var upload_url = storage.UploadWithoutQuota(string.Empty, attachment_path, reader, attachment.contentType, content_disposition);
                    attachment.storedFileUrl = MailStoragePathCombiner.GetStoredUrl(upload_url);
                }
            }
            catch (Exception e)
            {
                _log.Error("StoreAttachmentWithoutQuota(). filename: {0}, ctype: {1} Exception:\r\n{2}\r\n",
                           attachment.fileName,
                           attachment.contentType,
                           e.ToString());

                throw;
            }
        }
        public void StoreAttachmentCopy(int tenant, string user, MailAttachment attachment, string streamId)
        {
            try
            {
                if (attachment.streamId.Equals(streamId))
                {
                    return;
                }

                var s3Key = MailStoragePathCombiner.GerStoredFilePath(attachment);

                var dataClient = MailDataStore.GetDataStore(tenant);

                if (!dataClient.IsFile(s3Key))
                {
                    return;
                }

                attachment.fileNumber =
                    !string.IsNullOrEmpty(attachment.contentId) //Upload hack: embedded attachment have to be saved in 0 folder
                        ? 0
                        : attachment.fileNumber;

                var newS3Key = MailStoragePathCombiner.GetFileKey(user, streamId, attachment.fileNumber,
                                                                  attachment.storedName);

                var copyS3Url = dataClient.Copy(s3Key, string.Empty, newS3Key);

                attachment.storedFileUrl = MailStoragePathCombiner.GetStoredUrl(copyS3Url);

                attachment.streamId = streamId;

                _log.Debug("StoreAttachmentCopy() tenant='{0}', user_id='{1}', stream_id='{2}', new_s3_key='{3}', copy_s3_url='{4}', storedFileUrl='{5}',  filename='{6}'",
                           tenant, user, streamId, newS3Key, copyS3Url, attachment.storedFileUrl, attachment.fileName);
            }
            catch (Exception ex)
            {
                _log.Error("CopyAttachment(). filename='{0}', ctype='{1}' Exception:\r\n{2}\r\n",
                           attachment.fileName,
                           attachment.contentType,
                           ex.ToString());

                throw;
            }
        }
        private static MimePart CreateAttachment(MailAttachment attachment, bool load_attachments)
        {
            var ret_val = new MimePart();

            var s3_key    = MailStoragePathCombiner.GerStoredFilePath(attachment);
            var file_name = attachment.fileName ?? Path.GetFileName(s3_key);

            if (load_attachments)
            {
                var byte_array = attachment.data;

                if (byte_array == null || byte_array.Length == 0)
                {
                    using (var stream = StorageManager.GetDataStoreForAttachments(attachment.tenant).GetReadStream(s3_key))
                    {
                        byte_array = stream.GetCorrectBuffer();
                    }
                }

                ret_val = new MimePart(byte_array, file_name);

                if (attachment.contentId != null)
                {
                    ret_val.ContentId = attachment.contentId;
                }
            }
            else
            {
                var conent_type = Common.Web.MimeMapping.GetMimeMapping(s3_key);
                ret_val.ContentType = new ContentType {
                    Type = conent_type
                };
                ret_val.Filename = file_name;
                if (attachment.contentId != null)
                {
                    ret_val.ContentId = attachment.contentId;
                }
                ret_val.TextContent = "";
            }

            return(ret_val);
        }
        public static MimePart ToMimePart(this MailAttachment attachment, bool loadAttachments)
        {
            var retVal = new MimePart();

            var s3Key    = MailStoragePathCombiner.GerStoredFilePath(attachment);
            var fileName = attachment.fileName ?? Path.GetFileName(s3Key);

            if (loadAttachments)
            {
                var byteArray = attachment.data;

                if (byteArray == null || byteArray.Length == 0)
                {
                    using (var stream = StorageManager.GetDataStoreForAttachments(attachment.tenant).GetReadStream(s3Key))
                    {
                        byteArray = stream.ReadToEnd();
                    }
                }

                retVal = new MimePart(byteArray, fileName);

                if (!string.IsNullOrEmpty(attachment.contentId))
                {
                    retVal.ContentId = attachment.contentId;
                }
            }
            else
            {
                var conentType = MimeMapping.GetMimeMapping(s3Key);
                retVal.ContentType = new ContentType {
                    Type = conentType
                };
                retVal.Filename = fileName;
                if (attachment.contentId != null)
                {
                    retVal.ContentId = attachment.contentId;
                }
                retVal.TextContent = "";
            }

            return(retVal);
        }
        private List <MailAttachmentData> FixHtmlBodyWithEmbeddedAttachments(MailComposeBase compose)
        {
            var embededAttachmentsForSaving = new List <MailAttachmentData>();

            var embeddedLinks = compose.GetEmbeddedAttachmentLinks();

            if (!embeddedLinks.Any())
            {
                return(embededAttachmentsForSaving);
            }

            var fckStorage              = StorageManager.GetDataStoreForCkImages(compose.Mailbox.TenantId);
            var attachmentStorage       = StorageManager.GetDataStoreForAttachments(compose.Mailbox.TenantId);
            var currentMailFckeditorUrl = fckStorage.GetUri(StorageManager.CKEDITOR_IMAGES_DOMAIN, "").ToString();
            var currentUserStorageUrl   = MailStoragePathCombiner.GetUserMailsDirectory(compose.Mailbox.UserId);

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

            StorageManager storage = null;

            foreach (var embeddedLink in embeddedLinks)
            {
                try
                {
                    var isFckImage   = embeddedLink.StartsWith(currentMailFckeditorUrl);
                    var prefixLength = isFckImage
                        ? currentMailFckeditorUrl.Length
                        : embeddedLink.IndexOf(currentUserStorageUrl, StringComparison.Ordinal) +
                                       currentUserStorageUrl.Length + 1;
                    var fileLink = HttpUtility.UrlDecode(embeddedLink.Substring(prefixLength));
                    var fileName = Path.GetFileName(fileLink);
                    var attach   = new MailAttachmentData
                    {
                        fileName      = fileName,
                        storedName    = fileName,
                        contentId     = embeddedLink.GetMd5(),
                        storedFileUrl = fileLink,
                        streamId      = compose.StreamId,
                        user          = compose.Mailbox.UserId,
                        tenant        = compose.Mailbox.TenantId,
                        mailboxId     = compose.Mailbox.MailBoxId
                    };

                    var savedAttachment =
                        engine.AttachmentEngine.GetAttachment(
                            new ConcreteContentAttachmentExp(compose.Id, attach.contentId));

                    var savedAttachmentId = savedAttachment == null ? 0 : savedAttachment.fileId;

                    var attachmentWasSaved = savedAttachmentId != 0;
                    var currentImgStorage  = isFckImage ? fckStorage : attachmentStorage;
                    var domain             = isFckImage ? StorageManager.CKEDITOR_IMAGES_DOMAIN : compose.Mailbox.UserId;

                    if (compose.Id == 0 || !attachmentWasSaved)
                    {
                        attach.data = StorageManager.LoadDataStoreItemData(domain, fileLink, currentImgStorage);

                        if (storage == null)
                        {
                            storage = new StorageManager(compose.Mailbox.TenantId, compose.Mailbox.UserId);
                        }

                        storage.StoreAttachmentWithoutQuota(attach);

                        embededAttachmentsForSaving.Add(attach);
                    }

                    if (attachmentWasSaved)
                    {
                        attach = engine.AttachmentEngine.GetAttachment(
                            new ConcreteUserAttachmentExp(savedAttachmentId, compose.Mailbox.TenantId, compose.Mailbox.UserId));

                        var path = MailStoragePathCombiner.GerStoredFilePath(attach);
                        currentImgStorage    = attachmentStorage;
                        attach.storedFileUrl =
                            MailStoragePathCombiner.GetStoredUrl(currentImgStorage.GetUri(path));
                    }

                    compose.HtmlBody = compose.HtmlBody.Replace(embeddedLink, attach.storedFileUrl);
                }
                catch (Exception ex)
                {
                    Log.ErrorFormat("ChangeEmbededAttachmentLinksForStoring() failed with exception: {0}", ex.ToString());
                }
            }

            return(embededAttachmentsForSaving);
        }
        public static List <MailAttachment> ChangeEmbededAttachmentLinksForStoring(this MailDraft draft,
                                                                                   MailBoxManager manager,
                                                                                   ILogger log = null)
        {
            if (log == null)
            {
                log = new NullLogger();
            }

            //Todo: This method can be separated in two
            var fckStorage        = StorageManager.GetDataStoreForCkImages(draft.Mailbox.TenantId);
            var attachmentStorage = StorageManager.GetDataStoreForAttachments(draft.Mailbox.TenantId);

            var currentMailFckeditorUrl        = fckStorage.GetUri(StorageManager.CKEDITOR_IMAGES_DOMAIN, "").ToString();
            var currentMailAttachmentFolderUrl = MailStoragePathCombiner.GetMessageDirectory(draft.Mailbox.UserId, draft.StreamId);
            var currentUserStorageUrl          = MailStoragePathCombiner.GetUserMailsDirectory(draft.Mailbox.UserId);

            log.Info("ChangeEmbededAttachmentLinksForStoring() Fckeditor storage base url: {0}", currentMailFckeditorUrl);
            log.Info("ChangeEmbededAttachmentLinksForStoring() Current mail attachment folder storage base url: {0}",
                     currentMailAttachmentFolderUrl);
            log.Info("ChangeEmbededAttachmentLinksForStoring() Current user folder storage base url: {0}",
                     currentUserStorageUrl);

            var xpathQuery = StorageManager.GetXpathQueryForAttachmentsToResaving(currentMailFckeditorUrl,
                                                                                  currentMailAttachmentFolderUrl,
                                                                                  currentUserStorageUrl);

            log.Info(
                "ChangeEmbededAttachmentLinksForStoring() Xpath Query selector for embedded attachment links: {0}",
                xpathQuery);
            var attachmentsForSaving = new List <MailAttachment>();

            var doc = new HtmlDocument();

            doc.LoadHtml(draft.HtmlBody);

            var linkNodes = doc.DocumentNode.SelectNodes(xpathQuery);

            if (linkNodes != null)
            {
                foreach (var linkNode in linkNodes)
                {
                    try
                    {
                        var link = linkNode.Attributes["src"].Value;

                        log.Info("ChangeEmbededAttachmentLinksForStoring() Original selected file_link: {0}", link);

                        var isFckImage   = link.StartsWith(currentMailFckeditorUrl);
                        var prefixLength = isFckImage
                                               ? currentMailFckeditorUrl.Length
                                               : link.IndexOf(currentUserStorageUrl, StringComparison.Ordinal) +
                                           currentUserStorageUrl.Length + 1;
                        var fileLink = HttpUtility.UrlDecode(link.Substring(prefixLength));

                        var fileName = Path.GetFileName(fileLink);
                        var attach   = CreateEmbbededAttachment(fileName, link, fileLink, draft.Mailbox.UserId, draft.Mailbox.TenantId,
                                                                draft.Mailbox.MailBoxId, draft.StreamId);

                        var savedAttachmentId  = manager.GetAttachmentId(draft.Id, attach.contentId);
                        var attachmentWasSaved = savedAttachmentId != 0;
                        var currentImgStorage  = isFckImage ? fckStorage : attachmentStorage;
                        var domain             = isFckImage ? StorageManager.CKEDITOR_IMAGES_DOMAIN : draft.Mailbox.UserId;

                        if (draft.Id == 0 || !attachmentWasSaved)
                        {
                            attach.data = StorageManager.LoadDataStoreItemData(domain, fileLink, currentImgStorage);
                            manager.StoreAttachmentWithoutQuota(draft.Mailbox.TenantId, draft.Mailbox.UserId, attach);
                            attachmentsForSaving.Add(attach);
                        }

                        if (attachmentWasSaved)
                        {
                            attach = manager.GetMessageAttachment(savedAttachmentId, draft.Mailbox.TenantId, draft.Mailbox.UserId);
                            var path = MailStoragePathCombiner.GerStoredFilePath(attach);
                            currentImgStorage    = attachmentStorage;
                            attach.storedFileUrl =
                                MailStoragePathCombiner.GetStoredUrl(currentImgStorage.GetUri(path));
                        }

                        log.Info("ChangeEmbededAttachmentLinksForStoring() Restored new file_link: {0}",
                                 attach.storedFileUrl);
                        linkNode.SetAttributeValue("src", attach.storedFileUrl);
                    }
                    catch (Exception ex)
                    {
                        log.Error("ChangeEmbededAttachmentLinksForStoring() failed with exception: {0}", ex.ToString());
                    }
                }

                draft.HtmlBody = doc.DocumentNode.OuterHtml;
            }

            return(attachmentsForSaving);
        }
        public List <MailAttachment> ChangeEmbededAttachmentLinksForStoring(int tenant, string username, int mail_id, MailBoxManager manager)
        {
            //Todo: This method can be separated in two
            var fck_storage        = StorageManager.GetDataStoreForCkImages(tenant);
            var attachment_storage = StorageManager.GetDataStoreForAttachments(tenant);

            var current_mail_fckeditor_url         = fck_storage.GetUri(StorageManager.CkeditorImagesDomain, "").ToString();
            var current_mail_attachment_folder_url = GetThisMailFolder(username);
            var current_user_storage_url           = GetUserFolder(username);

            _logger.Info("ChangeEmbededAttachmentLinksForStoring() Fckeditor storage base url: {0}", current_mail_fckeditor_url);
            _logger.Info("ChangeEmbededAttachmentLinksForStoring() Current mail attachment folder storage base url: {0}", current_mail_attachment_folder_url);
            _logger.Info("ChangeEmbededAttachmentLinksForStoring() Current user folder storage base url: {0}", current_user_storage_url);

            var xpath_query = StorageManager.GetXpathQueryForAttachmentsToResaving(current_mail_fckeditor_url, current_mail_attachment_folder_url, current_user_storage_url);

            _logger.Info("ChangeEmbededAttachmentLinksForStoring() Xpath Query selector for embedded attachment links: {0}", xpath_query);
            var attachments_for_saving = new List <MailAttachment>();

            var doc = new HtmlDocument();

            doc.LoadHtml(HtmlBody);

            var link_nodes = doc.DocumentNode.SelectNodes(xpath_query);

            if (link_nodes != null)
            {
                foreach (var link_node in link_nodes)
                {
                    try
                    {
                        var link = link_node.Attributes["src"].Value;

                        _logger.Info("ChangeEmbededAttachmentLinksForStoring() Original selected file_link: {0}", link);

                        var is_fck_image  = link.StartsWith(current_mail_fckeditor_url);
                        var prefix_length = is_fck_image
                                                ? current_mail_fckeditor_url.Length
                                                : link.IndexOf(current_user_storage_url, StringComparison.Ordinal) +
                                            current_user_storage_url.Length + 1;
                        var file_link = HttpUtility.UrlDecode(link.Substring(prefix_length));

                        var file_name = Path.GetFileName(file_link);
                        var attach    = CreateEmbbededAttachment(file_name, link, file_link, username, tenant);

                        var saved_attachment_id  = manager.GetAttachmentId(mail_id, attach.contentId);
                        var attachment_was_saved = saved_attachment_id != 0;
                        var current_img_storage  = is_fck_image ? fck_storage : attachment_storage;
                        var domain = is_fck_image ? StorageManager.CkeditorImagesDomain : username;

                        if (mail_id == 0 || !attachment_was_saved)
                        {
                            attach.data = StorageManager.LoadDataStoreItemData(domain, file_link, current_img_storage);
                            //TODO: Add quota if needed
                            manager.StoreAttachmentWithoutQuota(tenant, username, attach);
                            attachments_for_saving.Add(attach);
                        }

                        if (attachment_was_saved)
                        {
                            attach = manager.GetMessageAttachment(saved_attachment_id, tenant, username);
                            var path = MailStoragePathCombiner.GerStoredFilePath(attach);
                            current_img_storage  = attachment_storage;
                            attach.storedFileUrl = current_img_storage.GetUri("", path).ToString();
                        }

                        _logger.Info("ChangeEmbededAttachmentLinksForStoring() Restored new file_link: {0}",
                                     attach.storedFileUrl);
                        link_node.SetAttributeValue("src", attach.storedFileUrl);
                    }
                    catch (Exception ex)
                    {
                        _logger.Error("ChangeEmbededAttachmentLinksForStoring() failed with exception: {0}", ex.ToString());
                    }
                }

                HtmlBody = doc.DocumentNode.OuterHtml;
            }

            return(attachments_for_saving);
        }
        public void StoreAttachments(int tenant, string user, List <MailAttachment> attachments, string stream_id, int id_mailbox)
        {
            if (!attachments.Any() || string.IsNullOrEmpty(stream_id))
            {
                return;
            }

            var storage = MailDataStore.GetDataStore(tenant);

            if (storage == null)
            {
                throw new NullReferenceException("GetDataStore has returned null reference.");
            }

            var quota_add_size = attachments.Sum(a => a.data.LongLength);

            QuotaUsedAdd(tenant, quota_add_size);

            try
            {
                foreach (var attachment in attachments)
                {
                    bool is_attachment_name_has_bad_name = string.IsNullOrEmpty(attachment.fileName) ||
                                                           attachment.fileName.IndexOfAny(Path.GetInvalidPathChars()) != -1 ||
                                                           attachment.fileName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1;
                    if (is_attachment_name_has_bad_name)
                    {
                        attachment.fileName = string.Format("attacment{0}{1}", attachment.fileNumber,
                                                            MimeMapping.GetExtention(attachment.contentType));
                    }

                    attachment.streamId = stream_id;
                    attachment.tenant   = tenant;
                    attachment.user     = user;
                    StoreAttachmentWithoutQuota(tenant, user, attachment, storage);

                    //This is dirty hack needed for mailbox updating on attachment processing. If we doesn't update mailbox checktime, it will be reset.
                    if (id_mailbox > 0)
                    {
                        LockMailbox(id_mailbox, DateTime.UtcNow.Ticks);
                    }
                }
            }
            catch
            {
                var stored_attachments_keys = attachments
                                              .Where(a => !string.IsNullOrEmpty(a.storedFileUrl))
                                              .Select(a => MailStoragePathCombiner.GerStoredFilePath(a))
                                              .ToList();

                //Todo: Rewrite this ugly code
                bool is_quota_cleaned = false;
                if (stored_attachments_keys.Any())
                {
                    var s3_storage = storage as S3Storage;
                    if (s3_storage != null)
                    {
                        // ToDo: Delete with quota argument needs to be moved to IDataStore!
                        stored_attachments_keys
                        .ForEach(key => s3_storage.Delete(string.Empty, key, false));
                    }
                    else
                    {
                        is_quota_cleaned = true;
                        stored_attachments_keys.ForEach(key => storage.Delete(string.Empty, key));
                    }
                }

                if (!is_quota_cleaned)
                {
                    QuotaUsedDelete(tenant, quota_add_size);
                }

                _log.Debug(String.Format("Problems with attachment saving in mailboxId={0}. All message attachments was deleted.", id_mailbox));
                throw;
            }
        }
示例#9
0
        private static MimeEntity ToMimeMessageBody(MailDraft draft)
        {
            var linkedResources = new AttachmentCollection(true);
            var attachments     = new AttachmentCollection();

            string textBody;

            MailUtil.TryExtractTextFromHtml(draft.HtmlBody, out textBody);

            MultipartAlternative multipartAlternative = null;
            MimeEntity           body = null;

            if (!string.IsNullOrEmpty(textBody))
            {
                var textPart = new TextPart("plain")
                {
                    Text = textBody,
                    ContentTransferEncoding = ContentEncoding.QuotedPrintable
                };

                if (!string.IsNullOrEmpty(draft.HtmlBody))
                {
                    multipartAlternative = new MultipartAlternative {
                        textPart
                    };
                    body = multipartAlternative;
                }
                else
                {
                    body = textPart;
                }
            }

            if (!string.IsNullOrEmpty(draft.HtmlBody))
            {
                var htmlPart = new TextPart("html")
                {
                    Text = draft.HtmlBody,
                    ContentTransferEncoding = ContentEncoding.QuotedPrintable
                };

                MimeEntity tempPart;

                if (draft.AttachmentsEmbedded.Any())
                {
                    var multipartRelated = new MultipartRelated
                    {
                        Root = htmlPart
                    };

                    foreach (var emb in draft.AttachmentsEmbedded)
                    {
                        MimeEntity linkedResource;

                        if (!emb.data.Any())
                        {
                            var s3Key = MailStoragePathCombiner.GerStoredFilePath(emb);

                            var contentType =
                                ContentType.Parse(string.IsNullOrEmpty(emb.contentType)
                                    ? MimeMapping.GetMimeMapping(emb.fileName)
                                    : emb.contentType);

                            using (var stream = StorageManager
                                                .GetDataStoreForAttachments(emb.tenant)
                                                .GetReadStream(s3Key))
                            {
                                linkedResource = linkedResources.Add(emb.fileName, stream, contentType);
                            }
                        }
                        else
                        {
                            linkedResource = linkedResources.Add(emb.fileName, emb.data);
                        }

                        linkedResource.ContentId = emb.contentId;

                        multipartRelated.Add(linkedResource);
                    }

                    tempPart = multipartRelated;
                }
                else
                {
                    tempPart = htmlPart;
                }

                if (multipartAlternative != null)
                {
                    multipartAlternative.Add(tempPart);
                }
                else
                {
                    body = tempPart;
                }
            }

            if (!string.IsNullOrEmpty(draft.CalendarIcs))
            {
                var calendarPart = new TextPart("calendar")
                {
                    Text = draft.CalendarIcs,
                    ContentTransferEncoding = ContentEncoding.QuotedPrintable
                };

                calendarPart.ContentType.Parameters.Add("method", draft.CalendarMethod);

                if (multipartAlternative != null)
                {
                    multipartAlternative.Add(calendarPart);
                }
                else
                {
                    body = calendarPart;
                }
            }


            if (draft.Attachments.Any() || !string.IsNullOrEmpty(draft.CalendarIcs))
            {
                var multipart = new Multipart("mixed");

                if (body != null)
                {
                    multipart.Add(body);
                }

                foreach (var att in draft.Attachments)
                {
                    MimeEntity attachmentResource;

                    if (!att.data.Any())
                    {
                        var s3Key = MailStoragePathCombiner.GerStoredFilePath(att);

                        using (var stream = StorageManager
                                            .GetDataStoreForAttachments(att.tenant)
                                            .GetReadStream(s3Key))
                        {
                            attachmentResource = attachments.Add(att.fileName, stream);
                        }
                    }
                    else
                    {
                        attachmentResource = attachments.Add(att.fileName, att.data);
                    }

                    multipart.Add(attachmentResource);
                }

                if (!string.IsNullOrEmpty(draft.CalendarIcs))
                {
                    var filename = "calendar.ics";
                    switch (draft.CalendarMethod)
                    {
                    case "REQUEST":
                        filename = "invite.ics";
                        break;

                    case "REPLY":
                        filename = "reply.ics";
                        break;

                    case "CANCEL":
                        filename = "cancel.ics";
                        break;
                    }

                    var contentType = new ContentType("application", "ics");
                    contentType.Parameters.Add("method", draft.CalendarMethod);
                    contentType.Parameters.Add("name", filename);

                    var data = Encoding.UTF8.GetBytes(draft.CalendarIcs);

                    var calendarResource = attachments.Add(filename, data, contentType);
                    multipart.Add(calendarResource);
                }

                body = multipart;
            }

            if (body != null)
            {
                return(body);
            }

            return(new TextPart("plain")
            {
                Text = string.Empty
            });
        }