public static string WaitForPassword(int TcpListerPort, FileLogger logger, string errorFilePath) { TcpListener server = null; string password = ""; bool exceptionFired = false; int ErrorCode = 0; SocketError SocketErrorCode = 0; try { IPAddress localAddr = IPAddress.Parse("127.0.0.1"); logger.Log("Creating new TcpListener ... "); server = new TcpListener(localAddr, TcpListerPort); logger.Log("TcpListener created"); // Start listening for client requests. logger.Log("Waiting too start TcpListener ... "); server.Start(); logger.Log("TcpListener started"); } catch (SocketException ex) { ErrorCode = ex.ErrorCode; SocketErrorCode = ex.SocketErrorCode; string errorText = String.Format("WaitForPassword: TcpListener Start Failed\nErrorCode: {0} ({1})\nMessage: {2}\n", Enum.GetName(typeof(SocketError), SocketErrorCode), SocketErrorCode, ex.Message); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, errorText); logger.Log("SocketException: ", ex.ToString()); exceptionFired = true; //System.Environment.Exit(1); // exit if finally } finally { // Stop listening for new clients. logger.Log("WaitForPassword: Executing finally", exceptionFired.ToString()); //server.Stop(); if (exceptionFired) { logger.Log("WaitForPassword: calling exit(XX)"); if (ErrorCode == (int)SocketError.AddressAlreadyInUse) { System.Environment.Exit(ExitCodes.ExitTcpPort); } else { System.Environment.Exit(ExitCodes.ExitTcpServer); } } } try { // Buffer for reading data Byte[] bytes = new Byte[1024]; String data = null; logger.Log("Waiting for a connection... "); // Perform a blocking call to accept requests. // You could also use server.AcceptSocket() here. TcpClient client = server.AcceptTcpClient(); logger.Log("Connected!"); data = null; // Get a stream object for reading and writing NetworkStream stream = client.GetStream(); logger.Log("Reading"); int i; while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) { // Translate data bytes to a ASCII string. data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); password = data; logger.Log("Received: ", data); // Process the data sent by the client. byte[] msg = System.Text.Encoding.ASCII.GetBytes(data); // Send back a response. //stream.Write(null, 0, msg.Length); stream.Write(msg, 0, msg.Length); logger.Log("Sent: ", data); break; } // Shutdown and end connection client.Close(); } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "WaitForPassword Failed\n", ex.Message); logger.Log("SocketException: ", ex.ToString()); exceptionFired = true; //System.Environment.Exit(1); // exit if finally } finally { // Stop listening for new clients. logger.Log("WaitForPassword: Executing finally", exceptionFired.ToString()); server.Stop(); if (exceptionFired) { logger.Log("WaitForPassword: calling exit(1)"); System.Environment.Exit(ExitCodes.ExitTcpServer); } } return(password); }
public static void Main(string[] args) { AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); string dataPath = GetLocalAppDataPath(); string MBoxViewerPath = Path.Combine(dataPath, "MBoxViewer"); string MailServicePath = Path.Combine(MBoxViewerPath, "MailService"); string TempPath = Path.Combine(MailServicePath, "Temp"); string okFilePath = MailServicePath + "\\ForwardMailSuccess.txt"; string errorFilePath = MailServicePath + "\\ForwardMailError.txt"; string errorFilePathOldInstance = MailServicePath + "\\ForwardMailError2.txt"; System.IO.DirectoryInfo info = Directory.CreateDirectory(TempPath); string loggerFilePath = FindKeyinArgs(args, "--logger-file"); var logger = new FileLogger(); logger.Open(loggerFilePath); logger.Log("Logger Open"); try { // File.Delete doesn't seem to generate exceptions if file doesn't exist //if (File.Exists(okFilePath) File.Delete(okFilePath); //if (File.Exists(errorFilePath) File.Delete(errorFilePath); File.Delete(errorFilePathOldInstance); } catch (Exception ex) { string txt = String.Format("Delete Critical Files Failed\n{0}\n{1}\n{2}\n\n{3}", okFilePath, errorFilePath, errorFilePathOldInstance, ex.Message); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, txt); logger.Log("Exception in Delete Critical Files: ", ex.ToString()); System.Environment.Exit(ExitCodes.ExitMailAddress); } int numArgs = args.GetLength(0); if ((numArgs <= 0) || ((numArgs % 2) != 0)) { string errorText = String.Format("Invalid command argument list: {0} .", String.Join(" ", args)); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, errorText + "\n"); logger.Log(errorText); System.Environment.Exit(ExitCodes.ExitCmdArguments); } /* * if (numArgs <= 0) * { * logger.Log(@"Usage: --from addr --to addr1,addr2,.. --cc addr1,addr2,.. -bcc addr1,addr2,.. * --user login-user-name --passwd --login-user-password --smtp smtp-server-name", ""); * Debug.Assert(true == false); * System.Environment.Exit(1); * } */ string instance = ""; IniFile smtpIni = null; EMailInfo mailInfo = new EMailInfo(); SMTPConfig smtpConfig = new SMTPConfig(); string smtpConfigFilePath = ""; string UserPassword = ""; string protocolLoggerFilePath = ""; int tcpListenPort = 0; logger.Log("Command line argument list:"); for (int j = 0, i = 0; j < numArgs; j = j + 2, i++) { string key = args[j]; string val = args[j + 1]; if (!key.StartsWith("--")) { string errorText = String.Format("Invalid key: {0} ", key); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, errorText + "\n"); logger.Log(errorText); System.Environment.Exit(ExitCodes.ExitCmdArguments); } if ((j + 1) >= numArgs) { string errorText = String.Format("Found key: {0} without value.", key); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, errorText + "\n"); logger.Log(errorText); System.Environment.Exit(ExitCodes.ExitCmdArguments); } if (key.CompareTo("--instance-id") == 0) { instance = val; } else if (key.CompareTo("--smtp-protocol-logger") == 0) { protocolLoggerFilePath = val; } else if (key.CompareTo("--from") == 0) { mailInfo.From = val; } else if (key.CompareTo("--to") == 0) { mailInfo.To = val; } else if (key.CompareTo("--cc") == 0) { mailInfo.CC = val; } else if (key.CompareTo("--bcc") == 0) { mailInfo.BCC = val; } else if (key.CompareTo("--user") == 0) { mailInfo.To = val; } else if (key.CompareTo("--passwd") == 0) { UserPassword = val; } else if (key.CompareTo("--smtp-cnf") == 0) { smtpConfigFilePath = val; } else if (key.CompareTo("--tcp-port") == 0) { tcpListenPort = int.Parse(val); } else if (key.CompareTo("--eml-file") == 0) { mailInfo.EmlFilePath = val; } else if (key.CompareTo("--mail-text-file") == 0) { mailInfo.TextFilePath = val; } else if (key.CompareTo("--logger-file") == 0) { ; // see FindKeyinArgs(args, "--logger-file"); } else { logger.Log(String.Format(" Unknown Key: {0} {1}", args[j], args[j + 1])); } logger.Log(String.Format(" {0} {1}", args[j], args[j + 1])); } if (smtpConfigFilePath.Length == 0) { string errorText = String.Format("required --smtp-cnf command line argument missing."); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, errorText + "\n"); logger.Log(errorText); System.Environment.Exit(ExitCodes.ExitCmdArguments); } if (!File.Exists(smtpConfigFilePath)) { string errorText = String.Format("SMTP configuration file {0} doesn't exist.", smtpConfigFilePath); bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, errorText + "\n"); logger.Log(errorText); System.Environment.Exit(ExitCodes.ExitCmdArguments); } try { if (protocolLoggerFilePath.Length > 0) { File.Delete(protocolLoggerFilePath); } } catch (Exception /*ex*/) {; } // ignore smtpIni = new IniFile(smtpConfigFilePath); string ActiveMailService = smtpIni.IniReadValue("MailService", "ActiveMailService"); smtpConfig.MailServiceName = smtpIni.IniReadValue(ActiveMailService, "MailServiceName"); smtpConfig.SmtpServerAddress = smtpIni.IniReadValue(ActiveMailService, "SmtpServerAddress"); smtpConfig.SmtpServerPort = int.Parse(smtpIni.IniReadValue(ActiveMailService, "SmtpServerPort")); smtpConfig.UserAccount = smtpIni.IniReadValue(ActiveMailService, "UserAccount"); if (UserPassword.Length > 0) { smtpConfig.UserPassword = UserPassword; } else { smtpConfig.UserPassword = smtpIni.IniReadValue(ActiveMailService, "UserPassword"); } smtpConfig.EncryptionType = int.Parse(smtpIni.IniReadValue(ActiveMailService, "EncryptionType")); logger.Log(smtpConfig.ToString()); // Uncomment when you exec this application from MBoxViewer //smtpConfig.UserPassword = ""; if (smtpConfig.UserPassword.Length == 0) { logger.Log("Waiting to receive password"); smtpConfig.UserPassword = WaitForPassword(tcpListenPort, logger, errorFilePath); if (smtpConfig.UserPassword.Length > 0) { logger.Log("Received non empty password"); //logger.Log("Received non empty password: "******"Received empty password"); } int found = smtpConfig.UserPassword.IndexOf(":"); if (found <= 0) { // Old instance , log to differnt file bool rval = FileUtils.CreateWriteCloseFile(errorFilePathOldInstance, "Received invalid id:password. Exitting\n"); System.Environment.Exit(ExitCodes.ExitCmdArguments); } string id = smtpConfig.UserPassword.Substring(0, found); string passwd = smtpConfig.UserPassword.Substring(found + 1); smtpConfig.UserPassword = passwd; logger.Log("Command line instance id: ", instance); logger.Log("Received instance id: ", id); //logger.Log("Received password: "******"Received password: "******"xxxxxxxxxxxx"); if (id.CompareTo(instance) != 0) { // Old instance , log to different file bool rval = FileUtils.CreateWriteCloseFile(errorFilePathOldInstance, "This is old instance. Exitting\n"); System.Environment.Exit(ExitCodes.ExitCmdArguments); } } MimeKit.ParserOptions opt = new MimeKit.ParserOptions(); var From = new MailboxAddress("", smtpConfig.UserAccount); // InternetAddressList CCList = new InternetAddressList(); InternetAddressList BCCList = new InternetAddressList(); InternetAddressList ToList = new InternetAddressList(); try { if (mailInfo.To.Length > 0) { ToList = MimeKit.InternetAddressList.Parse(opt, mailInfo.To); } if (mailInfo.CC.Length > 0) { CCList = MimeKit.InternetAddressList.Parse(opt, mailInfo.CC); } if (mailInfo.BCC.Length > 0) { BCCList = MimeKit.InternetAddressList.Parse(opt, mailInfo.BCC); } } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "Parsing Internet Address list Failed\n", ex.Message); logger.Log("Exception in InternetAddressList.Parse: ", ex.ToString()); System.Environment.Exit(ExitCodes.ExitMailAddress); } // string emlFilePath = mailInfo.EmlFilePath; // create the main textual body of the message var text = new TextPart("plain"); try { text.Text = File.ReadAllText(mailInfo.TextFilePath, Encoding.UTF8); } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "Building Mime Mesage Failed\n", ex.Message); logger.Log("Exception in Building Mime Message: ", ex.ToString()); System.Environment.Exit(ExitCodes.ExitMimeMessage); } logger.Log("Forwarding Eml file:", emlFilePath); MimeMessage msg = null; try { var message = new MimeMessage(); message = MimeKit.MimeMessage.Load(emlFilePath); List <MimeMessage> mimeMessages = new List <MimeMessage>(); mimeMessages.Add(message); msg = BuildMimeMessageWithEmlAsRFC822Attachment(text, mimeMessages, From, ToList, CCList, BCCList); } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "Building Mime Mesage Failed\n", ex.Message); logger.Log("Exception in Building Mime Message: ", ex.ToString()); System.Environment.Exit(ExitCodes.ExitMimeMessage); } logger.Log("BuildMimeMessageWithEmlAsRFC822Attachment Done"); //string msgAsString = MailkitConvert.ToString(msg); //string msgAsString = msg.ToString(); //logger.Log("\n", msgAsString); // OAUTH2 works on Google but requires verification by Google and it seems to be chargable option if number of users > 100 // Another problem is that ClientSecret can't be hardcoded in the application // For now we will just rely on User Account and User Password for authentication SaslMechanism oauth2 = null;; bool useOAUTH2 = false; if (useOAUTH2) { string appClientId = "xxxxxxxxxxxxxxxxxx.apps.googleusercontent.com"; string appClientSecret = "yyyyyyyyyyyyyyyyyyyyyyyyyyy"; var accessScopes = new[] { // that is the only scope that works per info from jstedfast "https://mail.google.com/", }; var clientSecrets = new ClientSecrets { ClientId = appClientId, ClientSecret = appClientSecret }; oauth2 = GetAuth2Token(smtpConfig.UserAccount, clientSecrets, accessScopes); } IProtocolLogger smtpProtocolLogger = null; if (protocolLoggerFilePath.Length > 0) { smtpProtocolLogger = new ProtocolLogger(protocolLoggerFilePath); } else { smtpProtocolLogger = new NullProtocolLogger(); } using (var client = new SmtpClient(smtpProtocolLogger)) { try { client.Connect(smtpConfig.SmtpServerAddress, smtpConfig.SmtpServerPort, (SecureSocketOptions)smtpConfig.EncryptionType); } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "Connect to SMTP Server Failed\n", ex.Message); logger.Log("Exception in Connect: ", ex.ToString()); System.Environment.Exit(ExitCodes.ExitConnect); } logger.Log(String.Format("Connected to {0} mail service", smtpConfig.MailServiceName)); try { if (useOAUTH2) { client.Authenticate(oauth2); } else { client.Authenticate(smtpConfig.UserAccount, smtpConfig.UserPassword); } } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "SMTP Authentication Failed\n", ex.Message); logger.Log("Exception in Authenticate: ", ex.ToString()); System.Environment.Exit(ExitCodes.ExitAuthenticate); } logger.Log("SMTP Authentication Succeeded"); // Clear smtpConfig.UserPassword in case it cores smtpConfig.UserPassword = ""; try { client.Send(msg); } catch (Exception ex) { bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "Send Failed\n", ex.Message); logger.Log("Exception in Send to SMTP Server: ", ex.ToString()); //string msgString = MailkitConvert.ToString(msg); //string msgAsString = msg.ToString(); // To help to investigate Warning place at the begining of the serialized MimeMessage // X - MimeKit - Warning: Do NOT use ToString() to serialize messages! Use one of the WriteTo() methods instead! //logger.Log("\n", msgString); System.Environment.Exit(ExitCodes.ExitSend); } string txt = "Mail Sending Succeeded"; logger.Log(txt); bool retval = FileUtils.CreateWriteCloseFile(okFilePath, txt); try { client.Disconnect(true); } catch (Exception ex) { // Ignore, not a fatal error //bool rval = FileUtils.CreateWriteCloseFile(errorFilePath, "Send Failed\n", ex.Message); logger.Log("Exception in Disconnect to SMTP Server: ", ex.ToString()); } logger.Log("SMTP Client Disconnected. All done."); } System.Environment.Exit(ExitCodes.ExitOk); }