• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.net.smtp;
27 
28 import java.util.StringTokenizer;
29 import java.io.*;
30 import java.net.*;
31 import sun.net.TransferProtocolClient;
32 
33 /**
34  * This class implements the SMTP client.
35  * You can send a piece of mail by creating a new SmtpClient, calling
36  * the "to" method to add destinations, calling "from" to name the
37  * sender, calling startMessage to return a stream to which you write
38  * the message (with RFC733 headers) and then you finally close the Smtp
39  * Client.
40  *
41  * @author      James Gosling
42  */
43 
44 public class SmtpClient extends TransferProtocolClient {
45 
46     String mailhost;
47     SmtpPrintStream message;
48 
49     /**
50      * issue the QUIT command to the SMTP server and close the connection.
51      */
closeServer()52     public void closeServer() throws IOException {
53         if (serverIsOpen()) {
54             closeMessage();
55             issueCommand("QUIT\r\n", 221);
56             super.closeServer();
57         }
58     }
59 
issueCommand(String cmd, int expect)60     void issueCommand(String cmd, int expect) throws IOException {
61         sendServer(cmd);
62         int reply;
63         while ((reply = readServerResponse()) != expect)
64             if (reply != 220) {
65                 throw new SmtpProtocolException(getResponseString());
66             }
67     }
68 
toCanonical(String s)69     private void toCanonical(String s) throws IOException {
70         if (s.startsWith("<"))
71             issueCommand("rcpt to: " + s + "\r\n", 250);
72         else
73             issueCommand("rcpt to: <" + s + ">\r\n", 250);
74     }
75 
to(String s)76     public void to(String s) throws IOException {
77         int st = 0;
78         int limit = s.length();
79         int pos = 0;
80         int lastnonsp = 0;
81         int parendepth = 0;
82         boolean ignore = false;
83         while (pos < limit) {
84             int c = s.charAt(pos);
85             if (parendepth > 0) {
86                 if (c == '(')
87                     parendepth++;
88                 else if (c == ')')
89                     parendepth--;
90                 if (parendepth == 0)
91                     if (lastnonsp > st)
92                         ignore = true;
93                     else
94                         st = pos + 1;
95             } else if (c == '(')
96                 parendepth++;
97             else if (c == '<')
98                 st = lastnonsp = pos + 1;
99             else if (c == '>')
100                 ignore = true;
101             else if (c == ',') {
102                 if (lastnonsp > st)
103                     toCanonical(s.substring(st, lastnonsp));
104                 st = pos + 1;
105                 ignore = false;
106             } else {
107                 if (c > ' ' && !ignore)
108                     lastnonsp = pos + 1;
109                 else if (st == pos)
110                     st++;
111             }
112             pos++;
113         }
114         if (lastnonsp > st)
115             toCanonical(s.substring(st, lastnonsp));
116     }
117 
from(String s)118     public void from(String s) throws IOException {
119         if (s.startsWith("<"))
120             issueCommand("mail from: " + s + "\r\n", 250);
121         else
122             issueCommand("mail from: <" + s + ">\r\n", 250);
123     }
124 
125     /** open a SMTP connection to host <i>host</i>. */
openServer(String host)126     private void openServer(String host) throws IOException {
127         mailhost = host;
128         openServer(mailhost, 25);
129         issueCommand("helo "+InetAddress.getLocalHost().getHostName()+"\r\n", 250);
130     }
131 
startMessage()132     public PrintStream startMessage() throws IOException {
133         issueCommand("data\r\n", 354);
134         try {
135             message = new SmtpPrintStream(serverOutput, this);
136         } catch (UnsupportedEncodingException e) {
137             throw new InternalError(encoding+" encoding not found");
138         }
139         return message;
140     }
141 
closeMessage()142     void closeMessage() throws IOException {
143         if (message != null)
144             message.close();
145     }
146 
147     /** New SMTP client connected to host <i>host</i>. */
SmtpClient(String host)148     public SmtpClient (String host) throws IOException {
149         super();
150         if (host != null) {
151             try {
152                 openServer(host);
153                 mailhost = host;
154                 return;
155             } catch(Exception e) {
156             }
157         }
158         try {
159             String s;
160             mailhost = java.security.AccessController.doPrivileged(
161                     new sun.security.action.GetPropertyAction("mail.host"));
162             if (mailhost != null) {
163                 openServer(mailhost);
164                 return;
165             }
166         } catch(Exception e) {
167         }
168         try {
169             mailhost = "localhost";
170             openServer(mailhost);
171         } catch(Exception e) {
172             mailhost = "mailhost";
173             openServer(mailhost);
174         }
175     }
176 
177     /** Create an uninitialized SMTP client. */
SmtpClient()178     public SmtpClient () throws IOException {
179         this(null);
180     }
181 
SmtpClient(int to)182     public SmtpClient(int to) throws IOException {
183         super();
184         setConnectTimeout(to);
185         try {
186             String s;
187             mailhost = java.security.AccessController.doPrivileged(
188                     new sun.security.action.GetPropertyAction("mail.host"));
189             if (mailhost != null) {
190                 openServer(mailhost);
191                 return;
192             }
193         } catch(Exception e) {
194         }
195         try {
196             mailhost = "localhost";
197             openServer(mailhost);
198         } catch(Exception e) {
199             mailhost = "mailhost";
200             openServer(mailhost);
201         }
202     }
203 
getMailHost()204     public String getMailHost() {
205         return mailhost;
206     }
207 
getEncoding()208     String getEncoding () {
209         return encoding;
210     }
211 }
212 
213 class SmtpPrintStream extends java.io.PrintStream {
214     private SmtpClient target;
215     private int lastc = '\n';
216 
SmtpPrintStream(OutputStream fos, SmtpClient cl)217     SmtpPrintStream (OutputStream fos, SmtpClient cl) throws UnsupportedEncodingException {
218         super(fos, false, cl.getEncoding());
219         target = cl;
220     }
221 
close()222     public void close() {
223         if (target == null)
224             return;
225         if (lastc != '\n') {
226             write('\n');
227         }
228         try {
229             target.issueCommand(".\r\n", 250);
230             target.message = null;
231             out = null;
232             target = null;
233         } catch (IOException e) {
234         }
235     }
236 
write(int b)237     public void write(int b) {
238         try {
239             // quote a dot at the beginning of a line
240             if (lastc == '\n' && b == '.') {
241                 out.write('.');
242             }
243 
244             // translate NL to CRLF
245             if (b == '\n' && lastc != '\r') {
246                 out.write('\r');
247             }
248             out.write(b);
249             lastc = b;
250         } catch (IOException e) {
251         }
252     }
253 
write(byte b[], int off, int len)254     public void write(byte b[], int off, int len) {
255         try {
256             int lc = lastc;
257             while (--len >= 0) {
258                 int c = b[off++];
259 
260                 // quote a dot at the beginning of a line
261                 if (lc == '\n' && c == '.')
262                     out.write('.');
263 
264                 // translate NL to CRLF
265                 if (c == '\n' && lc != '\r') {
266                     out.write('\r');
267                 }
268                 out.write(c);
269                 lc = c;
270             }
271             lastc = lc;
272         } catch (IOException e) {
273         }
274     }
print(String s)275     public void print(String s) {
276         int len = s.length();
277         for (int i = 0; i < len; i++) {
278             write(s.charAt(i));
279         }
280     }
281 }
282