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); } } } } } }
/// <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; }
/// <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; } }
/// <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); } }
/// <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; }
/// <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; } }
/// <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; } }
/// <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; } }
/// <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; } }
/// <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); } }
/// <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); } }
/// <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); } }
/// <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); } }
/// <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); } } }
/// <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(); }
/// <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; }
/// <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; } }
/// <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); } }
/// <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; }
/// <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(); }
/// <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; }
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); } }
/// <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; } }
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); } }
/// <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); } }
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); } }
/// <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; } }
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); } }