| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- using System.Net.Security;
- using System.Net.Sockets;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace MailFromWho
- {
- internal class Imap
- {
- #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
- private static StreamWriter _sw;
- private static TcpClient _tcpc;
- private static SslStream _ssl;
- #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
- private readonly Settings _settings;
- public Imap(Settings settings)
- {
- _settings = settings;
- }
- internal void GetAllAddresses()
- {
- try
- {
- var path = Environment.CurrentDirectory + $"{Path.DirectorySeparatorChar}{_settings.IntermediateFile}";
- var username = _settings.UserName;
- var imapServer = _settings.ImapServer;
- var sslPort = _settings.SslPort;
- var password = string.Empty;
- while (string.IsNullOrEmpty(password))
- {
- Console.Write($"Enter password of '{username}' @ '{imapServer}': ");
- var fgColour = Console.ForegroundColor;
- Console.ForegroundColor = Console.BackgroundColor;
- password = Console.ReadLine();
- Console.ForegroundColor = fgColour;
- }
- if (System.IO.File.Exists(path))
- {
- System.IO.File.Delete(path);
- }
- _sw = new System.IO.StreamWriter(System.IO.File.Create(path));
- // there should be no gap between the imap command and the \r\n
- // ssl.read() -- while ssl.readbyte!= eof does not work because there is no eof from server
- // cannot check for \r\n because in case of larger response from server ex:read email message
- // there are lot of lines so \r \n appears at the end of each line
- //ssl.timeout sets the underlying tcp connections timeout if the read or write
- //time out exceeds then the undelying connection is closed
- _tcpc = new System.Net.Sockets.TcpClient(imapServer, sslPort);
- _ssl = new System.Net.Security.SslStream(_tcpc.GetStream());
- _ssl.ReadTimeout = 200;
- _ssl.AuthenticateAsClient(imapServer);
- receiveResponse();
- sendRequest("$ LOGIN " + username + " " + password + "\r\n");
- receiveResponse();
- // Get all folders
- sendRequest("$ LIST " + "\"\"" + " \"*\"" + "\r\n");
- var foldersRaw = receiveResponse();
- var matches = Regex.Matches(foldersRaw, @"\s(INBOX.*?)\r\n");
- var folders = new List<string>();
- foreach (Match match in matches)
- {
- folders.Add(match.Groups[1].Value.Replace("\"", ""));
- }
- foreach (var folder in folders)
- {
- sendRequest($"$ SELECT \"{folder}\"\r\n");
- receiveResponse();
- sendRequest($"$ STATUS \"{folder}\" (MESSAGES)\r\n");
- var statusRaw = receiveResponse();
- var regex = new Regex(@"MESSAGES.(\d+)");
- var aantalBerichten = int.Parse(regex.Match(statusRaw).Groups[1].Value);
- var outputStr = $"FOLDER {folder} heeft {aantalBerichten} berichten";
- WriteOutput(outputStr, true);
- sendRequest("$ FETCH 1:* body[header.fields (from)]\r\n");
- var fromRaw = receiveResponse();
- // From: "flypacificblue.com" <reservations@flypacificblue.com>
- //matches = Regex.Matches(fromRaw, "From:\\s\\\"?(.[^\"]*?)\\\"?\\<(.*)\\>\r\n");
- matches = Regex.Matches(fromRaw, @"From:\s(.*)\r\n");
- var froms = new List<string>();
- foreach (Match match in matches)
- {
- var addressLine = match.Groups[1].Value;
- froms.Add(addressLine);
- WriteOutput(addressLine, true);
- }
- WriteOutput("", true);
- }
- receiveResponse();
- sendRequest("$ LOGOUT\r\n");
- receiveResponse();
- }
- catch (Exception ex)
- {
- Console.WriteLine("error: " + ex.Message);
- }
- finally
- {
- if (_sw != null)
- {
- _sw.WriteLine("");
- _sw.Close();
- _sw.Dispose();
- }
- if (_ssl != null)
- {
- _ssl.Close();
- _ssl.Dispose();
- }
- if (_tcpc != null)
- {
- _tcpc.Close();
- }
- }
- }
- private void WriteOutput(string outputStr, bool newline)
- {
- Console.Write(outputStr);
- _sw.Write(outputStr);
- if (newline)
- {
- Console.WriteLine("");
- _sw.WriteLine("");
- }
- }
- private void sendRequest(string command)
- {
- byte[] dummy;
- try
- {
- if (command != "")
- {
- if (_tcpc.Connected)
- {
- dummy = Encoding.ASCII.GetBytes(command);
- _ssl.Write(dummy, 0, dummy.Length);
- }
- else
- {
- throw new ApplicationException("TCP CONNECTION DISCONNECTED");
- }
- }
- _ssl.Flush();
- }
- catch (Exception ex)
- {
- throw new ApplicationException(ex.Message);
- }
- }
- private string receiveResponse()
- {
- var sb = new StringBuilder();
- byte[] buffer;
- try
- {
- var bytes = 0;
- // First wait for some data, but not too long...
- var waitTime = DateTime.Now.AddMilliseconds(200);
- while (bytes <= 0 && DateTime.Now < waitTime)
- {
- try
- {
- buffer = new byte[2048];
- bytes = _ssl.Read(buffer, 0, 2048);
- sb.Append(ReturnCleanASCII(Encoding.ASCII.GetString(buffer, 0, bytes)));
- }
- catch (IOException)
- {
- bytes = -1;
- }
- }
- while (bytes > 0)
- {
- try
- {
- buffer = new byte[2048];
- bytes = _ssl.Read(buffer, 0, 2048);
- sb.Append(ReturnCleanASCII(Encoding.ASCII.GetString(buffer, 0, bytes)));
- }
- catch (IOException)
- {
- bytes = -1;
- }
- }
- }
- catch (Exception ex)
- {
- throw new ApplicationException(ex.Message);
- }
- return sb.ToString();
- }
- private string ReturnCleanASCII(string s)
- {
- StringBuilder sb = new StringBuilder(s.Length);
- foreach (char c in s)
- {
- int i = (int)c;
- if (i > 127) // you probably don't want 127 either
- continue;
- if (i < 32 && (i != 10 && i != 13)) // I bet you don't want control characters
- continue;
- sb.Append(c);
- }
- return sb.ToString();
- }
- }
- }
|