/// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="server">Reference to owner relay server.</param>
        /// <param name="file">Message file to relay.</param>
        /// <param name="relay_retry">If true then first time relay, otherwise retry attempt.</param>
        public Relay_Session(Relay_Server server,string file,bool relay_retry)
        {
            m_pRelayServer = server;
            m_MessageFile  = file;
            m_relay_retry  = relay_retry;

            m_pMessageStream = File.Open(m_MessageFile,FileMode.Open,FileAccess.ReadWrite,FileShare.Read);
            m_pRelayInfo = new RelayInfo(m_pMessageStream,m_pRelayServer.UndeliveredAfter,m_pRelayServer.UndeliveredWarningAfter);
            m_SessionID = Guid.NewGuid().ToString();
            m_SessionStartTime = DateTime.Now;
            m_pSmtpClient = new SmtpClientEx();
            m_pSmtpClient.DnsServers = new string[]{m_pRelayServer.Dns1,m_pRelayServer.Dns2};
            if(m_pRelayServer.LogCommands){
                m_pSmtpClient.SessionLog += new LogEventHandler(OnSMTP_LogPart);
            }

            m_pConnectPoints = new Queue<IPAddress>();
        }
        /// <summary>
        /// Stops this virtual server.
        /// </summary>
        public void Stop()
        {
            m_Running = false;

            if(m_pSmtpServer != null){
                try{
                    m_pSmtpServer.Dispose();
                }
                catch{
                }
                m_pSmtpServer = null;
            }
            if(m_pPop3Server != null){
                try{
                    m_pPop3Server.Dispose();
                }
                catch{
                }
                m_pPop3Server = null;
            }
            if(m_pImapServer != null){
                try{
                    m_pImapServer.Dispose();
                }
                catch{
                }
                m_pImapServer = null;
            }
            if(m_pRelayServer != null){
                try{
                    m_pRelayServer.Dispose();
                }
                catch{
                }
                m_pRelayServer = null;
            }
            if(m_pFetchServer != null){
                try{
                    m_pFetchServer.Dispose();
                }
                catch{
                }
                m_pFetchServer = null;
            }
            if(m_pSipServer != null){
                try{
                    m_pSipServer.Stop();
                }
                catch{
                }
                m_pSipServer = null;
            }
            if(m_pTimer != null){
                try{
                    m_pTimer.Dispose();
                }
                catch{
                }
                m_pTimer = null;
            }
            if(m_pRecycleBinManager != null){
                try{
                    m_pRecycleBinManager.Dispose();
                }
                catch{
                }
                m_pRecycleBinManager = null;
            }
            if(m_pBadLoginManager != null){
                try{
                    m_pBadLoginManager.Dispose();
                }
                catch{
                }
                m_pBadLoginManager = null;
            }
        }
        /// <summary>
        /// Ends RelaySession, does clean up.
        /// </summary>
        /// <param name="sendOk">Specifies if message sent ok.</param>
        /// <param name="exception">If sendOk=false, then exception is filled with error info.</param>
        private void End(bool sendOk,Exception exception)
        {
            // This method may be called multiple times, if session timed out.  Just block it.
            lock(this){
                if(m_Ended){
                    return;
                }
                m_Ended = true;
            }

            try{
                // If exception and logging enabled, log exception.
                try{
                    if(m_pSmtpClient.SessionActiveLog != null && exception != null){
                        m_pSmtpClient.SessionActiveLog.AddTextEntry("Exception: " + exception.Message);
                    }
                }
                catch{
                    // FIX ME: this returns error here if smtp client not connected and exception, because
                    // no logger created yet.
                }

                if(sendOk){
                    Dispose();

                    // Message sended successfuly, may delete it
                    File.Delete(m_MessageFile);
                }
                else if(m_relay_retry){
                    Dispose();

                    // Move message to Retry folder.
                    string msgFileName = Path.GetFileName(m_MessageFile);
                    string retryFolder = API_Utlis.EnsureFolder(m_pRelayServer.VirtualServer.MailStorePath + "Retry");
                    File.Move(m_MessageFile,API_Utlis.PathFix(retryFolder + "\\" + msgFileName));
                }
                else if(!m_relay_retry){
                    string error     = exception.Message;
                    bool   permError = error.StartsWith("5"); // SMTP permanent errors 5xx

                    // If destination recipient is invalid or Undelivered Date Exceeded, try to return message to sender
                    if(permError || m_pRelayInfo.IsUndeliveredDateExceeded){
                        MakeUndeliveredNotify(m_pRelayInfo,error,m_pMessageStream);

                        Dispose();

                        // Undelivery note made, may delete message
                        if(m_pRelayInfo.From.Length > 0){
                            File.Delete(m_MessageFile);
                        }
                        // There isn't return address, can't send undelivery note
                        else if(m_pRelayServer.StoreUndeliveredMessages){
                            // Check if Directory exists, if not Create
                            if(!Directory.Exists(m_pRelayServer.VirtualServer.MailStorePath + "Undelivered\\")){
                                Directory.CreateDirectory(m_pRelayServer.VirtualServer.MailStorePath + "Undelivered\\");
                            }
                            File.Move(m_MessageFile,m_MessageFile.Replace("Retry","Undelivered"));
                        }
                    }
                    else if(m_pRelayInfo.MustSendWarning){
                        MakeUndeliveredWarning(m_pRelayInfo,error,m_pMessageStream);

                        byte[] mustSendWarningBit = System.Text.Encoding.ASCII.GetBytes("1");
                        m_pMessageStream.Position = m_pRelayInfo.WarningBitPos;
                        m_pMessageStream.Write(mustSendWarningBit,0,mustSendWarningBit.Length);

                        Dispose();
                    }

                    Dispose();
                }
            }
            catch(Exception x){
                Error.DumpError(x,new System.Diagnostics.StackTrace());
            }
            finally{
                m_pRelayServer.RemoveSession(this);
                m_pRelayServer = null;
            }
        }
        /// <summary>
        /// Starts this virtual server.
        /// </summary>
        public void Start()
        {
            if(m_Running){
                return;
            }
            m_Running = true;

            m_pSmtpServer = new SMTP_Server();
            m_pSmtpServer.AuthUser += new LumiSoft.Net.SMTP.Server.AuthUserEventHandler(this.Server_AuthenticateUser);
            m_pSmtpServer.SessionLog += new LumiSoft.Net.LogEventHandler(this.SMTP_Server_SessionLog);
            m_pSmtpServer.ValidateMailFrom += new LumiSoft.Net.SMTP.Server.ValidateMailFromHandler(this.smtp_Server_ValidateSender);
            m_pSmtpServer.SysError += new LumiSoft.Net.ErrorEventHandler(this.OnServer_SysError);
            m_pSmtpServer.GetMessageStoreStream += new GetMessageStoreStreamHandler(SMTP_Server_GetMessageStoreStream);
            m_pSmtpServer.MessageStoringCompleted += new MessageStoringCompletedHandler(SMTP_Server_MessageStoringCompleted);
            m_pSmtpServer.ValidateMailTo += new LumiSoft.Net.SMTP.Server.ValidateMailToHandler(this.smtp_Server_ValidateRecipient);
            m_pSmtpServer.ValidateMailboxSize += new LumiSoft.Net.SMTP.Server.ValidateMailboxSize(this.SMTP_Server_ValidateMailBoxSize);
            m_pSmtpServer.ValidateIPAddress += new LumiSoft.Net.ValidateIPHandler(this.SMTP_Server_ValidateIPAddress);

            m_pPop3Server = new POP3_Server();
            m_pPop3Server.GetTopLines += new LumiSoft.Net.POP3.Server.MessageHandler(this.POP3_Server_GetTopLines);
            m_pPop3Server.GetMessageStream += new GetMessageStreamHandler(POP3_Server_GetMessageStream);
            m_pPop3Server.DeleteMessage += new LumiSoft.Net.POP3.Server.MessageHandler(this.pop3_Server_DeleteMessage);
            m_pPop3Server.SysError += new LumiSoft.Net.ErrorEventHandler(this.OnServer_SysError);
            m_pPop3Server.AuthUser += new LumiSoft.Net.POP3.Server.AuthUserEventHandler(this.Server_AuthenticateUser);
            m_pPop3Server.GetMessgesList += new LumiSoft.Net.POP3.Server.GetMessagesInfoHandler(this.pop3_Server_GetMessgesList);
            m_pPop3Server.SessionLog += new LumiSoft.Net.LogEventHandler(this.POP3_Server_SessionLog);
            m_pPop3Server.ValidateIPAddress += new LumiSoft.Net.ValidateIPHandler(this.POP3_Server_ValidateIPAddress);

            m_pImapServer = new IMAP_Server();
            m_pImapServer.ValidateIPAddress += new LumiSoft.Net.ValidateIPHandler(this.IMAP_Server_ValidateIPAddress);
            m_pImapServer.SysError += new LumiSoft.Net.ErrorEventHandler(OnServer_SysError);
            m_pImapServer.AuthUser += new LumiSoft.Net.IMAP.Server.AuthUserEventHandler(IMAP_Server_AuthUser);
            m_pImapServer.GetSharedRootFolders += new SharedRootFoldersEventHandler(IMAP_Server_GetSharedRootFolders);
            m_pImapServer.GetFolders += new FoldersEventHandler(IMAP_Server_GetFolders);
            m_pImapServer.GetSubscribedFolders += new FoldersEventHandler(IMAP_Server_GetSubscribedFolders);
            m_pImapServer.SubscribeFolder += new FolderEventHandler(IMAP_Server_SubscribeFolder);
            m_pImapServer.UnSubscribeFolder += new FolderEventHandler(IMAP_Server_UnSubscribeFolder);
            m_pImapServer.CreateFolder += new FolderEventHandler(IMAP_Server_CreateFolder);
            m_pImapServer.DeleteFolder += new FolderEventHandler(IMAP_Server_DeleteFolder);
            m_pImapServer.RenameFolder += new FolderEventHandler(IMAP_Server_RenameFolder);
            m_pImapServer.GetMessagesInfo += new MessagesEventHandler(IMAP_Server_GetMessagesInfo);
            m_pImapServer.DeleteMessage += new MessageEventHandler(IMAP_Server_DeleteMessage);
            m_pImapServer.StoreMessage += new MessageEventHandler(IMAP_Server_StoreMessage);
            m_pImapServer.StoreMessageFlags += new MessageEventHandler(IMAP_Server_StoreMessageFlags);
            m_pImapServer.CopyMessage += new MessageEventHandler(IMAP_Server_CopyMessage);
            m_pImapServer.GetMessageItems += new MessagesItemsEventHandler(IMAP_Server_GetMessageItems);
            m_pImapServer.GetFolderACL += new GetFolderACLEventHandler(IMAP_Server_GetFolderACL);
            m_pImapServer.SetFolderACL += new SetFolderACLEventHandler(IMAP_Server_SetFolderACL);
            m_pImapServer.DeleteFolderACL += new DeleteFolderACLEventHandler(IMAP_Server_DeleteFolderACL);
            m_pImapServer.GetUserACL += new GetUserACLEventHandler(IMAP_Server_GetUserACL);
            m_pImapServer.GetUserQuota += new GetUserQuotaHandler(IMAP_Server_GetUserQuota);
            m_pImapServer.SessionLog += new LumiSoft.Net.LogEventHandler(this.IMAP_Server_SessionLog);

            m_pRelayServer = new Relay_Server(this);

            m_pFetchServer = new FetchPop3(this,m_pApi);

            m_pSipServer = new SIP_Stack();
            ((SIP_ProxyCore)m_pSipServer.SipCore).Authenticate += new SIP_AuthenticateEventHandler(m_pSipServer_Authenticate);
            ((SIP_ProxyCore)m_pSipServer.SipCore).IsLocalUri += new SIP_IsLocalUriEventHandler(m_pSipServer_IsLocalUri);
            ((SIP_ProxyCore)m_pSipServer.SipCore).AddressExists += new SIP_AddressExistsEventHandler(m_pSipServer_AddressExists);
            ((SIP_ProxyCore)m_pSipServer.SipCore).Registrar.CanRegister += new SIP_CanRegisterEventHandler(m_pSipServer_CanRegister);
            m_pSipServer.Error += new SIP_ErrorEventHandler(m_pSipServer_Error);

            m_pRecycleBinManager = new RecycleBinManager(m_pApi);

            m_pBadLoginManager = new BadLoginManager();

            m_pTimer = new System.Timers.Timer();
            m_pTimer.Interval = 15000;
            m_pTimer.Elapsed += new System.Timers.ElapsedEventHandler(m_pTimer_Elapsed);
            m_pTimer.Enabled = true;

            LoadSettings();
        }