1: using System;
2: using System.Collections.Generic;
3: using System.Configuration;
4: using ActiveUp.Net.Mail;
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-2021 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 readonly bool serverEnableSsl;
34: private readonly string serverHost, serverUser, serverPassword;
35: private readonly string defaultMailbox;
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:
59: /// <summary/>
60: public string BodyText { get; set; }
61:
62: /// <summary/>
63: public DateTime Date { get; set; }
64:
65: /// <summary/>
66: public DateTime ReceivedDate { get; set; }
67:
68: /// <summary/>
69: public List<Attachment> Attachments { get; set; }
70:
71: /// <summary/>
72: public Message(string messageId, string from, string subject, string bodyText)
73: {
74: this.MessageId = messageId;
75: this.From = from;
76: this.Subject = subject;
77: this.BodyText = bodyText;
78: }
79: }
80:
81: ////////////////////////////////////////////////////////////////////////////
82:
83: /// <summary>
84: ///
85: /// </summary>
86: public class Header
87: {
88: /// <summary/>
89: public Header()
90: {
91: }
92:
93: /// <summary/>
94: public string MessageId { get; set; }
95:
96: /// <summary/>
97: public string From { get; set; }
98:
99: /// <summary/>
100: public string Subject { get; set; }
101:
102: /// <summary/>
103: public DateTime Date { get; set; }
104:
105: /// <summary/>
106: public DateTime ReceivedDate { get; set; }
107:
108: /// <summary/>
109: public Header(string messageId, string from, string subject)
110: {
111: this.MessageId = messageId;
112: this.From = from;
113: this.Subject = subject;
114: }
115: }
116:
117: ////////////////////////////////////////////////////////////////////////////
118:
119: /// <summary>
120: ///
121: /// </summary>
122: public class Attachment
123: {
124: /// <summary/>
125: public string FileName { get; set; }
126:
127: /// <summary/>
128: public string ContentType { get; set; }
129:
130: /// <summary/>
131: public string Content { get; set; }
132: }
133:
134: ////////////////////////////////////////////////////////////////////////////
135:
136: /// <summary>
137: ///
138: /// </summary>
139: public Imap()
140: {
141: /*
142: * app.config
143: * <add key="imapServerHost" value="*" />
144: * <add key="imapServerUser" value="*" />
145: * <add key="imapServerPassword" value="*" />
146: * <add key="imapServerEnableSsl" value="*" />
147: */
148:
149: serverHost = ConfigurationManager.AppSettings["imapServerHost"].ToString();
150: serverUser = ConfigurationManager.AppSettings["imapServerUser"].ToString();
151: serverPassword = ConfigurationManager.AppSettings["imapServerPassword"].ToString();
152: serverEnableSsl = bool.TryParse(ConfigurationManager.AppSettings["imapServerEnableSsl"].ToString(), out bool b) && b;
153:
154: defaultMailbox = "Inbox";
155: }
156:
157: ////////////////////////////////////////////////////////////////////////////
158:
159: /// <summary>
160: ///
161: /// </summary>
162: public Imap(string _server, string _user, string _password, bool _useSsl)
163: {
164: this.serverHost = _server;
165: this.serverUser = _user;
166: this.serverPassword = _password;
167: this.serverEnableSsl = _useSsl;
168:
169: defaultMailbox = "Inbox";
170: }
171:
172: ////////////////////////////////////////////////////////////////////////////
173:
174: /// <summary>
175: ///
176: /// </summary>
177: ~Imap()
178: {
179:
180: }
181:
182: ////////////////////////////////////////////////////////////////////////////
183:
184: /// <summary>
185: ///
186: /// </summary>
187: public List<string> MailboxList()
188: {
189: List<string> mailboxList;
190:
191: using (var imap = new Imap4Client())
192: {
193: if (serverEnableSsl) imap.ConnectSsl(serverHost);
194: else imap.Connect(serverHost);
195:
196: this.Log("Connect(): Connection opened to " + serverHost);
197:
198: imap.Login(serverUser, serverPassword);
199:
200: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
201:
202: mailboxList = new List<string>(imap.Mailboxes.Count);
203:
204: foreach (Mailbox mailbox in imap.Mailboxes) mailboxList.Add(mailbox.Name);
205:
206: if (imap.IsConnected) imap.Disconnect();
207: }
208:
209: return mailboxList;
210: }
211:
212: ////////////////////////////////////////////////////////////////////////////
213:
214: /// <summary>
215: ///
216: /// </summary>
217: public void CreateMailbox(string mailboxName)
218: {
219: using (var imap = new Imap4Client())
220: {
221: if (serverEnableSsl) imap.ConnectSsl(serverHost);
222: else imap.Connect(serverHost);
223:
224: this.Log("Connect(): Connection opened to " + serverHost);
225:
226: imap.Login(serverUser, serverPassword);
227:
228: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
229:
230: imap.CreateMailbox(mailboxName);
231:
232: if (imap.IsConnected) imap.Disconnect();
233: }
234: }
235:
236: ////////////////////////////////////////////////////////////////////////////
237:
238: /// <summary>
239: ///
240: /// </summary>
241: public string DeleteMailbox(string mailboxName)
242: {
243: string response;
244:
245: using (var imap = new Imap4Client())
246: {
247: if (serverEnableSsl) imap.ConnectSsl(serverHost);
248: else imap.Connect(serverHost);
249:
250: this.Log("Connect(): Connection opened to " + serverHost);
251:
252: imap.Login(serverUser, serverPassword);
253:
254: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
255:
256: response = imap.DeleteMailbox(mailboxName);
257:
258: if (imap.IsConnected) imap.Disconnect();
259: }
260:
261: return response;
262: }
263:
264: ////////////////////////////////////////////////////////////////////////////
265:
266: /// <summary>
267: ///
268: /// </summary>
269: public Header ReadHeader(Mailbox mailbox, int i)
270: {
271: var header = new Header();
272:
273: try
274: {
275: var aHeader = mailbox.Fetch.HeaderObject(i);
276:
277: header.MessageId = aHeader.MessageId;
278: header.From = aHeader.From.Email;
279: header.Subject = aHeader.Subject;
280:
281: this.Log(string.Format("Success: Header read: {0},{1},{2}", header.MessageId, header.From, header.Subject));
282: }
283: catch (Imap4Exception iex)
284: {
285: this.Log(string.Format("Imap4 Error: {0}", iex.Message));
286: }
287: catch (Exception ex)
288: {
289: this.Log(string.Format("Failed: {0}", ex.Message));
290: }
291: finally
292: {
293: }
294:
295: return header;
296: }
297:
298: ////////////////////////////////////////////////////////////////////////////
299:
300: /// <summary>
301: ///
302: /// </summary>
303: public int MoveMessagesFromEmailToMailbox(string email, string destinationMailboxName)
304: {
305: int numberOfMessagesMoved;
306: int[] messageOrdinalList;
307: string searchPhrase;
308: Mailbox mailbox;
309:
310: numberOfMessagesMoved = 0;
311:
312: using (var imap = new Imap4Client())
313: {
314: if (serverEnableSsl) imap.ConnectSsl(serverHost);
315: else imap.Connect(serverHost);
316:
317: this.Log("Connect(): Connection opened to " + serverHost);
318:
319: imap.Login(serverUser, serverPassword);
320:
321: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
322:
323: mailbox = imap.SelectMailbox(defaultMailbox);
324:
325: searchPhrase = @"FROM """ + email + @"""";
326:
327: messageOrdinalList = mailbox.Search(searchPhrase);
328:
329: if (messageOrdinalList != null && messageOrdinalList.Length > 0)
330: {
331: // read message and check that from-email value before moving
332: for (int i = messageOrdinalList.Length - 1; i >= 0; i--)
333: {
334: MoveMessage(mailbox, messageOrdinalList[i], destinationMailboxName);
335: numberOfMessagesMoved++;
336: }
337: }
338:
339: if (imap.IsConnected) imap.Disconnect();
340: }
341:
342: return numberOfMessagesMoved;
343: }
344:
345: ////////////////////////////////////////////////////////////////////////////
346:
347: /// <summary>
348: ///
349: /// </summary>
350: public void MoveMessage(string messageId, string destinationMailboxName)
351: {
352: int[] messageOrdinalList;
353: string searchPhrase;
354: Mailbox mailbox;
355: ActiveUp.Net.Mail.Header header;
356:
357: using (var imap = new Imap4Client())
358: {
359: if (serverEnableSsl) imap.ConnectSsl(serverHost);
360: else imap.Connect(serverHost);
361:
362: this.Log("Connect(): Connection opened to " + serverHost);
363:
364: imap.Login(serverUser, serverPassword);
365:
366: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
367:
368: mailbox = imap.SelectMailbox(defaultMailbox);
369:
370: searchPhrase = @"ALL";
371:
372: messageOrdinalList = mailbox.Search(searchPhrase);
373:
374: if (messageOrdinalList != null && messageOrdinalList.Length > 0)
375: {
376: for (int i = messageOrdinalList.Length - 1; i >= 0; i--)
377: {
378: header = mailbox.Fetch.HeaderObject(messageOrdinalList[i]);
379:
380: if (header.MessageId == messageId)
381: {
382: MoveMessage(mailbox, messageOrdinalList[i], destinationMailboxName);
383:
384: break;
385: }
386: }
387: }
388:
389: if (imap.IsConnected) imap.Disconnect();
390: }
391: }
392:
393: ////////////////////////////////////////////////////////////////////////////
394:
395: /// <summary>
396: ///
397: /// </summary>
398: public void MoveMessage(Mailbox mailbox, int messageOrdinal, string destinationMailboxName)
399: {
400: mailbox.MoveMessage(messageOrdinal, destinationMailboxName);
401:
402: this.Log("Move message: " + messageOrdinal + " to mailbox '" + destinationMailboxName + "'");
403: }
404:
405: ////////////////////////////////////////////////////////////////////////////
406:
407: /// <summary>
408: /// Message list from Inbox
409: /// </summary>
410: public void MessageList(out List<Message> messageList)
411: {
412: string searchPhrase;
413:
414: searchPhrase = "ALL";
415:
416: SearchPhraseMessageList(searchPhrase, out messageList);
417: }
418:
419: ////////////////////////////////////////////////////////////////////////////
420:
421: /// <summary>
422: /// List of messages from Inbox that were sent from email
423: /// </summary>
424: public void MessageList(string email, out List<Message> messageList)
425: {
426: string searchPhrase;
427:
428: searchPhrase = @"FROM """ + email + @"""";
429:
430: SearchPhraseMessageList(searchPhrase, out messageList);
431: }
432:
433: ////////////////////////////////////////////////////////////////////////////
434:
435: /// <summary>
436: ///
437: /// </summary>
438: private void SearchPhraseMessageList(string searchPhrase, out List<Message> messageList)
439: {
440: Message message;
441: Mailbox mailbox;
442: MessageCollection messageCollection;
443:
444: messageList = new List<Message>();
445:
446: using (var imap = new Imap4Client())
447: {
448: if (serverEnableSsl) imap.ConnectSsl(serverHost);
449: else imap.Connect(serverHost);
450:
451: this.Log("Connect(): Connection opened to " + serverHost);
452:
453: imap.Login(serverUser, serverPassword);
454:
455: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
456:
457: mailbox = imap.SelectMailbox(defaultMailbox);
458:
459: try
460: {
461: messageCollection = mailbox.SearchParse(searchPhrase);
462:
463: foreach (ActiveUp.Net.Mail.Message m in messageCollection)
464: {
465: message = new Message
466: {
467: MessageId = m.MessageId,
468: From = m.From.Email,
469: Subject = m.Subject,
470: BodyText = m.BodyText.TextStripped,
471: Date = m.Date,
472: ReceivedDate = m.ReceivedDate
473: };
474:
475: foreach (ActiveUp.Net.Mail.MimePart mp in m.Attachments)
476: {
477: //if (mp.IsText)
478: //{
479: message.Attachments.Add(new Attachment
480: {
481: FileName = mp.Filename,
482: ContentType = mp.ContentType.MimeType,
483: Content = mp.TextContent
484: });
485: //}
486: }
487:
488: messageList.Add(message);
489:
490: this.Log(string.Format("Success: Message read: {0},{1},{2}", m.MessageId, m.From, m.Subject));
491: }
492: }
493: catch (Imap4Exception iex)
494: {
495: this.Log(string.Format("Imap4 Error: {0}", iex.Message));
496: }
497: catch (Exception ex)
498: {
499: this.Log(string.Format("Failed: {0}", ex.Message));
500: }
501: finally
502: {
503: if (imap.IsConnected) imap.Disconnect();
504: }
505: }
506: }
507:
508: ////////////////////////////////////////////////////////////////////////////
509:
510: /// <summary>
511: ///
512: /// </summary>
513: public List<Header> HeaderList(Mailbox mailbox)
514: {
515: Header header;
516: List<Header> headerList;
517: ActiveUp.Net.Mail.Header aHeader;
518:
519: headerList = new List<Header>(mailbox.MessageCount);
520:
521: try
522: {
523: for (int i = 1; i <= mailbox.MessageCount; i++)
524: {
525: header = new Header();
526:
527: aHeader = mailbox.Fetch.MessageObject(i);
528:
529: header.MessageId = aHeader.MessageId;
530: header.From = aHeader.From.Email;
531: header.Subject = aHeader.Subject;
532:
533: this.Log(string.Format("Success: Header read: {0},{1},{2}", header.MessageId, header.From, header.Subject));
534: }
535: }
536: catch (Imap4Exception iex)
537: {
538: this.Log(string.Format("Imap4 Error: {0}", iex.Message));
539: }
540: catch (Exception ex)
541: {
542: this.Log(string.Format("Failed: {0}", ex.Message));
543: }
544: finally
545: {
546: }
547:
548: return headerList;
549: }
550:
551: ////////////////////////////////////////////////////////////////////////////
552:
553: /// <summary>
554: ///
555: /// </summary>
556: public void DeleteMessage(string messageId)
557: {
558: int[] messageOrdinalList;
559: string searchPhrase;
560: Mailbox mailbox;
561: ActiveUp.Net.Mail.Header header;
562:
563: using (var imap = new Imap4Client())
564: {
565: if (serverEnableSsl) imap.ConnectSsl(serverHost);
566: else imap.Connect(serverHost);
567:
568: this.Log("Connect(): Connection opened to " + serverHost);
569:
570: imap.Login(serverUser, serverPassword);
571:
572: this.Log(string.Format("Connect(): Login to '{0}' by user '{1}' successful", serverHost, serverUser));
573:
574: mailbox = imap.SelectMailbox(defaultMailbox);
575:
576: searchPhrase = @"ALL";
577:
578: messageOrdinalList = mailbox.Search(searchPhrase);
579:
580: if (messageOrdinalList != null && messageOrdinalList.Length > 0)
581: {
582: for (int i = messageOrdinalList.Length - 1; i >= 0; i--)
583: {
584: header = mailbox.Fetch.HeaderObject(messageOrdinalList[i]);
585:
586: if (header.MessageId == messageId)
587: {
588: DeleteMessage(mailbox, messageOrdinalList[i]);
589: }
590: }
591: }
592:
593: if (imap.IsConnected) imap.Disconnect();
594: }
595: }
596:
597: ////////////////////////////////////////////////////////////////////////////
598:
599: /// <summary>
600: ///
601: /// </summary>
602: private void DeleteMessage(Mailbox mailbox, int messageOrdinal)
603: {
604: mailbox.DeleteMessage(messageOrdinal, true);
605:
606: this.Log("Delete message: " + messageOrdinal);
607: }
608:
609: ////////////////////////////////////////////////////////////////////////////
610:
611: /// <summary>
612: ///
613: /// </summary>
614: private void Log(string text)
615: {
616: string line;
617: DateTime now;
618:
619: now = DateTime.UtcNow.AddHours(3);
620:
621: line = now.ToString("yyyy-MM-dd HH:mm:ss: ") + text;
622:
623: Console.WriteLine(line);
624: }
625:
626: ////////////////////////////////////////////////////////////////////////////
627: ////////////////////////////////////////////////////////////////////////////
628: }
629: }