1: using ActiveUp.Net.Mail;
2: using System;
3: using System.Collections.Generic;
4: using System.Configuration;
5:
6: namespace Ia.Cl.Model
7: {
8: ////////////////////////////////////////////////////////////////////////////
9:
10: /// <summary publish="true">
11: /// IMAP support class.
12: /// </summary>
13: ///
14: /// <see href="http://www.skytale.net/blog/archives/23-Manual-IMAP.html"/>
15: /// <see href="http://tools.ietf.org/html/rfc3501#page-51"/>
16: /// <see href="https://www.aspsnippets.com/Articles/Fetch-and-read-email-messages-with-attachments-from-GMAIL-POP3-mail-server-in-ASPNet.aspx"/>
17: ///
18: /// <remarks>
19: /// Copyright © 2001-2015 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
20: ///
21: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
22: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
23: ///
24: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
25: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26: ///
27: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
28: ///
29: /// Copyright notice: This notice may not be removed or altered from any source distribution.
30: /// </remarks>
31: public class Imap
32: {
33: private bool serverEnableSsl;
34: private string serverHost, serverUser, serverPassword, defaultMailbox;
35: private Imap4Client imap;
36:
37: ////////////////////////////////////////////////////////////////////////////
38:
39: /// <summary>
40: ///
41: /// </summary>
42: public class Message
43: {
44: /// <summary/>
45: public Message()
46: {
47: this.Attachments = new List<Attachment>();
48: }
49:
50: /// <summary/>
51: public string MessageId { get; set; }
52:
53: /// <summary/>
54: public string From { get; set; }
55:
56: /// <summary/>
57: public string Subject { get; set; }
58: /// <summary/>
59: public string BodyText { get; set; }
60:
61: /// <summary/>
62: public DateTime Date { get; set; }
63:
64: /// <summary/>
65: public DateTime ReceivedDate { get; set; }
66:
67: /// <summary/>
68: public List<Attachment> Attachments { get; set; }
69:
70: /// <summary/>
71: public Message(string messageId, string from, string subject, string bodyText)
72: {
73: this.MessageId = messageId;
74: this.From = from;
75: this.Subject = subject;
76: this.BodyText = bodyText;
77: }
78: }
79:
80: ////////////////////////////////////////////////////////////////////////////
81:
82: /// <summary>
83: ///
84: /// </summary>
85: public class Header
86: {
87: /// <summary/>
88: public Header()
89: {
90: }
91:
92: /// <summary/>
93: public string MessageId { get; set; }
94: /// <summary/>
95: public string From { get; set; }
96: /// <summary/>
97: public string Subject { get; set; }
98: /// <summary/>
99: public DateTime Date { get; set; }
100: /// <summary/>
101: public DateTime ReceivedDate { get; set; }
102:
103: /// <summary/>
104: public Header(string messageId, string from, string subject)
105: {
106: this.MessageId = messageId;
107: this.From = from;
108: this.Subject = subject;
109: }
110: }
111:
112: ////////////////////////////////////////////////////////////////////////////
113:
114: /// <summary>
115: ///
116: /// </summary>
117: public class Attachment
118: {
119: /// <summary/>
120: public string FileName { get; set; }
121: /// <summary/>
122: public string ContentType { get; set; }
123: /// <summary/>
124: public string Content { get; set; }
125: }
126:
127: ////////////////////////////////////////////////////////////////////////////
128:
129: /// <summary>
130: ///
131: /// </summary>
132: public Imap()
133: {
134: bool b;
135:
136: /*
137: * app.config
138: * <add key="imapServerHost" value="*" />
139: * <add key="imapServerUser" value="*" />
140: * <add key="imapServerPassword" value="*" />
141: * <add key="imapServerEnableSsl" value="*" />
142: */
143:
144: serverHost = ConfigurationManager.AppSettings["imapServerHost"].ToString();
145: serverUser = ConfigurationManager.AppSettings["imapServerUser"].ToString();
146: serverPassword = ConfigurationManager.AppSettings["imapServerPassword"].ToString();
147: serverEnableSsl = bool.TryParse(ConfigurationManager.AppSettings["imapServerEnableSsl"].ToString(), out b) ? b : false;
148:
149: Initialize();
150: }
151:
152: ////////////////////////////////////////////////////////////////////////////
153:
154: /// <summary>
155: ///
156: /// </summary>
157: public Imap(string _server, string _user, string _password, bool _useSsl)
158: {
159: this.serverHost = _server;
160: this.serverUser = _user;
161: this.serverPassword = _password;
162: this.serverEnableSsl = _useSsl;
163:
164: Initialize();
165: }
166:
167: ////////////////////////////////////////////////////////////////////////////
168:
169: /// <summary>
170: ///
171: /// </summary>
172: ~Imap()
173: {
174: Disconnect();
175: }
176:
177: ////////////////////////////////////////////////////////////////////////////
178:
179: /// <summary>
180: ///
181: /// </summary>
182: private void Initialize()
183: {
184: defaultMailbox = "Inbox";
185:
186: imap = new Imap4Client();
187:
188: this.Log("Initialize(): Imap object created");
189: }
190:
191: ////////////////////////////////////////////////////////////////////////////
192:
193: /// <summary>
194: ///
195: /// </summary>
196: public void Connect()
197: {
198: if (serverEnableSsl) imap.ConnectSsl(serverHost);
199: else imap.Connect(serverHost);
200:
201: this.Log("Connect(): Connection opened to " + serverHost);
202:
203: imap.Login(serverUser, serverPassword);
204:
205: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
206: }
207:
208: ////////////////////////////////////////////////////////////////////////////
209:
210: /// <summary>
211: ///
212: /// </summary>
213: public bool IsConnected
214: {
215: get
216: {
217: this.Log("IsConnected: " + imap.IsConnected.ToString());
218:
219: return imap.IsConnected;
220: }
221: }
222:
223: ////////////////////////////////////////////////////////////////////////////
224:
225: /// <summary>
226: ///
227: /// </summary>
228: public void Disconnect()
229: {
230: if (imap.IsConnected)
231: {
232: try
233: {
234: imap.Disconnect();
235:
236: this.Log("Disconnect(): Disconnected");
237: }
238: catch (Exception ex)
239: {
240: this.Log("Disconnect(): Exception: " + ex.ToString());
241: }
242: }
243: else
244: {
245: this.Log("Disconnect(): Already disconnected");
246: }
247: }
248:
249: ////////////////////////////////////////////////////////////////////////////
250:
251: /// <summary>
252: ///
253: /// </summary>
254: public List<string> MailboxList()
255: {
256: List<string> mailboxList;
257:
258: mailboxList = new List<string>(imap.Mailboxes.Count);
259:
260: foreach (Mailbox mailbox in imap.Mailboxes) mailboxList.Add(mailbox.Name);
261:
262: return mailboxList;
263: }
264:
265: ////////////////////////////////////////////////////////////////////////////
266:
267: /// <summary>
268: ///
269: /// </summary>
270: public void CreateMailbox(string mailboxName)
271: {
272: imap.CreateMailbox(mailboxName);
273: }
274:
275: ////////////////////////////////////////////////////////////////////////////
276:
277: /// <summary>
278: ///
279: /// </summary>
280: public string DeleteMailbox(string mailboxName)
281: {
282: return imap.DeleteMailbox(mailboxName);
283: }
284:
285: ////////////////////////////////////////////////////////////////////////////
286:
287: /// <summary>
288: ///
289: /// </summary>
290: public Header ReadHeader(Mailbox mailbox, int i)
291: {
292: Header header;
293: ActiveUp.Net.Mail.Header aHeader;
294:
295: header = new Header();
296:
297: try
298: {
299: aHeader = mailbox.Fetch.HeaderObject(i);
300:
301: header.MessageId = aHeader.MessageId;
302: header.From = aHeader.From.Email;
303: header.Subject = aHeader.Subject;
304:
305: this.Log(string.Format("Success: Header read: {0},{1},{2}", header.MessageId, header.From, header.Subject));
306: }
307: catch (Imap4Exception iex)
308: {
309: this.Log(string.Format("Imap4 Error: {0}", iex.Message));
310: }
311: catch (Exception ex)
312: {
313: this.Log(string.Format("Failed: {0}", ex.Message));
314: }
315: finally
316: {
317: }
318:
319: return header;
320: }
321:
322: ////////////////////////////////////////////////////////////////////////////
323:
324: /// <summary>
325: ///
326: /// </summary>
327: public int MoveMessagesFromEmailToMailbox(string email, string destinationMailboxName)
328: {
329: int numberOfMessagesMoved;
330: int[] messageOrdinalList;
331: string searchPhrase;
332: Mailbox mailbox;
333:
334: numberOfMessagesMoved = 0;
335:
336: mailbox = imap.SelectMailbox(defaultMailbox);
337:
338: searchPhrase = @"FROM """ + email + @"""";
339:
340: messageOrdinalList = mailbox.Search(searchPhrase);
341:
342: if (messageOrdinalList != null && messageOrdinalList.Length > 0)
343: {
344: // read message and check that from-email value before moving
345: for (int i = messageOrdinalList.Length - 1; i >= 0; i--)
346: {
347: MoveMessage(mailbox, messageOrdinalList[i], destinationMailboxName);
348: numberOfMessagesMoved++;
349: }
350: }
351:
352: return numberOfMessagesMoved;
353: }
354:
355: ////////////////////////////////////////////////////////////////////////////
356:
357: /// <summary>
358: ///
359: /// </summary>
360: public void MoveMessage(string messageId, string destinationMailboxName)
361: {
362: int[] messageOrdinalList;
363: string searchPhrase;
364: Mailbox mailbox;
365: ActiveUp.Net.Mail.Header header;
366:
367: mailbox = imap.SelectMailbox(defaultMailbox);
368:
369: searchPhrase = @"ALL";
370:
371: messageOrdinalList = mailbox.Search(searchPhrase);
372:
373: if (messageOrdinalList != null && messageOrdinalList.Length > 0)
374: {
375: for (int i = messageOrdinalList.Length - 1; i >= 0; i--)
376: {
377: header = mailbox.Fetch.HeaderObject(messageOrdinalList[i]);
378:
379: if (header.MessageId == messageId)
380: {
381: MoveMessage(mailbox, messageOrdinalList[i], destinationMailboxName);
382:
383: break;
384: }
385: }
386: }
387: }
388:
389: ////////////////////////////////////////////////////////////////////////////
390:
391: /// <summary>
392: ///
393: /// </summary>
394: public void MoveMessage(Mailbox mailbox, int messageOrdinal, string destinationMailboxName)
395: {
396: mailbox.MoveMessage(messageOrdinal, destinationMailboxName);
397:
398: this.Log("Move message: " + messageOrdinal + " to mailbox '" + destinationMailboxName + "'");
399: }
400:
401: ////////////////////////////////////////////////////////////////////////////
402:
403: /// <summary>
404: /// Message list from Inbox
405: /// </summary>
406: public void MessageList(out List<Message> messageList)
407: {
408: string searchPhrase;
409:
410: searchPhrase = "ALL";
411:
412: SearchPhraseMessageList(searchPhrase, out messageList);
413: }
414:
415: ////////////////////////////////////////////////////////////////////////////
416:
417: /// <summary>
418: /// List of messages from Inbox that were sent from email
419: /// </summary>
420: public void MessageList(string email, out List<Message> messageList)
421: {
422: string searchPhrase;
423:
424: searchPhrase = @"FROM """ + email + @"""";
425:
426: SearchPhraseMessageList(searchPhrase, out messageList);
427: }
428:
429: ////////////////////////////////////////////////////////////////////////////
430:
431: /// <summary>
432: ///
433: /// </summary>
434: private void SearchPhraseMessageList(string searchPhrase, out List<Message> messageList)
435: {
436: Message message;
437: Mailbox mailbox;
438: MessageCollection messageCollection;
439:
440: messageList = new List<Message>();
441:
442: mailbox = imap.SelectMailbox(defaultMailbox);
443:
444: try
445: {
446: messageCollection = mailbox.SearchParse(searchPhrase);
447:
448: foreach (ActiveUp.Net.Mail.Message m in messageCollection)
449: {
450: message = new Message();
451:
452: message.MessageId = m.MessageId;
453: message.From = m.From.Email;
454: message.Subject = m.Subject;
455: message.BodyText = m.BodyText.TextStripped;
456: message.Date = m.Date;
457: message.ReceivedDate = m.ReceivedDate;
458:
459: foreach (ActiveUp.Net.Mail.MimePart mp in m.Attachments)
460: {
461: //if (mp.IsText)
462: //{
463: message.Attachments.Add(new Attachment
464: {
465: FileName = mp.Filename,
466: ContentType = mp.ContentType.MimeType,
467: Content = mp.TextContent
468: });
469: //}
470: }
471:
472: messageList.Add(message);
473:
474: this.Log(string.Format("Success: Message read: {0},{1},{2}", m.MessageId, m.From, m.Subject));
475: }
476: }
477: catch (Imap4Exception iex)
478: {
479: this.Log(string.Format("Imap4 Error: {0}", iex.Message));
480: }
481: catch (Exception ex)
482: {
483: this.Log(string.Format("Failed: {0}", ex.Message));
484: }
485: finally
486: {
487: }
488: }
489:
490: ////////////////////////////////////////////////////////////////////////////
491:
492: /// <summary>
493: ///
494: /// </summary>
495: public List<Header> HeaderList(Mailbox mailbox)
496: {
497: Header header;
498: List<Header> headerList;
499: ActiveUp.Net.Mail.Header aHeader;
500:
501: headerList = new List<Header>(mailbox.MessageCount);
502:
503: try
504: {
505: for (int i = 1; i <= mailbox.MessageCount; i++)
506: {
507: header = new Header();
508:
509: aHeader = mailbox.Fetch.MessageObject(i);
510:
511: header.MessageId = aHeader.MessageId;
512: header.From = aHeader.From.Email;
513: header.Subject = aHeader.Subject;
514:
515: this.Log(string.Format("Success: Header read: {0},{1},{2}", header.MessageId, header.From, header.Subject));
516: }
517: }
518: catch (Imap4Exception iex)
519: {
520: this.Log(string.Format("Imap4 Error: {0}", iex.Message));
521: }
522: catch (Exception ex)
523: {
524: this.Log(string.Format("Failed: {0}", ex.Message));
525: }
526: finally
527: {
528: }
529:
530: return headerList;
531: }
532:
533: ////////////////////////////////////////////////////////////////////////////
534:
535: /// <summary>
536: ///
537: /// </summary>
538: public void DeleteMessage(string messageId)
539: {
540: int[] messageOrdinalList;
541: string searchPhrase;
542: Mailbox mailbox;
543: ActiveUp.Net.Mail.Header header;
544:
545: mailbox = imap.SelectMailbox(defaultMailbox);
546:
547: searchPhrase = @"ALL";
548:
549: messageOrdinalList = mailbox.Search(searchPhrase);
550:
551: if (messageOrdinalList != null && messageOrdinalList.Length > 0)
552: {
553: for (int i = messageOrdinalList.Length - 1; i >= 0; i--)
554: {
555: header = mailbox.Fetch.HeaderObject(messageOrdinalList[i]);
556:
557: if (header.MessageId == messageId)
558: {
559: DeleteMessage(mailbox, messageOrdinalList[i]);
560: }
561: }
562: }
563: }
564:
565: ////////////////////////////////////////////////////////////////////////////
566:
567: /// <summary>
568: ///
569: /// </summary>
570: private void DeleteMessage(Mailbox mailbox, int messageOrdinal)
571: {
572: mailbox.DeleteMessage(messageOrdinal, true);
573:
574: this.Log("Delete message: " + messageOrdinal);
575: }
576:
577: ////////////////////////////////////////////////////////////////////////////
578:
579: /// <summary>
580: ///
581: /// </summary>
582: private void Log(string text)
583: {
584: string line;
585: DateTime now;
586:
587: now = DateTime.UtcNow.AddHours(3);
588:
589: line = now.ToString("yyyy-MM-dd HH:mm:ss: ") + text;
590:
591: Console.WriteLine(line);
592: }
593:
594: ////////////////////////////////////////////////////////////////////////////
595: ////////////////////////////////////////////////////////////////////////////
596: }
597: }