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; } }
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 }); }