PageRenderTime 71ms CodeModel.GetById 43ms RepoModel.GetById 1ms app.codeStats 0ms

/Code/Channels/Exchange/ExchangeClientChannel.cs

https://github.com/csmaster2005/inbox2_desktop
C# | 415 lines | 302 code | 98 blank | 15 comment | 22 complexity | 478e57f9eff6e7b813a387b80d23c006 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.IO;
  5. using System.Net;
  6. using ExchangeServicesWsdlClient;
  7. using Inbox2.Platform.Channels.Entities;
  8. using Inbox2.Platform.Channels.Interfaces;
  9. using Inbox2.Platform.Framework.Extensions;
  10. using Inbox2.Platform.Logging;
  11. using Logger = Inbox2.Platform.Logging.Logger;
  12. namespace Inbox2.Channels.Exchange
  13. {
  14. public class ExchangeClientChannel : IClientInputChannel, IClientOutputChannel, IPagableChannel, IReadStateChannel, IClientContactsChannel, ILabelsChannel
  15. {
  16. private ChannelFolder folder;
  17. private List<ChannelFolder> folders;
  18. #region Properties
  19. public long StartIndex { get; set; }
  20. public long EndIndex { get; set; }
  21. public long PageSize { get; set; }
  22. public ChannelProgressDelegate BytesRead { get; set; }
  23. public ChannelProgressDelegate BytesWritten { get; set; }
  24. public string Hostname { get; set; }
  25. public int Port { get; set; }
  26. public bool IsSecured { get; set; }
  27. public string Username
  28. {
  29. get { return CredentialsProvider.GetCredentials().Claim; }
  30. }
  31. public string Password
  32. {
  33. get { return CredentialsProvider.GetCredentials().Evidence; }
  34. }
  35. public bool IsEnabled { get; set; }
  36. public int MaxConcurrentConnections { get; set; }
  37. public IChannelCredentialsProvider CredentialsProvider { get; set; }
  38. public string Protocol
  39. {
  40. get { return "ExchangeWS"; }
  41. }
  42. public string SourceAdress
  43. {
  44. get
  45. {
  46. string username = CredentialsProvider.GetCredentials().Claim;
  47. return username.Contains("@") ? username : String.Format("{0}@{1}", username, Hostname);
  48. }
  49. }
  50. public LabelsSupport LabelsSupport
  51. {
  52. get { return LabelsSupport.Folders; }
  53. }
  54. public string AuthMessage { get; private set; }
  55. #endregion
  56. public ConnectResult Connect()
  57. {
  58. var credentials = CredentialsProvider.GetCredentials();
  59. var binding = ChannelHelper.BuildChannel(Hostname, credentials.Claim, credentials.Evidence);
  60. folders = new List<ChannelFolder>();
  61. // Try connecting
  62. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(binding.Url);
  63. request.AllowAutoRedirect = false;
  64. request.Credentials = new NetworkCredential(credentials.Claim, credentials.Evidence);
  65. try
  66. {
  67. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  68. Logger.Debug("Server {0} returned status-code {1}", LogSource.Channel, binding.Url, response.StatusCode);
  69. if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Found)
  70. return ConnectResult.Success;
  71. AuthMessage = String.Format("Statuscode {0}", response.StatusCode);
  72. return ConnectResult.AuthFailure;
  73. }
  74. catch (Exception ex)
  75. {
  76. AuthMessage = ex.Message;
  77. return ConnectResult.AuthFailure;
  78. }
  79. }
  80. public IEnumerable<ChannelFolder> GetFolders()
  81. {
  82. var client = new ExchangeClient(Hostname, CredentialsProvider);
  83. // inbox
  84. var inbox = client.GetFolder(DistinguishedFolderIdNameType.inbox);
  85. folders.Add(new ChannelFolder(inbox.FolderId.Id, inbox.DisplayName, ChannelFolderType.Inbox));
  86. folders.AddRange(GetChildFolders(client, inbox.FolderId.Id, ChannelFolderType.Label));
  87. // sent items
  88. var sent = client.GetFolder(DistinguishedFolderIdNameType.sentitems);
  89. folders.Add(new ChannelFolder(sent.FolderId.Id, sent.DisplayName, ChannelFolderType.SentItems));
  90. folders.AddRange(GetChildFolders(client, sent.FolderId.Id, ChannelFolderType.SentItems));
  91. // trash
  92. var trash = client.GetFolder(DistinguishedFolderIdNameType.deleteditems);
  93. folders.Add(new ChannelFolder(trash.FolderId.Id, trash.DisplayName, ChannelFolderType.Trash));
  94. // spam
  95. var spam = client.GetFolder(DistinguishedFolderIdNameType.junkemail);
  96. folders.Add(new ChannelFolder(spam.FolderId.Id, spam.DisplayName, ChannelFolderType.Spam));
  97. return folders;
  98. }
  99. IEnumerable<ChannelFolder> GetChildFolders(ExchangeClient client, string folderId, ChannelFolderType folderType)
  100. {
  101. var childFolders = client.FindAllFolders(folderId);
  102. return childFolders.Select(f => new ChannelFolder(f.FolderId.Id, f.DisplayName, folderType));
  103. }
  104. public void SelectFolder(ChannelFolder folder)
  105. {
  106. this.folder = folder;
  107. }
  108. public IEnumerable<ChannelMessageHeader> GetHeaders()
  109. {
  110. var client = new ExchangeClient(Hostname, CredentialsProvider);
  111. foreach (MessageType inboxItem in client.GetHeaders(folder).Reverse().Skip((int)StartIndex).Take((int)PageSize))
  112. {
  113. var header = new ChannelMessageHeader
  114. {
  115. MessageNumber = inboxItem.ItemId.Id,
  116. MessageIdentifier = inboxItem.InternetMessageId,
  117. Context = inboxItem.Subject,
  118. // Not sending size because exchange changes can the size due
  119. // to user actions usch as change priority.
  120. //Size = inboxItem.Size,
  121. DateReceived = inboxItem.DateTimeReceived,
  122. IsRead = inboxItem.IsRead,
  123. // Not processing IsStarred because somebody could send you an
  124. // email with importance: high and would end up getting starred;
  125. // feature just asking for abuse :-)
  126. //IsStarred = inboxItem.Importance == ImportanceChoicesType.High,
  127. };
  128. yield return header;
  129. }
  130. }
  131. public IEnumerable<ChannelMessage> GetMessage(ChannelMessageHeader header)
  132. {
  133. var client = new ExchangeClient(Hostname, CredentialsProvider);
  134. ChannelMessage message = new ChannelMessage();
  135. MessageType inboxItem = client.GetMessage(header.MessageNumber);
  136. // Now the message Body is there.
  137. BodyType messageBody = inboxItem.Body;
  138. message.Size = header.Size;
  139. message.MessageNumber = header.MessageNumber;
  140. message.MessageIdentifier = header.MessageIdentifier;
  141. message.Context = header.Context;
  142. message.From = new SourceAddress(inboxItem.From.Item.EmailAddress, inboxItem.From.Item.Name);
  143. if (inboxItem.ToRecipients != null)
  144. foreach (var toRecipient in inboxItem.ToRecipients)
  145. message.To.Add(new SourceAddress(toRecipient.EmailAddress, toRecipient.Name));
  146. if (inboxItem.CcRecipients != null)
  147. foreach (var ccRecipient in inboxItem.CcRecipients)
  148. message.CC.Add(new SourceAddress(ccRecipient.EmailAddress, ccRecipient.Name));
  149. if (inboxItem.BccRecipients != null)
  150. foreach (var bccRecipient in inboxItem.BccRecipients)
  151. message.BCC.Add(new SourceAddress(bccRecipient.EmailAddress, bccRecipient.Name));
  152. message.InReplyTo = inboxItem.InReplyTo;
  153. message.Metadata = header.Metadata;
  154. message.IsRead = inboxItem.IsRead;
  155. message.BodyHtml = messageBody.Value.ToStream();
  156. message.DateReceived = header.DateReceived;
  157. if (inboxItem.Attachments != null)
  158. {
  159. foreach (AttachmentType exchAttachment in inboxItem.Attachments)
  160. {
  161. var fileAttachment = client.GetAttachment(exchAttachment.AttachmentId.Id);
  162. message.Attachments.Add(new ChannelAttachment
  163. {
  164. Filename = fileAttachment.Name,
  165. ContentType = ContentType.Attachment,
  166. ContentStream = new MemoryStream(fileAttachment.Content)
  167. });
  168. }
  169. }
  170. yield return message;
  171. }
  172. public void Send(ChannelMessage message)
  173. {
  174. var client = new ExchangeClient(Hostname, CredentialsProvider);
  175. var messageId = client.SaveMessage(message);
  176. // Upload attachments
  177. if (message.Attachments.Count > 0)
  178. client.SaveAttachments(messageId, message);
  179. // Refresh and send message by message-id
  180. client.SendMessage(client.GetMessageId(messageId.Id).ItemId);
  181. }
  182. public bool Disconnect()
  183. {
  184. return true;
  185. }
  186. public IClientInputChannel Clone()
  187. {
  188. return new ExchangeClientChannel
  189. {
  190. Hostname = Hostname,
  191. Port = Port,
  192. IsSecured = IsSecured,
  193. MaxConcurrentConnections = MaxConcurrentConnections,
  194. CredentialsProvider = CredentialsProvider
  195. };
  196. }
  197. public void Dispose()
  198. {
  199. }
  200. public long GetNumberOfItems()
  201. {
  202. var client = new ExchangeClient(Hostname, CredentialsProvider);
  203. return client.GetNrItemsInFolder(folder);
  204. }
  205. public void MarkRead(ChannelMessageHeader message)
  206. {
  207. var client = new ExchangeClient(Hostname, CredentialsProvider);
  208. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  209. client.SetMessageReadState(messageId, true);
  210. }
  211. public void MarkUnread(ChannelMessageHeader message)
  212. {
  213. var client = new ExchangeClient(Hostname, CredentialsProvider);
  214. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  215. client.SetMessageReadState(messageId, false);
  216. }
  217. public void MarkDeleted(ChannelMessageHeader message)
  218. {
  219. var trash = GetFolders().First(f => f.FolderType == ChannelFolderType.Trash);
  220. var client = new ExchangeClient(Hostname, CredentialsProvider);
  221. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  222. client.MoveMessageToFolder(messageId, trash.FolderId);
  223. }
  224. public void SetStarred(ChannelMessageHeader message, bool starred)
  225. {
  226. var client = new ExchangeClient(Hostname, CredentialsProvider);
  227. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  228. client.SetMessageImportance(messageId, starred);
  229. }
  230. public void Purge(ChannelMessageHeader message)
  231. {
  232. var client = new ExchangeClient(Hostname, CredentialsProvider);
  233. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  234. client.DeleteMessage(messageId);
  235. }
  236. public ChannelFolder CreateFolder(string folderName)
  237. {
  238. var client = new ExchangeClient(Hostname, CredentialsProvider);
  239. var folderId = client.CreateFolder(folderName, folders.First(f => f.FolderType == ChannelFolderType.Inbox).FolderId);
  240. var newFolder = new ChannelFolder(folderId, folderName, ChannelFolderType.Label);
  241. folders.Add(newFolder);
  242. return newFolder;
  243. }
  244. public void MoveToFolder(ChannelMessageHeader message, ChannelFolder folder)
  245. {
  246. var client = new ExchangeClient(Hostname, CredentialsProvider);
  247. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  248. client.MoveMessageToFolder(messageId, folder.FolderId);
  249. }
  250. public void CopyToFolder(ChannelMessageHeader message, ChannelFolder folder)
  251. {
  252. var client = new ExchangeClient(Hostname, CredentialsProvider);
  253. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  254. client.CopyMessageToFolder(messageId, folder.FolderId);
  255. }
  256. public void RemoveFromFolder(ChannelMessageHeader message, ChannelFolder folder)
  257. {
  258. var client = new ExchangeClient(Hostname, CredentialsProvider);
  259. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  260. client.DeleteMessage(messageId);
  261. }
  262. public void AddLabel(ChannelMessageHeader message, string labelname)
  263. {
  264. var client = new ExchangeClient(Hostname, CredentialsProvider);
  265. var messageId = client.GetMessageId(message.MessageNumber).ItemId;
  266. client.CopyMessageToFolder(messageId, folders.First(f => f.Name.ToLower() == labelname.ToLower()).FolderId);
  267. }
  268. public void RemoveLabel(string messagenumber, string labelname)
  269. {
  270. var client = new ExchangeClient(Hostname, CredentialsProvider);
  271. var messageId = client.GetMessageId(messagenumber).ItemId;
  272. client.DeleteMessage(messageId);
  273. }
  274. public IEnumerable<ChannelContact> GetContacts()
  275. {
  276. var client = new ExchangeClient(Hostname, CredentialsProvider);
  277. foreach (var contactItem in client.GetContacts())
  278. {
  279. if (contactItem.EmailAddresses == null || contactItem.EmailAddresses.Length == 0)
  280. {
  281. Logger.Warn("Contact {0} had no email address, ignoring", LogSource.Sync, contactItem.DisplayName);
  282. continue;
  283. }
  284. var contact = new ChannelContact();
  285. contact.Profile.ChannelProfileKey = contactItem.ItemId.Id;
  286. contact.Profile.SourceAddress = new SourceAddress(contactItem.EmailAddresses[0].Value, contactItem.DisplayName);
  287. contact.Person.Lastname = contactItem.Surname;
  288. contact.Person.Firstname = contactItem.GivenName;
  289. if (contactItem.BirthdaySpecified)
  290. contact.Person.DateOfBirth = contactItem.Birthday;
  291. contact.Profile.ScreenName = contactItem.Nickname;
  292. contact.Profile.Title = contactItem.JobTitle;
  293. contact.Profile.ScreenName = contactItem.DisplayName;
  294. contact.Profile.CompanyName = contactItem.CompanyName;
  295. if (contactItem.PhysicalAddresses.Length > 0)
  296. {
  297. contact.Profile.Street = contactItem.PhysicalAddresses[0].Street;
  298. contact.Profile.ZipCode = contactItem.PhysicalAddresses[0].PostalCode;
  299. contact.Profile.City = contactItem.PhysicalAddresses[0].City;
  300. contact.Profile.Country = contactItem.PhysicalAddresses[0].CountryOrRegion;
  301. }
  302. yield return contact;
  303. }
  304. }
  305. IClientContactsChannel IClientContactsChannel.Clone()
  306. {
  307. return new ExchangeClientChannel()
  308. {
  309. Hostname = Hostname,
  310. Port = Port,
  311. IsSecured = IsSecured,
  312. MaxConcurrentConnections = MaxConcurrentConnections,
  313. CredentialsProvider = CredentialsProvider
  314. };
  315. }
  316. }
  317. }