2 // System.Web.Mail.SmtpClient.cs
5 // Per Arneng <pt99par@student.bth.se>
12 using System.Collections;
13 using System.Net.Sockets;
15 namespace System.Web.Mail {
17 /// represents a conntection to a smtp server
18 internal class SmtpClient {
20 private string server;
21 private TcpClient tcpConnection;
22 private SmtpStream smtp;
23 private Encoding encoding;
25 //Initialise the variables and connect
26 public SmtpClient( string server ) {
29 encoding = new ASCIIEncoding( );
34 // make the actual connection
35 // and HELO handshaking
36 private void Connect() {
37 tcpConnection = new TcpClient( server , 25 );
39 Stream stream = tcpConnection.GetStream();
40 smtp = new SmtpStream( stream );
42 // read the server greeting
44 smtp.CheckForStatusCode( 220 );
46 // write the HELO command to the server
47 smtp.WriteHelo( Dns.GetHostName() );
51 public void Send( MailMessageWrapper msg ) {
53 if( msg.From == null ) {
54 throw new SmtpException( "From property must be set." );
57 if( msg.To == null ) {
58 if( msg.To.Count < 1 ) throw new SmtpException( "Atleast one recipient must be set." );
62 // start with a reset incase old data
63 // is present at the server in this session
66 // write the mail from command
67 smtp.WriteMailFrom( msg.From.Address );
69 // write the rcpt to command for the To addresses
70 foreach( MailAddress addr in msg.To ) {
71 smtp.WriteRcptTo( addr.Address );
74 // write the rcpt to command for the Cc addresses
75 foreach( MailAddress addr in msg.Cc ) {
76 smtp.WriteRcptTo( addr.Address );
79 // write the rcpt to command for the Bcc addresses
80 foreach( MailAddress addr in msg.Bcc ) {
81 smtp.WriteRcptTo( addr.Address );
84 // write the data command and then
89 if( msg.Attachments.Count == 0 ) {
91 SendSinglepartMail( msg );
95 SendMultipartMail( msg );
99 // write the data end tag "."
100 smtp.WriteDataEndTag();
104 // sends a single part mail to the server
105 private void SendSinglepartMail( MailMessageWrapper msg ) {
108 smtp.WriteHeader( msg.Header );
110 // send the mail body
111 smtp.WriteBytes( msg.BodyEncoding.GetBytes( msg.Body ) );
115 // sends a multipart mail to the server
116 private void SendMultipartMail( MailMessageWrapper msg ) {
118 // generate the boundary between attachments
119 string boundary = MailUtil.GenerateBoundary();
121 // set the Content-Type header to multipart/mixed
122 msg.Header.ContentType =
123 String.Format( "multipart/mixed;\r\n boundary={0}" , boundary );
126 smtp.WriteHeader( msg.Header );
128 // write the first part text part
129 // before the attachments
130 smtp.WriteBoundary( boundary );
132 MailHeader partHeader = new MailHeader();
133 partHeader.ContentType = "text/plain";
135 smtp.WriteHeader( partHeader );
138 // FIXME: probably need to use QP or Base64 on everything higher
139 // then 8-bit .. like utf-16
140 smtp.WriteBytes( msg.BodyEncoding.GetBytes( msg.Body ) );
142 smtp.WriteBoundary( boundary );
144 // now start to write the attachments
146 for( int i=0; i< msg.Attachments.Count ; i++ ) {
147 MailAttachment a = (MailAttachment)msg.Attachments[ i ];
149 FileInfo fileInfo = new FileInfo( a.Filename );
151 MailHeader aHeader = new MailHeader();
153 aHeader.ContentType =
154 String.Format( "application/octet-stream; name=\"{0}\"",
157 aHeader.ContentDisposition =
158 String.Format( "attachment; filename=\"{0}\"" , fileInfo.Name );
160 aHeader.ContentTransferEncoding = a.Encoding.ToString();
162 smtp.WriteHeader( aHeader );
164 // perform the actual writing of the file.
165 // read from the file stream and write to the tcp stream
166 FileStream ins = new FileStream( fileInfo.FullName , FileMode.Open );
168 // create an apropriate encoder
169 IAttachmentEncoder encoder;
170 if( a.Encoding == MailEncoding.UUEncode ) {
171 encoder = new UUAttachmentEncoder( 644 , fileInfo.Name );
173 encoder = new Base64AttachmentEncoder();
176 encoder.EncodeStream( ins , smtp.Stream );
181 smtp.WriteLine( "" );
183 // if it is the last attachment write
184 // the final boundary otherwise write
186 if( i < (msg.Attachments.Count - 1) ) {
187 smtp.WriteBoundary( boundary );
189 smtp.WriteFinalBoundary( boundary );
197 // send quit command and
198 // closes the connection
199 public void Close() {
202 tcpConnection.Close();