Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }