* TagAttribute.cs: attributes can be stored as encoded html so we
[mono.git] / mcs / class / System.Web / System.Web.Mail / SmtpClient.cs
1 //
2 // System.Web.Mail.SmtpClient.cs
3 //
4 // Author(s):
5 //   Per Arneng <pt99par@student.bth.se>
6 //
7 //
8 using System;
9 using System.Net;
10 using System.IO;
11 using System.Text;
12 using System.Collections;
13 using System.Net.Sockets;
14
15 namespace System.Web.Mail {
16
17     /// represents a conntection to a smtp server
18     internal class SmtpClient {
19         
20         private string server;
21         private TcpClient tcpConnection;
22         private SmtpStream smtp;
23         private Encoding encoding;
24         
25         //Initialise the variables and connect
26         public SmtpClient( string server ) {
27             
28             this.server = server;
29             encoding = new ASCIIEncoding( );
30
31             Connect();
32         }
33         
34         // make the actual connection
35         // and HELO handshaking
36         private void Connect() {
37             tcpConnection = new TcpClient( server , 25 );
38             
39             Stream stream = tcpConnection.GetStream();
40             smtp = new SmtpStream( stream );
41             
42             // read the server greeting
43             smtp.ReadResponse();
44             smtp.CheckForStatusCode( 220 );
45            
46             // write the HELO command to the server
47             smtp.WriteHelo( Dns.GetHostName() );
48                     
49         }
50         
51         public void Send( MailMessageWrapper msg ) {
52             
53             if( msg.From == null ) {
54                 throw new SmtpException( "From property must be set." );
55             }
56
57             if( msg.To == null ) {
58                 if( msg.To.Count < 1 ) throw new SmtpException( "Atleast one recipient must be set." );
59             }
60             
61                     
62             // start with a reset incase old data
63             // is present at the server in this session
64             smtp.WriteRset();
65             
66             // write the mail from command
67             smtp.WriteMailFrom( msg.From.Address );
68             
69             // write the rcpt to command for the To addresses
70             foreach( MailAddress addr in msg.To ) {
71                 smtp.WriteRcptTo( addr.Address );
72             }
73
74             // write the rcpt to command for the Cc addresses
75             foreach( MailAddress addr in msg.Cc ) {
76                 smtp.WriteRcptTo( addr.Address );
77             }
78
79             // write the rcpt to command for the Bcc addresses
80             foreach( MailAddress addr in msg.Bcc ) {
81                 smtp.WriteRcptTo( addr.Address );
82             }
83             
84             // write the data command and then
85             // send the email
86             smtp.WriteData();
87            
88
89             if( msg.Attachments.Count == 0 ) {
90                 
91                 SendSinglepartMail( msg );
92             
93             } else {
94                 
95                 SendMultipartMail( msg );
96             
97             }
98
99             // write the data end tag "."
100             smtp.WriteDataEndTag();
101
102         }
103         
104         // sends a single part mail to the server
105         private void SendSinglepartMail( MailMessageWrapper msg ) {
106                             
107             // write the header
108             smtp.WriteHeader( msg.Header );
109             
110             // send the mail body
111             smtp.WriteBytes( msg.BodyEncoding.GetBytes( msg.Body ) );
112
113         }
114         
115         // sends a multipart mail to the server
116         private void SendMultipartMail( MailMessageWrapper msg ) {
117                     
118             // generate the boundary between attachments
119             string boundary = MailUtil.GenerateBoundary();
120                 
121             // set the Content-Type header to multipart/mixed
122             msg.Header.ContentType = 
123                 String.Format( "multipart/mixed;\r\n   boundary={0}" , boundary );
124                 
125             // write the header
126             smtp.WriteHeader( msg.Header );
127                 
128             // write the first part text part
129             // before the attachments
130             smtp.WriteBoundary( boundary );
131                 
132             MailHeader partHeader = new MailHeader();
133             partHeader.ContentType = "text/plain";
134                 
135             smtp.WriteHeader( partHeader );
136                 
137           
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 )  );
141
142             smtp.WriteBoundary( boundary );
143             
144             // now start to write the attachments
145             
146             for( int i=0; i< msg.Attachments.Count ; i++ ) {
147                 MailAttachment a = (MailAttachment)msg.Attachments[ i ];
148                         
149                 FileInfo fileInfo = new FileInfo( a.Filename );
150
151                 MailHeader aHeader = new MailHeader();
152                 
153                 aHeader.ContentType = 
154                     String.Format( "application/octet-stream; name=\"{0}\"", 
155                                    fileInfo.Name  );
156                 
157                 aHeader.ContentDisposition = 
158                     String.Format( "attachment; filename=\"{0}\"" , fileInfo.Name );
159                 
160                 aHeader.ContentTransferEncoding = a.Encoding.ToString();
161                                 
162                 smtp.WriteHeader( aHeader );
163                    
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 );
167                 
168                 // create an apropriate encoder
169                 IAttachmentEncoder encoder;
170                 if( a.Encoding == MailEncoding.UUEncode ) {
171                     encoder = new UUAttachmentEncoder( 644 , fileInfo.Name  );
172                 } else {
173                     encoder = new Base64AttachmentEncoder();
174                 }
175                 
176                 encoder.EncodeStream( ins , smtp.Stream );
177                 
178                 ins.Close();
179                 
180                     
181                 smtp.WriteLine( "" );
182                 
183                 // if it is the last attachment write
184                 // the final boundary otherwise write
185                 // a normal one.
186                 if( i < (msg.Attachments.Count - 1) ) { 
187                     smtp.WriteBoundary( boundary );
188                 } else {
189                     smtp.WriteFinalBoundary( boundary );
190                 }
191                     
192                 
193             }
194                
195         }
196         
197         // send quit command and
198         // closes the connection
199         public void Close() {
200             
201             smtp.WriteQuit();
202             tcpConnection.Close();
203         
204         }
205         
206                 
207     }
208
209 }