This class implements SMTP client. Defined in RFC 5321.
Наследование: LumiSoft.Net.TCP.TCP_Client
Пример #1
0
        private static void startDelivery()
        {
            DirectoryInfo curdir = new DirectoryInfo(System.Environment.CurrentDirectory + @"\INBOUND\");

            FileInfo[] fileEntries = curdir.GetFiles("*.eml");

            //string[] fileEntries = Directory.GetFiles(System.Environment.CurrentDirectory + @"\INBOUND\","*.eml");
            foreach (FileInfo fileName in fileEntries)
            {
                DefaultLogger.Log.LogDebug("Filename: " + fileName.FullName);

                var eml = MsgReader.Mime.Message.Load(fileName);


                if (eml.Headers != null)
                {
                    if (eml.Headers.To != null)
                    {
                        foreach (var recipient in eml.Headers.To)
                        {
                            var to = recipient.Address;
                            DefaultLogger.Log.LogDebug("Mail to: " + to);

                            using (FileStream fs = new FileStream(fileName.FullName, FileMode.Open, FileAccess.Read))
                                using (LumiSoft.Net.SMTP.Client.SMTP_Client client =
                                           new LumiSoft.Net.SMTP.Client.SMTP_Client())
                                {
                                    var message = LumiSoft.Net.Mail.Mail_Message.ParseFromFile(fileName.FullName);


                                    //SMTP_Client.QuickSendSmartHost("localhost", "192.168.1.216", 25, false, "fakeuser", "fakepassword", message);
                                    SMTP_Client.QuickSendSmartHost("192.168.1.216", 26, false, message);
                                }
                        }
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Dns relay session constructor.
        /// </summary>
        /// <param name="server">Owner relay server.</param>
        /// <param name="localBindInfo">Local bind info.</param>
        /// <param name="realyItem">Relay item.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>server</b>,<b>localBindInfo</b> or <b>realyItem</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        internal Relay_Session(Relay_Server server,IPBindInfo localBindInfo,Relay_QueueItem realyItem)
        {
            if(server == null){
                throw new ArgumentNullException("server");
            }
            if(localBindInfo == null){
                throw new ArgumentNullException("localBindInfo");
            }
            if(realyItem == null){
                throw new ArgumentNullException("realyItem");
            }

            m_pServer        = server;
            m_pLocalBindInfo = localBindInfo;
            m_pRelayItem     = realyItem;

            m_SessionID         = Guid.NewGuid().ToString();
            m_SessionCreateTime = DateTime.Now;
            m_pTargets          = new List<Relay_Target>();
            m_pSmtpClient       = new SMTP_Client();

            m_pSmtpClient.BdatEnabled = false;
        }
Пример #3
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 4954 4. The AUTH Command.

                        AUTH mechanism [initial-response]

                        Arguments:
                            mechanism: A string identifying a [SASL] authentication mechanism.

                            initial-response: An optional initial client response.  If
                            present, this response MUST be encoded as described in Section
                            4 of [BASE64] or contain a single character "=".
                    */

                    if(m_pSASL.SupportsInitialResponse){
                        byte[] buffer = Encoding.UTF8.GetBytes("AUTH " + m_pSASL.Name + " " + Convert.ToBase64String(m_pSASL.Continue(null)) + "\r\n");

                        // Log
                        m_pSmtpClient.LogAddWrite(buffer.Length,Encoding.UTF8.GetString(buffer).TrimEnd());

                        // Start command sending.
                        m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.AuthCommandSendingCompleted,null);
                    }
                    else{
                        byte[] buffer = Encoding.UTF8.GetBytes("AUTH " + m_pSASL.Name + "\r\n");

                        // Log
                        m_pSmtpClient.LogAddWrite(buffer.Length,"AUTH " + m_pSASL.Name);

                        // Start command sending.
                        m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.AuthCommandSendingCompleted,null);
                    }
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #4
0
        /// <summary>
        /// Is called when STARTTLS command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void StartTlsCommandCompleted(SMTP_Client.StartTlsAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                else{
                    // Do EHLO/HELO.
                    SMTP_Client.EhloHeloAsyncOP ehloOP = new SMTP_Client.EhloHeloAsyncOP(null);
                    ehloOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.EhloHeloAsyncOP> e){
                        EhloCommandCompleted(ehloOP);
                    };
                    if(!m_pSmtpClient.EhloHeloAsync(ehloOP)){
                        EhloCommandCompleted(ehloOP);
                    }                    
                }                                
            }
            catch(Exception x){
                Dispose(x);
            }
        }
Пример #5
0
            /// <summary>
            /// Cleans up any resource being used.
            /// </summary>
            public void Dispose()
            {
                if(m_State == AsyncOP_State.Disposed){
                    return;
                }
                SetState(AsyncOP_State.Disposed);
                
                m_pException    = null;
                m_pCertCallback = null;
                m_pSmtpClient   = null;

                this.CompletedAsync = null;
            }
Пример #6
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                try{
                    SmartStream.ReadLineAsyncOP op = new SmartStream.ReadLineAsyncOP(new byte[8000],SizeExceededAction.JunkAndThrowException);
                    op.Completed += delegate(object s,EventArgs<SmartStream.ReadLineAsyncOP> e){   
                        try{
                            // Response reading completed.
                            if(!ReadLineCompleted(op)){
                                SetState(AsyncOP_State.Completed);                        
                                OnCompletedAsync();
                            }
                            // Continue response reading.
                            else{
                                while(owner.TcpStream.ReadLine(op,true)){
                                    // Response reading completed.
                                    if(!ReadLineCompleted(op)){
                                        SetState(AsyncOP_State.Completed);                        
                                        OnCompletedAsync();

                                        break;
                                    }
                                }
                            }
                        }
                        catch(Exception x){
                            m_pException = x;
                            SetState(AsyncOP_State.Completed);                        
                            OnCompletedAsync();
                        }
                    };
                    while(owner.TcpStream.ReadLine(op,true)){
                        // Response reading completed.
                        if(!ReadLineCompleted(op)){
                            SetState(AsyncOP_State.Completed);

                            return false;
                        }                        
                    }

                    return true;
                }
                catch(Exception x){
                    m_pException = x;
                    SetState(AsyncOP_State.Completed);

                    return false;
                }                
            }
Пример #7
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    // NOTE: At frist we try EHLO command, if it fails we fallback to HELO.

                    /* RFC 5321 4.1.1.1.
                        ehlo        = "EHLO" SP ( Domain / address-literal ) CRLF  
                     
                        ehlo-ok-rsp = ( "250" SP Domain [ SP ehlo-greet ] CRLF )
                                    / ( "250-" Domain [ SP ehlo-greet ] CRLF
                                     *( "250-" ehlo-line CRLF )
                                        "250" SP ehlo-line CRLF )
                    */

                    byte[] buffer = Encoding.UTF8.GetBytes("EHLO " + m_HostName + "\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,"EHLO " + m_HostName);

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.EhloCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + m_pException.Message,m_pException);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #8
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    // See if BDAT supported.
                    bool bdatSupported = false;
                    foreach(string feature in m_pSmtpClient.EsmtpFeatures){
                        if(feature.ToUpper() == SMTP_ServiceExtensions.CHUNKING){
                            bdatSupported = true;

                            break;
                        }
                    }
            
                    // BDAT.
                    if(bdatSupported && m_UseBdat){
                        /* RFC 3030 2.
                            bdat-cmd   ::= "BDAT" SP chunk-size [ SP end-marker ] CR LF
                            chunk-size ::= 1*DIGIT
                            end-marker ::= "LAST"
                        */

                        m_pBdatBuffer    = new byte[64000];
                        m_BdatSendBuffer = new byte[64100]; // 100 bytes for "BDAT xxxxxx...CRLF"

                        // Start reading message data-block.
                        m_pStream.BeginRead(m_pBdatBuffer,0,m_pBdatBuffer.Length,this.BdatChunkReadingCompleted,null);
                    }
                    // DATA.
                    else{
                        /* RFC 5321 4.1.1.4.
                            The mail data are terminated by a line containing only a period, that
                            is, the character sequence "<CRLF>.<CRLF>", where the first <CRLF> is
                            actually the terminator of the previous line.
                          
                            Examples:
			 		            C: DATA<CRLF>
			 		            S: 354 Start sending message, end with <crlf>.<crlf>.<CRLF>
			 		            C: send_message
			 		            C: .<CRLF>
                                S: 250 Ok<CRLF>
                        */

                        byte[] buffer = Encoding.UTF8.GetBytes("DATA\r\n");

                        // Log
                        m_pSmtpClient.LogAddWrite(buffer.Length,"DATA");

                        // Start command sending.
                        m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.DataCommandSendingCompleted,null);
                    }                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + m_pException.Message,m_pException);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #9
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 5321 4.1.1.3. RCPT.
                        rcpt = "RCPT TO:" ( "<Postmaster@" Domain ">" / "<Postmaster>" / Forward-path ) [SP Rcpt-parameters] CRLF

			            Examples:
			 		        RCPT TO:<*****@*****.**>
             
                        RFC 3461 adds NOTIFY and ORCPT parameters.
			        */

                    // Build command.
                    StringBuilder cmd = new StringBuilder();
                    cmd.Append("RCPT TO:<" + m_To + ">");            
                    if(m_DsnNotify == SMTP_DSN_Notify.NotSpecified){
                    }
                    else if(m_DsnNotify == SMTP_DSN_Notify.Never){
                        cmd.Append(" NOTIFY=NEVER");
                    }
                    else{
                        bool first = true;                
                        if((m_DsnNotify & SMTP_DSN_Notify.Delay) != 0){
                            cmd.Append(" NOTIFY=DELAY");
                            first = false;
                        }
                        if((m_DsnNotify & SMTP_DSN_Notify.Failure) != 0){
                            if(first){
                                cmd.Append(" NOTIFY=FAILURE");   
                            }
                            else{
                                cmd.Append(",FAILURE");
                            }
                            first = false;
                        }
                        if((m_DsnNotify & SMTP_DSN_Notify.Success) != 0){
                            if(first){
                                cmd.Append(" NOTIFY=SUCCESS");   
                            }
                            else{
                                cmd.Append(",SUCCESS");
                            }
                            first = false;
                        }
                    }
                    if(!string.IsNullOrEmpty(m_ORcpt)){
                        cmd.Append(" ORCPT=" + m_ORcpt);
                    }

                    byte[] buffer = Encoding.UTF8.GetBytes(cmd.ToString() + "\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,cmd.ToString());

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.RcptCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    if(m_pSmtpClient != null){
                        m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    }
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #10
0
        /// <summary>
        /// Is called when MAIL command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void MailCommandCompleted(SMTP_Client.MailFromAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                else{
                    SMTP_Client.RcptToAsyncOP rcptOP = new SMTP_Client.RcptToAsyncOP(
                        this.To,
                        IsDsnSupported() ? m_pRelayItem.DSN_Notify : SMTP_DSN_Notify.NotSpecified,
                        IsDsnSupported() ? m_pRelayItem.OriginalRecipient : null
                    );
                    rcptOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.RcptToAsyncOP> e){
                        RcptCommandCompleted(rcptOP);
                    };
                    if(!m_pSmtpClient.RcptToAsync(rcptOP)){
                        RcptCommandCompleted(rcptOP);
                    }
                }                                
            }
            catch(Exception x){
                Dispose(x);
            }
        }
Пример #11
0
        /// <summary>
        /// Is called when AUTH command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void AuthCommandCompleted(SMTP_Client.AuthAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                else{
                    long messageSize = -1;
                    try{
                        messageSize = m_pRelayItem.MessageStream.Length - m_pRelayItem.MessageStream.Position;
                    }
                    catch{
                        // Stream doesn't support seeking.
                    }

                    SMTP_Client.MailFromAsyncOP mailOP = new SMTP_Client.MailFromAsyncOP(
                        this.From,
                        messageSize,
                        IsDsnSupported() ? m_pRelayItem.DSN_Ret : SMTP_DSN_Ret.NotSpecified,
                        IsDsnSupported() ? m_pRelayItem.EnvelopeID : null
                    );
                    mailOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.MailFromAsyncOP> e){
                        MailCommandCompleted(mailOP);
                    };
                    if(!m_pSmtpClient.MailFromAsync(mailOP)){
                        MailCommandCompleted(mailOP);
                    }
                }                                
            }
            catch(Exception x){
                Dispose(x);
            }
        }
Пример #12
0
        /// <summary>
        /// Is called when STARTTLS command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void StartTlsCommandCompleted(SMTP_Client.StartTlsAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                else{
                    // Do EHLO/HELO.
                    string hostName = string.IsNullOrEmpty(m_pLocalBindInfo.HostName) ? Dns.GetHostName() : m_pLocalBindInfo.HostName;
                    SMTP_Client.EhloHeloAsyncOP ehloOP = new SMTP_Client.EhloHeloAsyncOP(hostName);
                    ehloOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.EhloHeloAsyncOP> e){
                        EhloCommandCompleted(ehloOP);
                    };
                    if(!m_pSmtpClient.EhloHeloAsync(ehloOP)){
                        EhloCommandCompleted(ehloOP);
                    }                    
                }                                
            }
            catch(Exception x){
                Dispose(x);
            }
        }
Пример #13
0
        /// <summary>
        /// Is called when EHLO/HELO command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void EhloCommandCompleted(SMTP_Client.EhloHeloAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                else{
                    // Start TLS requested, start switching to secure.
                    if(!m_pSmtpClient.IsSecureConnection && ((m_pServer.UseTlsIfPossible && IsTlsSupported()) || m_pActiveTarget.SslMode == SslMode.TLS)){
                        SMTP_Client.StartTlsAsyncOP startTlsOP = new SMTP_Client.StartTlsAsyncOP(null);
                        startTlsOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.StartTlsAsyncOP> e){
                            StartTlsCommandCompleted(startTlsOP);
                        };
                        if(!m_pSmtpClient.StartTlsAsync(startTlsOP)){
                            StartTlsCommandCompleted(startTlsOP);
                        }
                    }
                    // Authentication requested, start authenticating.
                    else if(!string.IsNullOrEmpty(m_pActiveTarget.UserName)){
                        SMTP_Client.AuthAsyncOP authOP = new SMTP_Client.AuthAsyncOP(m_pSmtpClient.AuthGetStrongestMethod(m_pActiveTarget.UserName,m_pActiveTarget.Password));                        
                        authOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.AuthAsyncOP> e){
                            AuthCommandCompleted(authOP);
                        };
                        if(!m_pSmtpClient.AuthAsync(authOP)){
                            AuthCommandCompleted(authOP);
                        }
                    }
                    // Start MAIL command.
                    else{
                        long messageSize = -1;
                        try{
                            messageSize = m_pRelayItem.MessageStream.Length - m_pRelayItem.MessageStream.Position;
                        }
                        catch{
                            // Stream doesn't support seeking.
                        }

                        SMTP_Client.MailFromAsyncOP mailOP = new SMTP_Client.MailFromAsyncOP(
                            this.From,
                            messageSize,
                            IsDsnSupported() ? m_pRelayItem.DSN_Ret : SMTP_DSN_Ret.NotSpecified,
                            IsDsnSupported() ? m_pRelayItem.EnvelopeID : null
                        );
                        mailOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.MailFromAsyncOP> e){
                            MailCommandCompleted(mailOP);
                        };
                        if(!m_pSmtpClient.MailFromAsync(mailOP)){
                            MailCommandCompleted(mailOP);
                        }
                    }
                }                                
            }
            catch(Exception x){
                Dispose(x);
            }
        }
Пример #14
0
 /// <summary>
 /// Completes relay session and does clean up. This method is thread-safe.
 /// </summary>
 /// <param name="exception">Exception happened or null if relay completed successfully.</param>
 public void Dispose(Exception exception)
 {
     try{
         lock(this){
             if(m_IsDisposed){
                 return;
             }
             try{
                 m_pServer.OnSessionCompleted(this,exception);
             }
             catch{
             }
             m_pServer.Sessions.Remove(this);
             m_IsDisposed = true;
                 
             m_pLocalBindInfo = null;
             m_pRelayItem = null;
             m_pSmartHosts = null;
             if(m_pSmtpClient != null){
                 m_pSmtpClient.Dispose();
                 m_pSmtpClient = null;
             }
             m_pTargets = null;
             if(m_pActiveTarget != null){
                 m_pServer.RemoveIpUsage(m_pActiveTarget.Target.Address);
                 m_pActiveTarget = null;
             }
             m_pServer = null;
         }
     }
     catch(Exception x){
         if(m_pServer != null){
             m_pServer.OnError(x);
         }
     }
 }
Пример #15
0
        /// <summary>
        /// Smart host relay session constructor.
        /// </summary>
        /// <param name="server">Owner relay server.</param>
        /// <param name="realyItem">Relay item.</param>
        /// <param name="smartHosts">Smart hosts.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>server</b>,<b>realyItem</b> or <b>smartHosts</b>is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        internal Relay_Session(Relay_Server server,Relay_QueueItem realyItem,Relay_SmartHost[] smartHosts)
        {
            if(server == null){
                throw new ArgumentNullException("server");
            }
            if(realyItem == null){
                throw new ArgumentNullException("realyItem");
            }
            if(smartHosts == null){
                throw new ArgumentNullException("smartHosts");
            }

            m_pServer     = server;
            m_pRelayItem  = realyItem;
            m_pSmartHosts = smartHosts;
                        
            m_RelayMode         = Relay_Mode.SmartHost;
            m_SessionID         = Guid.NewGuid().ToString();
            m_SessionCreateTime = DateTime.Now;
            m_pTargets          = new List<Relay_Target>();
            m_pSmtpClient       = new SMTP_Client();
        }
Пример #16
0
            /// <summary>
            /// Cleans up any resources being used.
            /// </summary>
            public void Dispose()
            {
                if(m_State == AsyncOP_State.Disposed){
                    return;
                }
                SetState(AsyncOP_State.Disposed);
                
                m_pException  = null;
                m_MailFrom    = null;
                m_EnvID       = null;
                m_pSmtpClient = null;

                this.CompletedAsync = null;
            }
Пример #17
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 5321 4.1.1.2. MAIL
			            mail         = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF
                        Reverse-path = Path / "<>"
                        Path         = "<" [ A-d-l ":" ] Mailbox ">"

			  
			           RFC 1870 adds optional SIZE keyword support.
			                SIZE keyword may only be used if it's reported in EHLO command response.
			 	        Examples:
			 		        MAIL FROM:<*****@*****.**> SIZE=1000
             
                       RFC 3461 adds RET and ENVID paramters.
			        */

                    bool isSizeSupported = false;
                    foreach(string feature in m_pSmtpClient.EsmtpFeatures){
                        if(feature.ToLower().StartsWith("size ")){
                            isSizeSupported = true;

                            break;
                        }
                    }

                    // Build command.
                    StringBuilder cmd = new StringBuilder();
                    cmd.Append("MAIL FROM:<" + m_MailFrom + ">");
                    if(isSizeSupported && m_MessageSize > 0){
                        cmd.Append(" SIZE=" + m_MessageSize.ToString());
                    }
                    if(m_DsnRet == SMTP_DSN_Ret.FullMessage){
                        cmd.Append(" RET=FULL");
                    }
                    else if(m_DsnRet == SMTP_DSN_Ret.Headers){
                        cmd.Append(" RET=HDRS");
                    }
                    if(!string.IsNullOrEmpty(m_EnvID)){
                        cmd.Append(" ENVID=" + m_EnvID);
                    }

                    byte[] buffer = Encoding.UTF8.GetBytes(cmd.ToString() + "\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,cmd.ToString());

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.MailCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #18
0
        /// <summary>
        /// Is called when RCPT command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void RcptCommandCompleted(SMTP_Client.RcptToAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                else{
                    // Start sending message.
                    SMTP_Client.SendMessageAsyncOP sendMsgOP = new SMTP_Client.SendMessageAsyncOP(m_pRelayItem.MessageStream,false);
                    sendMsgOP.CompletedAsync += delegate(object s,EventArgs<SMTP_Client.SendMessageAsyncOP> e){
                        MessageSendingCompleted(sendMsgOP);
                    };
                    if(!m_pSmtpClient.SendMessageAsync(sendMsgOP)){
                        MessageSendingCompleted(sendMsgOP);
                    }
                }                                
            }
            catch(Exception x){
                Dispose(x);
            }
        }
Пример #19
0
            /// <summary>
            /// Cleans up any resources being used.
            /// </summary>
            public void Dispose()
            {
                if(m_State == AsyncOP_State.Disposed){
                    return;
                }
                SetState(AsyncOP_State.Disposed);
                
                m_pException     = null;
                m_pStream        = null;
                m_pSmtpClient    = null;
                m_pBdatBuffer    = null;
                m_BdatSendBuffer = null;

                this.CompletedAsync = null;
            }
Пример #20
0
        /// <summary>
        /// Is called when message sending has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void MessageSendingCompleted(SMTP_Client.SendMessageAsyncOP op)
        {
            if(op == null){
                throw new ArgumentNullException("op");
            }

            try{
                if(op.Error != null){
                    Dispose(op.Error);
                }
                // Message sent sucessfully.
                else{
                    Dispose(null);
                }
            }
            catch(Exception x){
                Dispose(x);
            }

            op.Dispose();
        }
Пример #21
0
            /// <summary>
            /// Cleans up any resource being used.
            /// </summary>
            public void Dispose()
            {
                if(m_State == AsyncOP_State.Disposed){
                    return;
                }
                SetState(AsyncOP_State.Disposed);
                
                m_pException  = null;
                m_HostName    = null;
                m_pSmtpClient = null;
                m_pReplyLines = null;

                this.CompletedAsync = null;
            }
Пример #22
0
        private void RelayMessage()
        {
            try
            {
                if(!m_RelayTable.Contains(Thread.CurrentThread)){
                    SCore.WriteLog(m_pServer.m_SartUpPath + "mailServiceError.log","RelayMails: params missing");
                    return;
                }

                string messageFile = m_RelayTable[Thread.CurrentThread].ToString();

                bool sendOk = false;
                using(FileStream fs = File.Open(messageFile,FileMode.Open,FileAccess.ReadWrite)){
                    // Get relay info
                    RelayInfo relayInf = new RelayInfo(fs,1,1);

                    string from = relayInf.From;
                    if(from.Length == 0){
                        from = relayInf.To;
                    }

                    SMTP_Client smtpClnt  = new SMTP_Client();
                    smtpClnt.UseSmartHost = UseSmartHost;
                    smtpClnt.SmartHost    = SmartHost;
                    smtpClnt.DnsServers   = new string[]{Dns1,Dns2};
                    sendOk = smtpClnt.Send(new string[]{relayInf.To},from,fs);
                }

                if(sendOk){
                    // Message sended successfuly, may delete it
                    File.Delete(messageFile);
                }
                // send failed
                else{
                    // Move message to Retry folder
                    string msgFileName = Path.GetFileName(messageFile);
                    File.Move(messageFile,m_pServer.m_MailStorePath + "Retry\\" + msgFileName);
                }
            }
            catch(Exception x){
                if(!(x is IOException)){
                    Error.DumpError(x,new System.Diagnostics.StackTrace());
                }
            }
            finally{
                RemoveThread(Thread.CurrentThread);
            }
        }
Пример #23
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 5321 4.1.1.9.
                        noop = "NOOP" [ SP String ] CRLF
                    */

                    byte[] buffer = Encoding.UTF8.GetBytes("NOOP\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,"NOOP");

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.NoopCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #24
0
        private void SendRetryMail()
        {
            try
            {
                if(!m_RelayTable.Contains(Thread.CurrentThread)){
                    SCore.WriteLog(m_pServer.m_SartUpPath + "mailServiceError.log","SendRetryMail: params missing");
                    return;
                }

                string messageFile = m_RelayTable[Thread.CurrentThread].ToString();

                using(FileStream fs = File.Open(messageFile,FileMode.Open,FileAccess.ReadWrite)){
                    // Get relay info
                    RelayInfo relayInf = new RelayInfo(fs,RelayUndelivered,RelayUndelWarning);

                    string from = relayInf.From;
                    if(from.Length == 0){
                        from = relayInf.To;
                    }

                    SMTP_Client smtpClnt  = new SMTP_Client();
                    smtpClnt.UseSmartHost = UseSmartHost;
                    smtpClnt.SmartHost    = SmartHost;
                    smtpClnt.DnsServers   = new string[]{Dns1,Dns2};
                    if(smtpClnt.Send(new string[]{relayInf.To},from,fs)){
                        fs.Close();
                        // Message sended successfuly, may delete it
                        File.Delete(messageFile);
                    }
                    // send failed
                    else{
                        string error = smtpClnt.Errors[0].ErrorText;

                        // If destination recipient is invalid or Undelivered Date Exceeded, try to return message to sender
                        if(smtpClnt.Errors[0].ErrorType != SMTP_ErrorType.UnKnown || relayInf.IsUndeliveredDateExceeded){
                            MakeUndeliveredNotify(relayInf,error,fs);
                            fs.Close();

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

                            byte[] mustSendWarningBit = System.Text.Encoding.ASCII.GetBytes("1");
                            fs.Position = relayInf.WarningBitPos;
                            fs.Write(mustSendWarningBit,0,mustSendWarningBit.Length);
                        }
                    }
                }
            }
            catch(Exception x){
                if(!(x is IOException)){
                    Error.DumpError(x,new System.Diagnostics.StackTrace());
                }
            }
            finally{
                RemoveThread(Thread.CurrentThread);
            }
        }
Пример #25
0
        /// <summary>
        /// Sends message by using specified smart host.
        /// </summary>
        /// <param name="localHost">Host name which is reported to SMTP server.</param>
        /// <param name="host">Host name or IP address.</param>
        /// <param name="port">Host port.</param>
        /// <param name="ssl">Specifies if connected via SSL.</param>
        /// <param name="userName">SMTP server user name. This value may be null, then authentication not used.</param>
        /// <param name="password">SMTP server password.</param>
        /// <param name="from">Sender email what is reported to SMTP server.</param>
        /// <param name="to">Recipients email addresses.</param>
        /// <param name="message">Raw message to send.</param>
        /// <exception cref="ArgumentNullException">Is raised when argument <b>host</b>,<b>from</b>,<b>to</b> or <b>stream</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the method arguments has invalid value.</exception>
        /// <exception cref="SMTP_ClientException">Is raised when SMTP server returns error.</exception>
        public static void QuickSendSmartHost(string localHost,string host,int port,bool ssl,string userName,string password,string from,string[] to,Stream message)
        {
            if(host == null){
                throw new ArgumentNullException("host");
            }
            if(host == ""){
                throw new ArgumentException("Argument 'host' value may not be empty.");
            }
            if(port < 1){
                throw new ArgumentException("Argument 'port' value must be >= 1.");
            }
            if(from == null){
                throw new ArgumentNullException("from");
            }
            if(from != "" && !SMTP_Utils.IsValidAddress(from)){
                throw new ArgumentException("Argument 'from' has invalid value.");
            }
            if(to == null){
                throw new ArgumentNullException("to");
            }
            if(to.Length == 0){
                throw new ArgumentException("Argument 'to' must contain at least 1 recipient.");
            }
            foreach(string t in to){
                if(!SMTP_Utils.IsValidAddress(t)){
                    throw new ArgumentException("Argument 'to' has invalid value '" + t + "'.");
                }
            }
            if(message == null){
                throw new ArgumentNullException("message");
            }

            using(SMTP_Client smtp = new SMTP_Client()){
                smtp.Connect(host,port,ssl);                
                smtp.EhloHelo(localHost != null ? localHost : Dns.GetHostName());
                if(!string.IsNullOrEmpty(userName)){
                    smtp.Auth(smtp.AuthGetStrongestMethod(userName,password));
                }
                smtp.MailFrom(from,-1);
                foreach(string t in to){
                    smtp.RcptTo(t);
                }
                smtp.SendMessage(message);
            }
        }
Пример #26
0
        public void Send(ChannelMessage message)
        {
            var creds = CredentialsProvider.GetCredentials().ToNetworkCredential();

            Mail_Message msg = new Mail_Message();

            msg.MimeVersion = "1.0";
            msg.MessageID = MIME_Utils.CreateMessageID();
            msg.Subject = message.Context;
            msg.From = message.From.ToMailBoxList();
            msg.ReplyTo = message.ReturnTo == null ?
                message.From.ToAddressList() : message.ReturnTo.ToAddressList();

            if (String.IsNullOrEmpty(message.InReplyTo) == false)
                msg.InReplyTo = message.InReplyTo;

            msg.To = new Mail_t_AddressList();
            foreach (var address in message.To)
                msg.To.Add(address.ToMailBox());

            msg.Cc = new Mail_t_AddressList();
            foreach (var address in message.CC)
                msg.Cc.Add(address.ToMailBox());

            //--- multipart/mixed -------------------------------------------------------------------------------------------------
            MIME_h_ContentType contentType_multipartMixed = new MIME_h_ContentType(MIME_MediaTypes.Multipart.mixed);
            contentType_multipartMixed.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
            MIME_b_MultipartMixed multipartMixed = new MIME_b_MultipartMixed(contentType_multipartMixed);
            msg.Body = multipartMixed;

            //--- multipart/alternative -----------------------------------------------------------------------------------------
            MIME_Entity entity_multipartAlternative = new MIME_Entity();
            MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
            contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
            MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
            entity_multipartAlternative.Body = multipartAlternative;
            multipartMixed.BodyParts.Add(entity_multipartAlternative);

            //--- text/plain ----------------------------------------------------------------------------------------------------
            MIME_Entity entity_text_plain = new MIME_Entity();
            MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
            entity_text_plain.Body = text_plain;
            // Add text body if there is any
            if (message.BodyText != null && message.BodyText.Length > 0)
            {
                var bodyText = message.BodyText.ReadString();

                // Make sure there is a newline at the end of our text, otherwise it will screw up
                // our multipart data format
                if (!bodyText.EndsWith(Environment.NewLine))
                    bodyText = bodyText + Environment.NewLine;

                text_plain.SetText(MIME_TransferEncodings.SevenBit, Encoding.UTF8, bodyText);
            }

            multipartAlternative.BodyParts.Add(entity_text_plain);

            //--- text/html ------------------------------------------------------------------------------------------------------
            MIME_Entity entity_text_html = new MIME_Entity();
            MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
            entity_text_html.Body = text_html;
            if (message.BodyHtml != null && message.BodyHtml.Length > 0)
            {
                var bodyHtml = message.BodyHtml.ReadString();

                // Make sure there is a newline at the end of our text, otherwise it will screw up
                // our multipart data format
                if (!bodyHtml.EndsWith(Environment.NewLine))
                    bodyHtml = bodyHtml + Environment.NewLine;

                text_html.SetText(MIME_TransferEncodings.SevenBit, Encoding.UTF8, bodyHtml);
            }

            multipartAlternative.BodyParts.Add(entity_text_html);

            foreach (var channelAttachment in message.Attachments)
            {
                MIME_b_Application attachmentBody = new MIME_b_Application(MIME_MediaTypes.Application.octet_stream);
                MIME_Entity attachment = new MIME_Entity();
                attachment.Body = attachmentBody;

                // Has to happen before the following lines of code
                multipartMixed.BodyParts.Add(attachment);

                attachment.ContentType = new MIME_h_ContentType(MimeHelper.GetMimeType(channelAttachment.Filename));
                attachment.ContentType.Param_Name = channelAttachment.Filename;

                MIME_h_ContentDisposition contentDisposition = new MIME_h_ContentDisposition(DispositionTypeNames.Attachment);
                contentDisposition.Param_FileName = channelAttachment.Filename;

                attachment.ContentDisposition = contentDisposition;
                attachment.ContentTransferEncoding = TransferEncoding.Base64.ToString();

                attachmentBody.SetData(channelAttachment.ContentStream, MIME_TransferEncodings.Base64);
            }

            // Inject headers
            if (!String.IsNullOrEmpty(message.MessageIdentifier))
                msg.Header.Add(new MIME_h_Unstructured("x-i2mp-messageid", message.MessageIdentifier));

            //if (!String.IsNullOrEmpty(message.Metadata.i2mpFlow))
            //    msg.Header.Add(new MIME_h_Unstructured("x-i2mp-flow", message.Metadata.i2mpFlow));

            //if (!String.IsNullOrEmpty(message.Metadata.i2mpReference))
            //    mailMessage.Headers.Add("X-i2mp-ref", message.Metadata.i2mpReference);

            //if (!String.IsNullOrEmpty(message.Metadata.i2mpSequence))
            //    mailMessage.Headers.Add("X-i2mp-seq", message.Metadata.i2mpSequence);

            //if (!String.IsNullOrEmpty(message.Metadata.i2mpRelation))
            //    mailMessage.Headers.Add("X-i2mp-rel", message.Metadata.i2mpRelation);

            //if (!String.IsNullOrEmpty(message.Metadata.i2mpRelationId))
            //    mailMessage.Headers.Add("X-i2mp-rel-id", message.Metadata.i2mpRelationId);

            // Send message
            try
            {
                SMTP_Client client = new SMTP_Client();

                if ("/Settings/Channels/LoggerEnabled".AsKey(false))
                    client.Logger = new LumiSoft.Net.Log.Logger();

                // todo push this logic into the smtp client implementation itself
                if (Hostname == "smtp.live.com")
                {
                    // Hack for hotmail, first do a connect with no secured channel,
                    // then a STARTTLS
                    client.Connect(Hostname, Port, false);
                    client.StartTLS();
                }
                else
                {
                    client.Connect(Hostname, Port, IsSecured);
                }

                client.Authenticate(creds.UserName, creds.Password);

                using (MemoryStream ms = new MemoryStream())
                {
                    client.MailFrom(msg.From[0].Address, -1);

                    msg.ToStream(ms,
                        new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8);

                    // Reset stream
                    ms.Seek(0, SeekOrigin.Begin);

                    foreach (var address in message.To)
                        client.RcptTo(address.Address);

                    foreach (var address in message.CC)
                        client.RcptTo(address.Address);

                    foreach (var address in message.BCC)
                        client.RcptTo(address.Address);

                    try
                    {
                        client.SendMessage(ms);
                    }
                    finally
                    {
                        client.Dispose();
                    }
                }
            }
            catch(SmtpFailedRecipientsException e)
            {
                throw new ChannelFunctionalException(e.Message, e) { DoNotRetry = true };
            }
            catch (SmtpException e)
            {
                throw new ChannelFunctionalException(e.Message, e);
            }
            catch (Exception e)
            {
                throw new ChannelFunctionalException(e.Message, e);
            }
        }
Пример #27
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 3207 4.
                        The format for the STARTTLS command is:

                        STARTTLS

                        with no parameters.

                        After the client gives the STARTTLS command, the server responds with
                        one of the following reply codes:

                        220 Ready to start TLS
                        501 Syntax error (no parameters allowed)
                        454 TLS not available due to temporary reason
                    */

                    byte[] buffer = Encoding.UTF8.GetBytes("STARTTLS\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,"STARTTLS");

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.StartTlsCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Пример #28
-1
        public void TestMethod1()
        {
            try
            {
                                
                Mime mime = Mime.Parse(@"C:\Users\sanghyuk\Desktop\messages\[사내] 신규 모바일 FPS _Gunpie Adventure_ OPEN!!!.eml");

                Mail_Message message = Mail_Message.ParseFromFile(@"C:\Users\sanghyuk\Desktop\messages\[사내] 신규 모바일 FPS _Gunpie Adventure_ OPEN!!!.eml");
                Guid guid = Guid.NewGuid();
                string messageID = string.Format("<{0}@AutoGenerated.com>", guid.ToString().Split('-', '_'));
                message.MessageID = messageID; 
                message.To.Clear();
                Mail_t_Mailbox address = new Mail_t_Mailbox(string.Empty, "*****@*****.**");
                message.To.Add(address);
                               

                SMTP_Client client = new SMTP_Client();


                SMTP_Client.QuickSendSmartHost("mail.nexon.co.kr", 25, false, message);
                
                

                
                
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }