// -------------------------- AuthenticateToServer ------------------------- private void AuthenticateToServer(SocketExchange InExchange) { string message = null; // log the base64 encoded string that follows the 334 challenge. string ResponseData = InExchange.GetResponseData( ); byte[] msgBytes = Convert.FromBase64String(ResponseData); System.Text.Encoding encoding = System.Text.Encoding.UTF8; string msg = encoding.GetString(msgBytes); LogMessage(NetworkRole.Client, msg); // send the user name, expect back a challenge for the password. int LoopCx = 0; while (true) { message = Convert.ToBase64String( Encoding.ASCII.GetBytes(Username.ToCharArray( ))) + SmtpConstants.CrLf; InExchange.ExpectedResponseCodes = new ExpectedResponseCodes( SmtpConstants.Challenge, SmtpConstants.SyntaxError); InExchange.SendReceive(message); if (InExchange.ExpectedResponseCode == SmtpConstants.Challenge) { break; } else if (InExchange.ExpectedResponseCode == SmtpConstants.SyntaxError) { ++LoopCx; if (LoopCx >= 3) { InExchange.ThrowUnexpectedResponse(SmtpConstants.Challenge); } } else { InExchange.ThrowIfUnexpectedResponse( ); } } // send the password. expect back 235 = login successful. message = Convert.ToBase64String( Encoding.ASCII.GetBytes(Password.ToCharArray( ))) + SmtpConstants.CrLf; InExchange.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Authenticated); InExchange.SendReceive(message); InExchange.ThrowIfUnexpectedResponse( ); // is authenticated. SignalAuthenticatedEvent(new MailEventArgs(MailEvent.Authenticated)); }
// ------------------------------ SendMail -------------------------------- public void SendMail(MailMessage msg) { SocketExchange sockEx = null; try { sockEx = Connect( ); // send the MAIL FROM message to the server. This is the start of the sending // of the email message. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Challenge, SmtpConstants.Ok); sockEx.SendReceive("MAIL FROM: <" + msg.From.Address + ">" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); if (sockEx.ResponseCode == SmtpConstants.Challenge) { AuthenticateToServer(sockEx); } // send "rcpt to" message to the mail server to validate the recipients. ServerValidateRecipients(sockEx, msg.ToRecipients); ServerValidateRecipients(sockEx, msg.CCRecipients); ServerValidateRecipients(sockEx, msg.BCCRecipients); // send the DATA message to the server. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.DataReady); sockEx.SendReceive("DATA" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); // send the message itself. SignalStartDataSendEvent(new MailEventArgs(MailEvent.StartDataSend)); sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok); string dataMessage = msg.ToString( ) + SmtpConstants.CrLf + "." + SmtpConstants.CrLf; sockEx.SendReceive(dataMessage); sockEx.ThrowIfUnexpectedResponse( ); SignalEndDataSendEvent(new MailEventArgs(MailEvent.EndDataSend)); Disconnect(sockEx); sockEx = null; } // close the connection. finally { if (sockEx != null) { SignalDisconnectedEvent(new MailEventArgs(MailEvent.Disconnected)); sockEx.CloseConnection( ); } } }
// -------------------- MailServerLogin -------------------------------- private void MailServerLogin( ) { // send username ... mSockEx.ExpectedResponseCodes = new ExpectedResponseCodes(PopConstants.Ok); mSockEx.SendReceive("user " + m_credential.User + PopConstants.CrLf); if (mSockEx.ExpectedResponseCode == null) { mSockEx.ThrowUnexpectedResponse( ); } // send password mSockEx.ExpectedResponseCodes = new ExpectedResponseCodes(PopConstants.Ok); mSockEx.SendReceive("pass " + m_credential.Pass + PopConstants.CrLf); mSockEx.ThrowIfUnexpectedResponse( ); }
// ---------------------- LoadEmail --------------------------- private void LoadEmail(SocketExchange InEx, Int64 InMailDropPosition) { // tell the server we want to read the message. InEx.Send("retr " + InMailDropPosition + PopConstants.CrLf); InEx.ExpectedResponseCodes = new ExpectedResponseCodes(PopConstants.Ok, PopConstants.Error); InEx.SendReceive("retr " + InMailDropPosition + PopConstants.CrLf); InEx.ThrowIfUnexpectedResponse( ); // -ERR response. no such message number. if (InEx.ResponseCode == PopConstants.Error) { } else { // for now, receive SSL link messages in the same thread. if (InEx.ConnectedSecureSocket != null) { StringBuilder mail = null; mail = ReceiveMessage_SameThread(InEx); InEx.LoadResponseMessage(mail.ToString( )); } // receive in a background thread. else { StartReceive(InEx); InEx.LoadResponseMessage(mSockThreadState.sb.ToString( )); } } // parse email ... mParts = MimeCommon.MessagePartSplitter(InEx.ResponseMessage); string[] lines = MimeCommon.MessageLineSplitter(InEx.ResponseMessage); mAttachments = null; MimeAttachment attach = (MimeAttachment)Attachments.FirstAttachment( ).Current; if (attach != null) { attach.SaveAs("c:\\apress\\attachment.txt"); } // if (1 == 2) // DumpHeader(InEx, InMailDropPosition); for (int ix = 0; ix < lines.Length; ++ix) { InEx.Logger.AddMessage(NetworkRole.Server, lines[ix]); } ParseEmail(lines); // remove reading pop3State ... mSockThreadState = null; }
/// <summary> /// send QUIT command and disconnect from server. /// </summary> /// <param name="InSockEx"></param> public void Disconnect(SocketExchange InSockEx) { // send quit message. InSockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Quit); InSockEx.SendReceive("QUIT" + SmtpConstants.CrLf); InSockEx.ThrowIfUnexpectedResponse( ); SignalDisconnectedEvent(new MailEventArgs(MailEvent.Disconnected)); InSockEx.CloseConnection( ); }
// ----------------------- NextEmail ---------------------------------- public bool NextEmail(SocketExchange InEx) { string returned; long pos; if (m_directPosition == -1) { if (m_inboxPosition == 0) { pos = 1; } else { pos = m_inboxPosition + 1; } } else { pos = m_directPosition + 1; m_directPosition = -1; } InEx.ExpectedResponseCodes = new ExpectedResponseCodes(PopConstants.Ok, PopConstants.Error); InEx.SendReceive("list " + pos.ToString( ) + PopConstants.CrLf); if (InEx.ExpectedResponseCode == PopConstants.Error) { return(false); } else { InEx.ThrowIfUnexpectedResponse( ); } returned = InEx.ResponseMessage; m_inboxPosition = pos; // strip out CRLF ... string[] noCr = returned.Split(new char[] { '\r' }); // get size ... string[] elements = noCr[0].Split(new char[] { ' ' }); long size = long.Parse(elements[2]); // ... else read email data m_pop3Message = new Pop3Message(m_inboxPosition, size, m_socket, InEx); return(true); }
// ------------------------- ServerValidateRecipients ------------------------ // Send "rcpt to" message to the mail server to validate each recipient. private void ServerValidateRecipients( SocketExchange InSock, ArrayList InRecipients) { IEnumerator it = InRecipients.GetEnumerator( ); while (it.MoveNext( ) == true) { EmailAddress recipient = (EmailAddress)it.Current; string message = "RCPT TO: <" + recipient.Address + ">" + SmtpConstants.CrLf; InSock.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok); InSock.SendReceive(message); InSock.ThrowIfUnexpectedResponse( ); } }
// ------------------------------ SendMail -------------------------------- public void SendMailOld(MailMessage msg) { SocketExchange sockEx = null; // connect to the mail server. sockEx = new SocketExchange(ServerName, Port, DetailLogger); try { if (UseSecureConnection == true) { sockEx.SecureConnect( ); } else { sockEx.Connect( ); } SignalConnectedEvent(new MailEventArgs(MailEvent.Connected)); // receive the initial server hello message. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.ServerReady); sockEx.Receive( ); sockEx.ThrowIfUnexpectedResponse( ); // hello message exchange. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok); if (ServerRequiresAuthentication == true) { sockEx.SendReceive("EHLO " + Dns.GetHostName() + SmtpConstants.CrLf); } else { sockEx.SendReceive("HELO " + Dns.GetHostName() + SmtpConstants.CrLf); } sockEx.ThrowIfUnexpectedResponse( ); // got a 250, but did not get a 250-AUTH. receive more. if ((sockEx.ResponseCode == SmtpConstants.Ok) && (sockEx.ResponseMessageContains("AUTH") == false)) { LogMessage(NetworkRole.Client, "AUTH not received. Receive more."); sockEx.SleepThenReadMoreAvailableData(300); } // authentication loop sockEx.ReadMoreDelay = 0; if (ServerRequiresAuthentication == true) { int okCount = 0; while (true) { sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok, SmtpConstants.Challenge); sockEx.SendReceive("AUTH LOGIN" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); if (sockEx.ResponseCode == SmtpConstants.Challenge) { AuthenticateToServer(sockEx); break; } else if (sockEx.ResponseCode == SmtpConstants.Ok) { ++okCount; continue; } } } // send the MAIL FROM message to the server. This is the start of the sending // of the email message. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Challenge, SmtpConstants.Ok); sockEx.SendReceive("MAIL FROM: <" + msg.From.Address + ">" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); if (sockEx.ResponseCode == SmtpConstants.Challenge) { AuthenticateToServer(sockEx); } // send "rcpt to" message to the mail server to validate the recipients. ServerValidateRecipients(sockEx, msg.ToRecipients); ServerValidateRecipients(sockEx, msg.CCRecipients); ServerValidateRecipients(sockEx, msg.BCCRecipients); // send the DATA message to the server. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.DataReady); sockEx.SendReceive("DATA" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); // send the message itself. SignalStartDataSendEvent(new MailEventArgs(MailEvent.StartDataSend)); sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok); string dataMessage = msg.ToString( ) + SmtpConstants.CrLf + "." + SmtpConstants.CrLf; sockEx.SendReceive(dataMessage); sockEx.ThrowIfUnexpectedResponse( ); SignalEndDataSendEvent(new MailEventArgs(MailEvent.EndDataSend)); // send quit message. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Quit); sockEx.SendReceive("QUIT" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); } // close the connection. finally { SignalDisconnectedEvent(new MailEventArgs(MailEvent.Disconnected)); sockEx.CloseConnection( ); } }
/// <summary> /// Connect and login to the smtp server. /// </summary> /// <returns></returns> public SocketExchange Connect( ) { // connect to the mail server. SocketExchange sockEx = new SocketExchange(ServerName, Port, DetailLogger); if (UseSecureConnection == true) { sockEx.SecureConnect( ); } else { sockEx.Connect( ); } SignalConnectedEvent(new MailEventArgs(MailEvent.Connected)); // receive the initial server hello message. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.ServerReady); sockEx.Receive( ); sockEx.ThrowIfUnexpectedResponse( ); // hello message exchange. sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok); if (ServerRequiresAuthentication == true) { sockEx.SendReceive("EHLO " + Dns.GetHostName() + SmtpConstants.CrLf); } else { sockEx.SendReceive("HELO " + Dns.GetHostName() + SmtpConstants.CrLf); } sockEx.ThrowIfUnexpectedResponse( ); // got a 250, but did not get a 250-AUTH. receive more. if ((sockEx.ResponseCode == SmtpConstants.Ok) && (sockEx.ResponseMessageContains("AUTH") == false)) { LogMessage(NetworkRole.Client, "AUTH not received. Receive more."); sockEx.SleepThenReadMoreAvailableData(300); } // authentication loop sockEx.ReadMoreDelay = 0; if (ServerRequiresAuthentication == true) { int okCount = 0; while (true) { sockEx.ExpectedResponseCodes = new ExpectedResponseCodes(SmtpConstants.Ok, SmtpConstants.Challenge); sockEx.SendReceive("AUTH LOGIN" + SmtpConstants.CrLf); sockEx.ThrowIfUnexpectedResponse( ); if (sockEx.ResponseCode == SmtpConstants.Challenge) { AuthenticateToServer(sockEx); break; } else if (sockEx.ResponseCode == SmtpConstants.Ok) { ++okCount; continue; } } } return(sockEx); }
// ---------------------- LoadEmail --------------------------- private void LoadEmail(SocketExchange InEx, System.Int64 InMailDropPosition) { // tell the server we want to read the message. InEx.Send("retr " + InMailDropPosition + PopConstants.CrLf); InEx.ExpectedResponseCodes = new ExpectedResponseCodes(PopConstants.Ok, PopConstants.Error); InEx.SendReceive("retr " + InMailDropPosition + PopConstants.CrLf); InEx.ThrowIfUnexpectedResponse( ); // -ERR response. no such message number. if (InEx.ResponseCode == PopConstants.Error) { } else { // for now, receive SSL link messages in the same thread. if (InEx.ConnectedSecureSocket != null) { StringBuilder mail = null; mail = ReceiveMessage_SameThread(InEx); InEx.LoadResponseMessage(mail.ToString( )); } // receive in a background thread. else { StartReceive(InEx); InEx.LoadResponseMessage(mSockThreadState.sb.ToString( )); } } // parse email ... mParts = MimeCommon.MessagePartSplitter(InEx.ResponseMessage); string[] lines = MimeCommon.MessageLineSplitter(InEx.ResponseMessage); if (1 == 2) { mParts = MimeCommon.MessagePartSplitter(lines); } mAttachments = null; MimeAttachment attach = (MimeAttachment)Attachments.FirstAttachment( ).Current; if (attach != null) { attach.SaveAs("c:\\apress\\attachment.txt"); } if (1 == 2) { // dump the header lines of the top part. InEx.Logger.AddMessage(NetworkRole.Server, "--- start header line dump ---"); MimeTopPart topPart = ( MimeTopPart )mParts.GetTopPart( ); for (int Ix = 0; Ix < topPart.PropertyLines.Length; ++Ix) { InEx.Logger.AddMessage(NetworkRole.Server, topPart.PropertyLines[Ix]); } for (int Ix = 0; Ix < topPart.MessageLines.Length; ++Ix) { InEx.Logger.AddMessage(NetworkRole.Server, topPart.MessageLines[Ix]); } InEx.Logger.AddMessage(NetworkRole.Server, "--- end of header line dump ---"); // dump the lines of each part. foreach (MimeMessagePart part in mParts) { InEx.Logger.AddMessage(NetworkRole.Server, "** message part **"); InEx.Logger.AddMessage(NetworkRole.Server, "** property lines **"); foreach (string line in part.PropertyLines) { InEx.Logger.AddMessage(NetworkRole.Server, line); } InEx.Logger.AddMessage(NetworkRole.Server, "** message lines **"); foreach (string line in part.MessageLines) { InEx.Logger.AddMessage(NetworkRole.Server, line); } } InEx.Logger.AddMessage(NetworkRole.Server, "---- end of parts ----------"); } for (int ix = 0; ix < lines.Length; ++ix) { InEx.Logger.AddMessage(NetworkRole.Server, lines[ix]); } ParseEmail(lines); // remove reading pop3State ... mSockThreadState = null; }