//
// System.Web.Mail.SmtpStream.cs
//
// Author(s):
// Per Arneng <pt99par@student.bth.se>
//
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics;
namespace System.Web.Mail{
internal class SmtpStream {
protected Stream stream;
protected Encoding encoding;
protected SmtpResponse lastResponse;
protected string command = "";
public SmtpStream( Stream stream ) {
this.stream = stream;
encoding = new ASCIIEncoding();
}
public Stream Stream {
get { return stream; }
}
public SmtpResponse LastResponse {
get { return lastResponse; }
}
public void WriteRset() {
command = "RSET";
WriteLine( command );
ReadResponse();
CheckForStatusCode( 250 );
}
public void WriteAuthLogin()
{
command = "AUTH LOGIN";
WriteLine( command );
ReadResponse();
}
public bool WriteStartTLS( )
{
command = "STARTTLS";
WriteLine( command );
ReadResponse();
return LastResponse.StatusCode == 220;
}
public void WriteEhlo( string hostName )
{
command = "EHLO " + hostName;
WriteLine( command );
ReadResponse();
CheckForStatusCode( 250 );
}
public void WriteHelo( string hostName ) {
command = "HELO " + hostName;
WriteLine( command );
ReadResponse();
CheckForStatusCode( 250 );
}
public void WriteMailFrom( string from ) {
command = "MAIL FROM: <" + from + ">";
WriteLine( command );
ReadResponse();
CheckForStatusCode( 250 );
}
public void WriteRcptTo( string to ) {
command = "RCPT TO: <" + to + ">";
WriteLine( command );
ReadResponse();
CheckForStatusCode( 250 );
}
public void WriteData() {
command = "DATA";
WriteLine( command );
ReadResponse();
CheckForStatusCode( 354 );
}
public void WriteQuit() {
command = "QUIT";
WriteLine( command );
ReadResponse();
CheckForStatusCode( 221 );
}
public void WriteBoundary( string boundary ) {
WriteLine( "\r\n--{0}" , boundary );
}
public void WriteFinalBoundary( string boundary ) {
WriteLine( "\r\n--{0}--" , boundary );
}
// single dot by itself
public void WriteDataEndTag() {
command = "\r\n.";
WriteLine( command );
ReadResponse();
CheckForStatusCode( 250 );
}
public void WriteHeader( MailHeader header ) {
// write the headers
foreach( string key in header.Data.AllKeys )
WriteLine( "{0}: {1}" , key , header.Data[ key ] );
// write the header end tag
WriteLine( "" );
}
public void CheckForStatusCode( int statusCode ) {
if( LastResponse.StatusCode != statusCode ) {
string msg = "" +
"Server reponse: '" + lastResponse.RawResponse + "';" +
"Status code: '" + lastResponse.StatusCode + "';" +
"Expected status code: '" + statusCode + "';" +
"Last command: '" + command + "'";
throw new SmtpException( msg );
}
}
// write buffer's bytes to the stream
public void WriteBytes( byte[] buffer ) {
stream.Write( buffer , 0 , buffer.Length );
}
// writes a formatted line to the server
public void WriteLine( string format , params object[] args ) {
WriteLine( String.Format( format , args ) );
}
// writes a line to the server
public void WriteLine( string line ) {
byte[] buffer = encoding.GetBytes( line + "\r\n" );
stream.Write( buffer , 0 , buffer.Length );
Debug.WriteLine ("smtp: {0}", line);
}
// read a line from the server
public void ReadResponse( ) {
byte[] buffer = new byte [512];
int position = 0;
bool lastLine = false;
do {
int readLength = stream.Read (buffer , position , buffer.Length - position);
if (readLength > 0) {
int available = position + readLength - 1;
if (available > 4 && (buffer [available] == '\n' || buffer [available] == '\r'))
for (int index = available - 3; ; index--) {
if (index < 0 || buffer [index] == '\n' || buffer [index] == '\r') {
lastLine = buffer [index + 4] == ' ';
break;
}
}
// move position
position += readLength;
// check if buffer is full
if (position == buffer.Length) {
byte [] newBuffer = new byte [buffer.Length * 2];
Array.Copy (buffer, 0, newBuffer, 0, buffer.Length);
buffer = newBuffer;
}
}
} while(!lastLine);
string line = encoding.GetString (buffer , 0 , position - 1);
// parse the line to the lastResponse object
lastResponse = SmtpResponse.Parse (line);
Debug.WriteLine ("smtp: {0}", line);
}
}
}
|