public void Show(Message message) { this.message = message; RockScroll.Value = 0; timer.IsEnabled = true; }
public static void Delete(Message source) { var oldMessage = source.DuckCopy<Message>(); #region Do action Action doAction = delegate { source.MessageFolder = Folders.Trash; source.TargetMessageState = EntityStates.Deleted; AsyncUpdateQueue.Enqueue(source); }; #endregion #region Undo action Action undoAction = delegate { source.MessageFolder = oldMessage.MessageFolder; source.TargetMessageState = oldMessage.TargetMessageState; AsyncUpdateQueue.Enqueue(source); }; #endregion ClientState.Current.UndoManager.Execute(new HistoryAction(doAction, undoAction)); }
public UpdateMessageStateTask(ChannelConfiguration config, IReadStateChannel channel, List<ChannelFolder> availableFolders, Message message) { this.config = config; this.channel = channel; this.availableFolders = availableFolders; this.message = message; }
/// <summary> /// Matches the message to a conversation. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> internal Conversation MatchToConversation(Message message) { Logger.Debug("Trying to match conversation for message {0}", LogSource.MessageMatcher, message); Conversation conversation; if (MatchOnConversationId(message, out conversation) == ExecutionResult.Break) { UpdateConversation(conversation); return conversation; } if (MatchOnInReplyTo(message, out conversation, 1) == ExecutionResult.Break) { UpdateConversation(conversation); return conversation; } if (MatchOnSubject(message, out conversation) == ExecutionResult.Break) { UpdateConversation(conversation); return conversation; } throw new ApplicationException("Unable to match message to conversation!"); }
public static void Forward(Message source) { ClientState.Current.ViewController.MoveTo( PluginsManager.Current.GetPlugin<ConversationsPlugin>().NewItemView, new NewMessageDataHelper { SourceMessageId = source.MessageId, Context = "Fw: " + source.Context, Body = MessageBodyGenerator.CreateBodyTextForForward(source, true), AttachedFiles = source.Documents.Select(d => new AttachmentDataHelper(d)).ToList() }); }
public ClientMessageAccess(Message message) { this.message = message; if (message.BodyHtmlStreamName.HasValue) using (var s = ClientState.Current.Storage.Read("m", message.BodyHtmlStreamName.ToString())) bodyHtml = s.ReadString(); if (message.BodyTextStreamName.HasValue) using (var s = ClientState.Current.Storage.Read("m", message.BodyTextStreamName.ToString())) bodyText = s.ReadString(); }
public static void Reply(Message source) { ClientState.Current.ViewController.MoveTo( PluginsManager.Current.GetPlugin<ConversationsPlugin>().NewItemView, new NewMessageDataHelper { SourceMessageId = source.MessageId, SelectedChannelId = source.SourceChannelId, Context = "Re: " + source.Context, To = source.From.ToList(), Body = MessageBodyGenerator.CreateBodyTextForReply(source, true) }); }
public void Show(Message message) { // This is for our fake message if (message.MessageId < 0) { return; } this.message = message; QuickReplyAll.Text = String.Empty; // if document hasn't loaded (the first time), loadcomplete will take care of show for us if (initialized) { BuildAndShowMessage(); } // When message is shown due to system selection, do not track the read action if (!ThreadFlag.IsSet) { message.TrackAction(ActionType.Read); } if (flipper != null) { flipper.Dispose(); } // Mark message read if after setting is enabled var markReadAFter = SettingsManager.ClientSettings.AppConfiguration.MarkReadWhenViewingAfter; if (markReadAFter.HasValue) { flipper = new Flipper(TimeSpan.FromSeconds(markReadAFter.Value), delegate { if (!message.IsRead) { message.MarkRead(); } }); flipper.Delay(); } else if (SettingsManager.ClientSettings.AppConfiguration.MarkReadWhenViewing) { message.MarkRead(); } OnPropertyChanged("Message"); }
public static void MessageStored(Message message) { var mailbox = VirtualMailBox.Current; // Match thread MessageMatcher.Match(message); mailbox.Messages.Add(message); ViewFilter.Current.UpdateCurrentViewAsync(); // Add to search index ClientState.Current.Search.Store(message); }
static string GetMessageHtmlView(Message source) { // Hack: load core assembly directly (should be in memory anyway) Assembly asm = Assembly.LoadFrom("Inbox2.Core.Streams.dll"); //Load HTML File: Stream htmlFile = asm.GetManifestResourceStream("Inbox2.Core.Streams.ThreadView.html"); string path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; var access = new ClientMessageAccess(source); var sanitized = HtmlSanitizer.Sanitize(access.GetBestBodyMatch(TextConversion.ToHtml)); return htmlFile.ReadString() .Replace("#rootfolder#", "file://" + path.Replace("\\", "//") + "/") .Replace("#Title#", HttpUtility.HtmlEncode(source.Context)) .Replace("#HtmlSource#", sanitized); }
protected virtual bool CheckReadStates(Message message, ChannelMessageHeader header) { // Channel doesn't support readstates, no point in checking if (!config.Charasteristics.SupportsReadStates) return false; // Message has been marked for channel update, ignore for now if (message.TargetMessageState.HasValue) return false; // Check readstate of message if (header.IsRead) { if (!message.IsRead) message.MarkRead(false); } else { if (message.IsRead) message.MarkUnread(false); } if (header.IsStarred) { // Star if (!message.IsStarred) message.SetStarred(false); } else { // Unstar if (message.IsStarred) message.SetUnstarred(false); } return true; }
void SaveDocuments(Message message, bool isDraft) { if (isDraft) { // Delete old attachments from message, will be re-added again below SourceMessage.Documents.ToList() .ForEach(d => d.DeleteFrom(SourceMessage)); } // Add attachments to message foreach (var file in attachedFiles) { var document = new Document { Message = message, Filename = file.Filename, ContentType = ContentType.Attachment, SourceChannelId = message.SourceChannelId, DateCreated = DateTime.Now, DateSent = DateTime.Now, DocumentFolder = Folders.SentItems }; document.StreamName = Guid.NewGuid().GetHash(12) + "_" + Path.GetExtension(document.Filename); document.ContentStream = new FileStream(file.Streamname, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); EventBroker.Publish(AppEvents.DocumentReceived, document); // Might needs this when deleting an attachment from a draft message file.DocumentId = document.DocumentId; } }
public SendMessageCommand(Message message) { this.message = message; this.mailbox = VirtualMailBox.Current; }
/// <summary> /// Creates a new conversation. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> Conversation CreateNewConversation(Message message) { Conversation conversation = DispatcherActivator<Conversation>.Create(); string conversationId = message.ConversationIdentifier; if (String.IsNullOrEmpty(message.ConversationIdentifier)) { // Create new conversation id conversationId = Guid.NewGuid().ToConversationId(); } conversation.ConversationIdentifier = conversationId; conversation.Context = message.Context.ToClearSubject(); ClientState.Current.DataService.Save(conversation); Logger.Debug("Conversation {0} was created successfully", LogSource.MessageMatcher, conversation); Logger.Debug("Message {0} now has ConversationIdentifier {1}", LogSource.MessageMatcher, message, conversationId); UpdateMessage(message, conversation); Debug.Assert(!String.IsNullOrEmpty(message.ConversationIdentifier), "Message can not have an empty ConversationIdentifier!"); mailbox.Conversations.Add(conversation); return conversation; }
/// <summary> /// Matches the specified message. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> public static Conversation Match(Message message) { return new MessageMatcher().MatchToConversation(message); }
public ProfileMatcher(Message message) { this.message = message; this.mailbox = VirtualMailBox.Current; }
public ClientMessageAccess(Message message, string bodyText, string bodyHtml) { this.message = message; this.bodyText = bodyText; this.bodyHtml = bodyHtml; }
public void Show(Message message) { // This is for our fake message if (message.MessageId < 0) return; this.message = message; QuickReplyAll.Text = String.Empty; // if document hasn't loaded (the first time), loadcomplete will take care of show for us if (initialized) BuildAndShowMessage(); // When message is shown due to system selection, do not track the read action if (!ThreadFlag.IsSet) message.TrackAction(ActionType.Read); if (flipper != null) flipper.Dispose(); // Mark message read if after setting is enabled var markReadAFter = SettingsManager.ClientSettings.AppConfiguration.MarkReadWhenViewingAfter; if (markReadAFter.HasValue) { flipper = new Flipper(TimeSpan.FromSeconds(markReadAFter.Value), delegate { if (!message.IsRead) message.MarkRead(); }); flipper.Delay(); } else if (SettingsManager.ClientSettings.AppConfiguration.MarkReadWhenViewing) message.MarkRead(); OnPropertyChanged("Message"); }
public ProfileMatcher(Message message) { this.message = message; this.dataService = ClientState.Current.DataService; }
void UpdateMessage(Message message, Conversation conversation) { message.ConversationIdentifier = conversation.ConversationIdentifier; ClientState.Current.DataService.Update(message); Thread.CurrentThread.ExecuteOnUIThread(() => conversation.Add(message)); }
void Send_Executed(object sender, ExecutedRoutedEventArgs e) { ClientStats.LogEvent("Quick reply all send"); if (String.IsNullOrEmpty(QuickReplyAll.Text.Trim())) return; var newMessage = new Message(); #region Create message var channel = message.SourceChannelId == 0 ? ChannelsManager.GetDefaultChannel() : ChannelsManager.GetChannelObject(Message.SourceChannelId); var recipients = new SourceAddressCollection(); var sourceAddress = channel.InputChannel.GetSourceAddress(); recipients.Add(Message.From); recipients.AddRange(Message.To); // Remove our own address from recipient list if (recipients.Contains(sourceAddress)) recipients.Remove(sourceAddress); newMessage.InReplyTo = Message.MessageIdentifier; newMessage.ConversationIdentifier = Message.ConversationIdentifier; newMessage.Context = "Re: " + Message.Context; newMessage.From = channel.InputChannel.GetSourceAddress(); newMessage.TargetChannelId = channel.Configuration.ChannelId; newMessage.To.AddRange(recipients); newMessage.CC.AddRange(Message.CC); var access = new ClientMessageAccess(newMessage, null, MessageBodyGenerator.CreateBodyTextForReply(Message, QuickReplyAll.Text.Nl2Br())); newMessage.BodyHtmlStreamName = access.WriteBodyHtml(); newMessage.BodyPreview = access.GetBodyPreview(); newMessage.IsRead = true; newMessage.DateSent = DateTime.Now; newMessage.MessageFolder = Folders.SentItems; newMessage.DateSent = DateTime.Now; newMessage.DateCreated = DateTime.Now; #endregion #region Send message ClientState.Current.DataService.Save(newMessage); // Add message to mailbox EventBroker.Publish(AppEvents.MessageStored, newMessage); // Save command CommandQueue.Enqueue(AppCommands.SendMessage, newMessage); if (!NetworkInterface.GetIsNetworkAvailable()) { ClientState.Current.ShowMessage( new AppMessage(Strings.MessageWillBeSentLater) { EntityId = newMessage.MessageId.Value, EntityType = EntityType.Message }, MessageType.Success); } QuickReplyAll.Text = String.Empty; message.TrackAction(ActionType.ReplyForward); #endregion }
public static void MessageStored(Message message) { new ProfileMatcher(message).Execute(); }
bool FilterMessage(Message message) { if (message == null) return false; // For our fake message work-around if (message.MessageId == -1) return true; // This is a expunged message if (message.ConversationIdentifier == "-1") return false; // Break out if source/target channel is not visible if (!message.IsChannelVisible) return false; if (Filter.CurrentView == ActivityView.MyInbox && message.Conversation.Messages.Count(m => m.MessageFolder != Folders.SentItems) == 0) return false; if (Filter.CurrentView == ActivityView.MyInbox && (message.MessageFolder == Folders.Trash || message.MessageFolder == Folders.Archive || message.MessageFolder == Folders.Drafts || message.MessageFolder == Folders.Spam)) return false; if (Filter.CurrentView == ActivityView.Archive && message.MessageFolder != Folders.Archive) return false; if (Filter.CurrentView == ActivityView.Received && message.MessageFolder != Folders.Inbox) return false; if (Filter.CurrentView == ActivityView.Sent && message.MessageFolder != Folders.SentItems) return false; if (Filter.CurrentView == ActivityView.Drafts && message.MessageFolder != Folders.Drafts) return false; if (Filter.CurrentView == ActivityView.Trash && message.MessageFolder != Folders.Trash) return false; if (Filter.CurrentView == ActivityView.Starred && message.IsStarred == false) return false; if (Filter.CurrentView == ActivityView.Unread && (message.IsRead || message.MessageFolder == Folders.Trash || message.MessageFolder == Folders.Spam)) return false; if (Filter.CurrentView == ActivityView.Todo && message.IsTodo == false) return false; if (Filter.CurrentView == ActivityView.WaitingFor && message.IsWaitingFor == false) return false; if (Filter.CurrentView == ActivityView.Someday && message.IsSomeday == false) return false; if (Filter.CurrentView == ActivityView.Label && (message.IsTrash || message.HasLabel(Filter.Label) == false)) return false; return true; }
public void DeleteFrom(Message message) { var mailbox = VirtualMailBox.Current; // Get all versions associated with the message we want to detach // this document from. var versionsForMessage = Versions .Where(v => v.MessageId == message.MessageId.Value) .ToList(); // Remove all versions for this message foreach (var version in versionsForMessage) { Versions.Remove(version); ClientState.Current.DataService.Delete(version); } if (Versions.Count == 0) { // No versions left, delete document and stream from disk ClientState.Current.Storage.Delete(".", StreamName); // todo remove stream from search-index using (mailbox.Documents.WriterLock) mailbox.Documents.Remove(this); ClientState.Current.DataService.Delete(this); } message.Documents.Remove(this); }
public static void ReplyAll(Message source, string text) { var recipients = new SourceAddressCollection(); recipients.AddRange(source.To); recipients.AddRange(source.CC); long channelid; // Remove receivers own address from list if (source.SourceChannelId != 0) { var channel = ChannelsManager.GetChannelObject(source.SourceChannelId); var sourceAddress = channel.InputChannel.GetSourceAddress(); if (recipients.Contains(sourceAddress)) recipients.Remove(sourceAddress); channelid = source.SourceChannelId; } else { var channel = ChannelsManager.GetChannelObject(source.TargetChannelId); var sourceAddress = channel.InputChannel.GetSourceAddress(); if (recipients.Contains(sourceAddress)) recipients.Remove(sourceAddress); channelid = source.TargetChannelId; } ClientState.Current.ViewController.MoveTo( PluginsManager.Current.GetPlugin<ConversationsPlugin>().NewItemView, new NewMessageDataHelper { SourceMessageId = source.MessageId, SelectedChannelId = channelid, Context = "Re: " + source.Context, To = source.From.ToList(), Cc = recipients, Body = MessageBodyGenerator.CreateBodyTextForReply(source, text), SuppressSignature = !String.IsNullOrEmpty(text) }); }
public static void ReplyAll(Message source) { ReplyAll(source, String.Empty); }
protected override void ExecuteCore() { try { Logger.Debug("Retreiving message {0} from {1}", LogSource.Receive, header, config.DisplayName); foreach (var channelMessage in channel.GetMessage(header)) { var message = new Message { MessageNumber = header.MessageNumber, MessageIdentifier = channelMessage.MessageIdentifier, From = channelMessage.From, ReturnTo = channelMessage.ReturnTo, To = channelMessage.To, CC = channelMessage.CC, BCC = channelMessage.BCC, InReplyTo = channelMessage.InReplyTo, Size = header.Size, Context = channelMessage.Context, ConversationIdentifier = channelMessage.ConversationId, SourceFolder = channelMessage.SourceFolder, Metadata = channelMessage.Metadata, IsRead = channelMessage.IsRead, IsStarred = channelMessage.IsStarred, DateReceived = channelMessage.DateReceived, DateSent = channelMessage.DateSent }; message.Context = message.Context != null ? message.Context.Trim() : String.Empty; string bodyText = channelMessage.BodyText.ReadString(); string bodyHtml = channelMessage.BodyHtml.ReadString(); var access = new ClientMessageAccess(message, bodyText, bodyHtml); if (folder.ToStorageFolder() == Folders.SentItems) { // For sent items we sent the TargetChannelId message.SourceChannelId = 0; message.TargetChannelId = config.ChannelId; } else { // For all other items we sent the SourceChannelId message.SourceChannelId = config.ChannelId; } // Create BodyPreview field from reader message.BodyPreview = access.GetBodyPreview(); message.BodyHtmlStreamName = access.WriteBodyHtml(); message.BodyTextStreamName = access.WriteBodyText(); message.MessageFolder = folder.ToStorageFolder(); message.Metadata = header.Metadata; // Fix for messages which have a timestamp in the future if (message.DateReceived > DateTime.Now) message.DateReceived = DateTime.Now; // Set IsNew state for message if (!message.IsRead) message.IsNew = true; // Save message ClientState.Current.DataService.Save(message); // Message received, process attachments foreach (var attachment in channelMessage.Attachments) { var document = new Document { Filename = attachment.Filename, TargetChannelId = attachment.TargetChannelId, DocumentFolder = folder.ToStorageFolder(), ContentType = attachment.ContentType, ContentId = attachment.ContentId, ContentStream = attachment.ContentStream, SourceChannelId = config.ChannelId, DateReceived = message.DateReceived, DateSent = message.DateSent, Message = message }; EventBroker.Publish(AppEvents.DocumentReceived, document); if (attachment.ContentStream != null) { attachment.ContentStream.Dispose(); attachment.ContentStream = null; } } if (channelMessage.BodyText != null) channelMessage.BodyText.Dispose(); if (channelMessage.BodyHtml != null) channelMessage.BodyHtml.Dispose(); EventBroker.Publish(AppEvents.MessageStored, message); } } catch (Exception ex) { Logger.Error("An error occured when trying to download header {0}. Exception = {1}", LogSource.BackgroundTask, header, ex); throw; } }
void Send_Executed(object sender, ExecutedRoutedEventArgs e) { ClientStats.LogEvent("Quick reply all send"); if (String.IsNullOrEmpty(QuickReplyAll.Text.Trim())) { return; } var newMessage = new Message(); #region Create message var channel = message.SourceChannelId == 0 ? ChannelsManager.GetDefaultChannel() : ChannelsManager.GetChannelObject(Message.SourceChannelId); var recipients = new SourceAddressCollection(); var sourceAddress = channel.InputChannel.GetSourceAddress(); recipients.Add(Message.From); recipients.AddRange(Message.To); // Remove our own address from recipient list if (recipients.Contains(sourceAddress)) { recipients.Remove(sourceAddress); } newMessage.InReplyTo = Message.MessageIdentifier; newMessage.ConversationIdentifier = Message.ConversationIdentifier; newMessage.Context = "Re: " + Message.Context; newMessage.From = channel.InputChannel.GetSourceAddress(); newMessage.TargetChannelId = channel.Configuration.ChannelId; newMessage.To.AddRange(recipients); newMessage.CC.AddRange(Message.CC); var access = new ClientMessageAccess(newMessage, null, MessageBodyGenerator.CreateBodyTextForReply(Message, QuickReplyAll.Text.Nl2Br())); newMessage.BodyHtmlStreamName = access.WriteBodyHtml(); newMessage.BodyPreview = access.GetBodyPreview(); newMessage.IsRead = true; newMessage.DateSent = DateTime.Now; newMessage.MessageFolder = Folders.SentItems; newMessage.DateSent = DateTime.Now; newMessage.DateCreated = DateTime.Now; #endregion #region Send message ClientState.Current.DataService.Save(newMessage); // Add message to mailbox EventBroker.Publish(AppEvents.MessageStored, newMessage); // Save command CommandQueue.Enqueue(AppCommands.SendMessage, newMessage); if (!NetworkInterface.GetIsNetworkAvailable()) { ClientState.Current.ShowMessage( new AppMessage(Strings.MessageWillBeSentLater) { EntityId = newMessage.MessageId.Value, EntityType = EntityType.Message }, MessageType.Success); } QuickReplyAll.Text = String.Empty; message.TrackAction(ActionType.ReplyForward); #endregion }
bool IsMessageVisible(Message message) { if (FilterMessage(message)) { if (Filter.IsActivityViewVisible) { if (SettingsManager.ClientSettings.AppConfiguration.RollUpConversations) { // Default behavior for my inbox if (Filter.CurrentView == ActivityView.MyInbox || Filter.CurrentView == ActivityView.Archive) return message.IsLast; } } else { if (Filter.CurrentView == ActivityView.MyInbox || Filter.CurrentView == ActivityView.Archive) return message.IsLast; } return true; } return false; }
public MessageContentMapper(Message message) { this.message = message; }
public MessageBuilder(Message source) { this.source = source; }
/// <summary> /// Matches the conversation on the the subject field. /// </summary> /// <param name="message">The message.</param> /// <param name="conversation">The conversation.</param> /// <returns></returns> ExecutionResult MatchOnSubject(Message message, out Conversation conversation) { if (message.MessageFolder == Folders.SentItems) { Logger.Debug("MatchOnSubject: Message {0} is a sent item. Creating new conversation because it is not a reply but a new message", LogSource.MessageMatcher, message); conversation = CreateNewConversation(message); return ExecutionResult.Break; } if (message.MessageFolder == Folders.Drafts) { Logger.Debug("MatchOnSubject: Message {0} is a concept message. Creating new conversation", LogSource.MessageMatcher, message); conversation = CreateNewConversation(message); return ExecutionResult.Break; } if (String.IsNullOrEmpty(message.Context) || String.IsNullOrEmpty(message.Context.ToClearSubject()) || message.Context.Trim().Length == 0) { Logger.Debug("MatchOnSubject: Message {0} has an empty context. Creating new conversation", LogSource.MessageMatcher, message); conversation = CreateNewConversation(message); return ExecutionResult.Break; } Logger.Debug("MatchOnSubject: trying to find conversation for Message {0} with Context {1}", LogSource.MessageMatcher, message, message.Context.ToClearSubject()); string context = message.Context.ToClearSubject(); // Determine if the recipients in the message match with the current recipients List<Message> messagesWithSameContext; using (mailbox.Messages.ReaderLock) messagesWithSameContext = mailbox.Messages.Where( m => m.MessageId != message.MessageId && (m.Context == context || m.Context.ToClearSubject() == context)) .ToList(); string conversationId = null; var recentRelatedMessage = messagesWithSameContext.Where(m => DateTime.Compare((m.SortDate).AddDays(3), DateTime.Now) >= 0).FirstOrDefault(); if (recentRelatedMessage != null) { conversationId = recentRelatedMessage.ConversationIdentifier; } else { if (message.MessageFolder == Folders.Inbox) { if (messagesWithSameContext.Count > 0) { // This is an incoming message SourceAddress from = message.From; bool isEmailChannel = SourceAddress.IsValidEmail(from.Address); //Get all channels for user var addresses = ChannelsManager .Channels .Where(c => c.InputChannel != null) .Select(c => c.InputChannel.SourceAdress) .ToList(); foreach (var contextMessage in messagesWithSameContext) { var addressCollection = new SourceAddressCollection(); addressCollection.AddRange(contextMessage.To); addressCollection.AddRange(contextMessage.CC); addressCollection.AddRange(contextMessage.BCC); addressCollection.Add(contextMessage.From); if (addressCollection.Contains(from, new SourceAddressComparer())) { bool hasMatchedConversation = false; if (message.To.Count( c => addresses.Contains(c.Address) || addressCollection.Contains(c)) > 0) hasMatchedConversation = true; if (!hasMatchedConversation && !isEmailChannel) { if (message.To.Count(addressCollection.Contains) > 0) hasMatchedConversation = true; } if (hasMatchedConversation) { conversationId = contextMessage.ConversationIdentifier; break; } } } } } } if (String.IsNullOrEmpty(conversationId)) { Logger.Debug("MatchOnSubject: Message {0} has no matching conversation, creating a new one", LogSource.MessageMatcher, message); // Nothing found, create new conversation conversation = CreateNewConversation(message); } else { using (mailbox.Conversations.ReaderLock) conversation = mailbox.Conversations.FirstOrDefault(c => c.ConversationIdentifier == conversationId); Logger.Debug("MatchOnSubject: Message {0} has matching conversation with ConversationId {1}", LogSource.MessageMatcher, message, conversation.ConversationId); UpdateMessage(message, conversation); Logger.Debug("MatchOnSubject: Message {0} now has ConversationId {1}", LogSource.MessageMatcher, message, message.ConversationIdentifier); } // End of line return ExecutionResult.Break; }