internal MailBatchDatum(FolderModel folderModel, string mailId, string messageHead) { this.FolderModel = folderModel; this.MailId = mailId; this.MessageHead = messageHead; this.uploaded = true; }
/// <summary> /// Persists the selection state, uploaded mail count, failed mail count and /// last uplaoded mail id. Ten recurses to persist all the sub folders. /// </summary> void SaveFolderModelState(XmlElement parentXmlElement, FolderModel folderModel) { XmlElement folderXmlElement = this.xmlDocument.CreateElement(LKGStatePersistor.FolderElementName); parentXmlElement.AppendChild(folderXmlElement); folderXmlElement.SetAttribute( LKGStatePersistor.NameAttrName, folderModel.Folder.Name); folderXmlElement.SetAttribute( LKGStatePersistor.SelectionStateAttrName, folderModel.IsSelected.ToString()); foreach (string mailId in folderModel.MailUploadData.Keys) { XmlElement uploadedEmailXmlElement = this.xmlDocument.CreateElement( LKGStatePersistor.MailElementName); folderXmlElement.AppendChild(uploadedEmailXmlElement); uploadedEmailXmlElement.SetAttribute( LKGStatePersistor.MailIdAttrName, mailId); FailedMailDatum failedMailDatum = (FailedMailDatum)folderModel.MailUploadData[mailId]; if (failedMailDatum != null) { // In case of failure to upload we set the reason, otherwise not. uploadedEmailXmlElement.SetAttribute( LKGStatePersistor.FailureReasonAttrName, failedMailDatum.FailureReason); uploadedEmailXmlElement.InnerText = failedMailDatum.MailHead; } } foreach (FolderModel childFolderModel in folderModel.Children) { this.SaveFolderModelState( folderXmlElement, childFolderModel); } }
/// <summary> /// Loads the folder state i.e. SelectionState, UploadedMailCount, /// FailedMailCount, LastUploadedMailId. Then it recurses on the /// sub folders. /// </summary> void LoadFolderModelState(XmlElement folderXmlElement, FolderModel folderModel) { LKGStatePersistor.LoadSelectedState( folderXmlElement, folderModel); foreach (XmlNode childXmlNode in folderXmlElement.ChildNodes) { XmlElement childXmlElement = childXmlNode as XmlElement; if (childXmlElement == null) { continue; } if (childXmlElement.Name != LKGStatePersistor.MailElementName) { continue; } string mailId = childXmlElement.GetAttribute(LKGStatePersistor.MailIdAttrName); if (mailId == null || mailId.Length == 0) { continue; } string failureReason = childXmlElement.GetAttribute( LKGStatePersistor.FailureReasonAttrName); if (failureReason == null || failureReason.Length == 0) { folderModel.SuccessfullyUploaded(mailId); } else { FailedMailDatum failedMailDatum = new FailedMailDatum(childXmlElement.InnerText, failureReason); folderModel.FailedToUpload(mailId, failedMailDatum); } } this.LoadFolderModelsState( folderXmlElement.ChildNodes, folderModel.Children); }
bool MoveToNextNonEmptySelectedFolder() { this.DisposeCurrentEnumerator(); while (this.folderIterationIndex < this.folderModelFlatList.Count) { this.currentFolderModel = (FolderModel)this.folderModelFlatList[this.folderIterationIndex]; this.folderIterationIndex++; if (!this.currentFolderModel.IsSelected || this.currentFolderModel.Folder.MailCount == 0) { continue; } this.currentFolderEnumerator = this.currentFolderModel.Folder.Mails.GetEnumerator(); if (!this.currentFolderEnumerator.MoveNext()) { // We reached the end of the folder // so dispose enumerator and continue with the next folder. this.DisposeCurrentEnumerator(); continue; } // There are mails and current points to the mail to be uploaded. return true; } this.currentFolderModel = null; return false; }
internal unsafe bool AddMail(IMail mail, FolderModel folderModel) { byte[] rfc822Buffer = mail.Rfc822Buffer; Debug.Assert(rfc822Buffer.Length > 0 && rfc822Buffer.Length <= GoogleEmailUploaderConfig.MaximumBatchSize); bool canAdd = ( // If its multimail batch let it be almost default mail batch size this.mailCount > 0 && this.MemoryStream.Length + rfc822Buffer.Length + 2048 <= GoogleEmailUploaderConfig.NormalBatchSize && this.mailCount < GoogleEmailUploaderConfig.MaximumMailsPerBatch ) || ( // If this mail is HUGE then its ok to be in singleton batch. this.mailCount == 0 && rfc822Buffer.Length <= GoogleEmailUploaderConfig.MaximumBatchSize); if (!canAdd) { return false; } this.batchXmlTextWriter.WriteStartElement(MailBatch.EntryElementName, MailBatch.AtomNS); { // Add the category element to the feed. this.batchXmlTextWriter.WriteStartElement("category", MailBatch.AtomNS); this.batchXmlTextWriter.WriteAttributeString("scheme", MailBatch.GDataKindURI); this.batchXmlTextWriter.WriteAttributeString("term", MailBatch.AppsMailItemURI); this.batchXmlTextWriter.WriteEndElement(); } // Write out batchId { this.batchXmlTextWriter.WriteStartElement(MailBatch.IdElementName, MailBatch.GDataBatchNS); this.batchXmlTextWriter.WriteString(this.mailCount.ToString()); this.batchXmlTextWriter.WriteEndElement(); } // Write out rfc822... { bool containsNonPrintASCII = false; // This test is rough. utf8 is multi byte, so having the illegal xml // byte need not mean its illegal xml. We could send every thing as // base64. This just helps us to optimize saving bytes on the wire. for (int i = 0; i < rfc822Buffer.Length; ++i) { byte b = rfc822Buffer[i]; if (b >= 0x80 || !MailBatch.IsPrintableAscii[b]) { containsNonPrintASCII = true; break; } } this.batchXmlTextWriter.WriteStartElement("rfc822Msg", MailBatch.AppsNS); if (containsNonPrintASCII) { // If the rfc822 contains illegal xml chars then // we use base64 encoding. this.batchXmlTextWriter.WriteAttributeString("encoding", "base64"); this.batchXmlTextWriter.WriteBase64(rfc822Buffer, 0, rfc822Buffer.Length); } else { // Otherwise we embed the rfc as is. string rfcString = Encoding.UTF8.GetString(rfc822Buffer); this.batchXmlTextWriter.WriteString(rfcString); } this.batchXmlTextWriter.WriteEndElement(); } // Write out mail item properties except IS_TRASH. We will not move // anything to Trash folder as it automatically empties the Trash. { if (!mail.IsRead) { this.batchXmlTextWriter.WriteStartElement("mailItemProperty", MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("value", "IS_UNREAD"); this.batchXmlTextWriter.WriteEndElement(); } if (mail.IsStarred) { this.batchXmlTextWriter.WriteStartElement("mailItemProperty", MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("value", "IS_STARRED"); this.batchXmlTextWriter.WriteEndElement(); } if (MailBatch.IsAncestor(mail.Folder, FolderKind.Inbox) && !this.GoogleEmailUploaderModel.IsArchiveEverything) { this.batchXmlTextWriter.WriteStartElement("mailItemProperty", MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("value", "IS_INBOX"); this.batchXmlTextWriter.WriteEndElement(); } if (MailBatch.IsAncestor(mail.Folder, FolderKind.Sent)) { this.batchXmlTextWriter.WriteStartElement("mailItemProperty", MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("value", "IS_SENT"); this.batchXmlTextWriter.WriteEndElement(); } if (MailBatch.IsAncestor(mail.Folder, FolderKind.Draft)) { this.batchXmlTextWriter.WriteStartElement("mailItemProperty", MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("value", "IS_DRAFT"); this.batchXmlTextWriter.WriteEndElement(); } } // Write out labels... { string[] labels = folderModel.Labels; for (int i = 0; i < labels.Length; ++i) { this.batchXmlTextWriter.WriteStartElement("label", MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("labelName", labels[i]); this.batchXmlTextWriter.WriteEndElement(); } } this.batchXmlTextWriter.WriteEndElement(); this.mailCount++; this.lastAddedFolderModel = folderModel; MailBatchDatum batchData = new MailBatchDatum(folderModel, mail.MailId, MailBatch.GetMailHeader(mail)); this.MailBatchData.Add(batchData); return true; }
internal void StartBatch() { this.MemoryStream.Position = 0; this.MemoryStream.SetLength(0); this.mailCount = 0; this.MailBatchData.Clear(); this.lastAddedFolderModel = null; this.batchXmlTextWriter = new XmlTextWriter(this.MemoryStream, Encoding.UTF8); this.batchXmlTextWriter.Formatting = Formatting.Indented; // Start the document this.batchXmlTextWriter.WriteStartDocument(); // Start the feed... this.batchXmlTextWriter.WriteStartElement("a", MailBatch.FeedElementName, MailBatch.AtomNS); this.batchXmlTextWriter.WriteAttributeString("xmlns", "app", MailBatch.XmlNS, MailBatch.AppsNS); this.batchXmlTextWriter.WriteAttributeString("xmlns", "batch", MailBatch.XmlNS, MailBatch.GDataBatchNS); this.startDateTime = DateTime.Now; }