| /* |
| * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.net.smtp; |
| |
| import java.util.StringTokenizer; |
| import java.io.*; |
| import java.net.*; |
| import sun.net.TransferProtocolClient; |
| |
| /** |
| * This class implements the SMTP client. |
| * You can send a piece of mail by creating a new SmtpClient, calling |
| * the "to" method to add destinations, calling "from" to name the |
| * sender, calling startMessage to return a stream to which you write |
| * the message (with RFC733 headers) and then you finally close the Smtp |
| * Client. |
| * |
| * @author James Gosling |
| */ |
| |
| public class SmtpClient extends TransferProtocolClient { |
| |
| String mailhost; |
| SmtpPrintStream message; |
| |
| /** |
| * issue the QUIT command to the SMTP server and close the connection. |
| */ |
| public void closeServer() throws IOException { |
| if (serverIsOpen()) { |
| closeMessage(); |
| issueCommand("QUIT\r\n", 221); |
| super.closeServer(); |
| } |
| } |
| |
| void issueCommand(String cmd, int expect) throws IOException { |
| sendServer(cmd); |
| int reply; |
| while ((reply = readServerResponse()) != expect) |
| if (reply != 220) { |
| throw new SmtpProtocolException(getResponseString()); |
| } |
| } |
| |
| private void toCanonical(String s) throws IOException { |
| if (s.startsWith("<")) |
| issueCommand("rcpt to: " + s + "\r\n", 250); |
| else |
| issueCommand("rcpt to: <" + s + ">\r\n", 250); |
| } |
| |
| public void to(String s) throws IOException { |
| int st = 0; |
| int limit = s.length(); |
| int pos = 0; |
| int lastnonsp = 0; |
| int parendepth = 0; |
| boolean ignore = false; |
| while (pos < limit) { |
| int c = s.charAt(pos); |
| if (parendepth > 0) { |
| if (c == '(') |
| parendepth++; |
| else if (c == ')') |
| parendepth--; |
| if (parendepth == 0) |
| if (lastnonsp > st) |
| ignore = true; |
| else |
| st = pos + 1; |
| } else if (c == '(') |
| parendepth++; |
| else if (c == '<') |
| st = lastnonsp = pos + 1; |
| else if (c == '>') |
| ignore = true; |
| else if (c == ',') { |
| if (lastnonsp > st) |
| toCanonical(s.substring(st, lastnonsp)); |
| st = pos + 1; |
| ignore = false; |
| } else { |
| if (c > ' ' && !ignore) |
| lastnonsp = pos + 1; |
| else if (st == pos) |
| st++; |
| } |
| pos++; |
| } |
| if (lastnonsp > st) |
| toCanonical(s.substring(st, lastnonsp)); |
| } |
| |
| public void from(String s) throws IOException { |
| if (s.startsWith("<")) |
| issueCommand("mail from: " + s + "\r\n", 250); |
| else |
| issueCommand("mail from: <" + s + ">\r\n", 250); |
| } |
| |
| /** open a SMTP connection to host <i>host</i>. */ |
| private void openServer(String host) throws IOException { |
| mailhost = host; |
| openServer(mailhost, 25); |
| issueCommand("helo "+InetAddress.getLocalHost().getHostName()+"\r\n", 250); |
| } |
| |
| public PrintStream startMessage() throws IOException { |
| issueCommand("data\r\n", 354); |
| try { |
| message = new SmtpPrintStream(serverOutput, this); |
| } catch (UnsupportedEncodingException e) { |
| throw new InternalError(encoding+" encoding not found", e); |
| } |
| return message; |
| } |
| |
| void closeMessage() throws IOException { |
| if (message != null) |
| message.close(); |
| } |
| |
| /** New SMTP client connected to host <i>host</i>. */ |
| public SmtpClient (String host) throws IOException { |
| super(); |
| if (host != null) { |
| try { |
| openServer(host); |
| mailhost = host; |
| return; |
| } catch(Exception e) { |
| } |
| } |
| try { |
| String s; |
| mailhost = java.security.AccessController.doPrivileged( |
| new sun.security.action.GetPropertyAction("mail.host")); |
| if (mailhost != null) { |
| openServer(mailhost); |
| return; |
| } |
| } catch(Exception e) { |
| } |
| try { |
| mailhost = "localhost"; |
| openServer(mailhost); |
| } catch(Exception e) { |
| mailhost = "mailhost"; |
| openServer(mailhost); |
| } |
| } |
| |
| /** Create an uninitialized SMTP client. */ |
| public SmtpClient () throws IOException { |
| this(null); |
| } |
| |
| public SmtpClient(int to) throws IOException { |
| super(); |
| setConnectTimeout(to); |
| try { |
| String s; |
| mailhost = java.security.AccessController.doPrivileged( |
| new sun.security.action.GetPropertyAction("mail.host")); |
| if (mailhost != null) { |
| openServer(mailhost); |
| return; |
| } |
| } catch(Exception e) { |
| } |
| try { |
| mailhost = "localhost"; |
| openServer(mailhost); |
| } catch(Exception e) { |
| mailhost = "mailhost"; |
| openServer(mailhost); |
| } |
| } |
| |
| public String getMailHost() { |
| return mailhost; |
| } |
| |
| String getEncoding () { |
| return encoding; |
| } |
| } |
| |
| class SmtpPrintStream extends java.io.PrintStream { |
| private SmtpClient target; |
| private int lastc = '\n'; |
| |
| SmtpPrintStream (OutputStream fos, SmtpClient cl) throws UnsupportedEncodingException { |
| super(fos, false, cl.getEncoding()); |
| target = cl; |
| } |
| |
| public void close() { |
| if (target == null) |
| return; |
| if (lastc != '\n') { |
| write('\n'); |
| } |
| try { |
| target.issueCommand(".\r\n", 250); |
| target.message = null; |
| out = null; |
| target = null; |
| } catch (IOException e) { |
| } |
| } |
| |
| public void write(int b) { |
| try { |
| // quote a dot at the beginning of a line |
| if (lastc == '\n' && b == '.') { |
| out.write('.'); |
| } |
| |
| // translate NL to CRLF |
| if (b == '\n' && lastc != '\r') { |
| out.write('\r'); |
| } |
| out.write(b); |
| lastc = b; |
| } catch (IOException e) { |
| } |
| } |
| |
| public void write(byte b[], int off, int len) { |
| try { |
| int lc = lastc; |
| while (--len >= 0) { |
| int c = b[off++]; |
| |
| // quote a dot at the beginning of a line |
| if (lc == '\n' && c == '.') |
| out.write('.'); |
| |
| // translate NL to CRLF |
| if (c == '\n' && lc != '\r') { |
| out.write('\r'); |
| } |
| out.write(c); |
| lc = c; |
| } |
| lastc = lc; |
| } catch (IOException e) { |
| } |
| } |
| public void print(String s) { |
| int len = s.length(); |
| for (int i = 0; i < len; i++) { |
| write(s.charAt(i)); |
| } |
| } |
| } |