Path: blob/master/src/java.base/share/classes/sun/net/smtp/SmtpClient.java
41159 views
/*1* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.net.smtp;2627import java.io.*;28import java.net.*;29import sun.net.TransferProtocolClient;30import sun.security.action.GetPropertyAction;3132/**33* This class implements the SMTP client.34* You can send a piece of mail by creating a new SmtpClient, calling35* the "to" method to add destinations, calling "from" to name the36* sender, calling startMessage to return a stream to which you write37* the message (with RFC733 headers) and then you finally close the Smtp38* Client.39*40* @author James Gosling41*/4243public class SmtpClient extends TransferProtocolClient {4445private static int DEFAULT_SMTP_PORT = 25;46String mailhost;47SmtpPrintStream message;4849/**50* issue the QUIT command to the SMTP server and close the connection.51*/52public void closeServer() throws IOException {53if (serverIsOpen()) {54closeMessage();55issueCommand("QUIT\r\n", 221);56super.closeServer();57}58}5960void issueCommand(String cmd, int expect) throws IOException {61sendServer(cmd);62int reply;63while ((reply = readServerResponse()) != expect)64if (reply != 220) {65throw new SmtpProtocolException(getResponseString());66}67}6869private void toCanonical(String s) throws IOException {70if (s.startsWith("<"))71issueCommand("rcpt to: " + s + "\r\n", 250);72else73issueCommand("rcpt to: <" + s + ">\r\n", 250);74}7576public void to(String s) throws IOException {77if (s.indexOf('\n') != -1) {78throw new IOException("Illegal SMTP command",79new IllegalArgumentException("Illegal carriage return"));80}81int st = 0;82int limit = s.length();83int pos = 0;84int lastnonsp = 0;85int parendepth = 0;86boolean ignore = false;87while (pos < limit) {88int c = s.charAt(pos);89if (parendepth > 0) {90if (c == '(')91parendepth++;92else if (c == ')')93parendepth--;94if (parendepth == 0)95if (lastnonsp > st)96ignore = true;97else98st = pos + 1;99} else if (c == '(')100parendepth++;101else if (c == '<')102st = lastnonsp = pos + 1;103else if (c == '>')104ignore = true;105else if (c == ',') {106if (lastnonsp > st)107toCanonical(s.substring(st, lastnonsp));108st = pos + 1;109ignore = false;110} else {111if (c > ' ' && !ignore)112lastnonsp = pos + 1;113else if (st == pos)114st++;115}116pos++;117}118if (lastnonsp > st)119toCanonical(s.substring(st, lastnonsp));120}121122public void from(String s) throws IOException {123if (s.indexOf('\n') != -1) {124throw new IOException("Illegal SMTP command",125new IllegalArgumentException("Illegal carriage return"));126}127if (s.startsWith("<")) {128issueCommand("mail from: " + s + "\r\n", 250);129} else {130issueCommand("mail from: <" + s + ">\r\n", 250);131}132}133134/** open a SMTP connection to host <i>host</i>. */135private void openServer(String host) throws IOException {136mailhost = host;137openServer(mailhost, DEFAULT_SMTP_PORT);138issueCommand("helo "+InetAddress.getLocalHost().getHostName()+"\r\n", 250);139}140141public PrintStream startMessage() throws IOException {142issueCommand("data\r\n", 354);143try {144message = new SmtpPrintStream(serverOutput, this);145} catch (UnsupportedEncodingException e) {146throw new InternalError(encoding+" encoding not found", e);147}148return message;149}150151void closeMessage() throws IOException {152if (message != null)153message.close();154}155156/** New SMTP client connected to host <i>host</i>. */157public SmtpClient (String host) throws IOException {158super();159if (host != null) {160try {161openServer(host);162mailhost = host;163return;164} catch(Exception e) {165}166}167try {168String s;169mailhost = GetPropertyAction.privilegedGetProperty("mail.host");170if (mailhost != null) {171openServer(mailhost);172return;173}174} catch(Exception e) {175}176try {177mailhost = "localhost";178openServer(mailhost);179} catch(Exception e) {180mailhost = "mailhost";181openServer(mailhost);182}183}184185/** Create an uninitialized SMTP client. */186public SmtpClient () throws IOException {187this(null);188}189190public SmtpClient(int to) throws IOException {191super();192setConnectTimeout(to);193try {194String s;195mailhost = GetPropertyAction.privilegedGetProperty("mail.host");196if (mailhost != null) {197openServer(mailhost);198return;199}200} catch(Exception e) {201}202try {203mailhost = "localhost";204openServer(mailhost);205} catch(Exception e) {206mailhost = "mailhost";207openServer(mailhost);208}209}210211public String getMailHost() {212return mailhost;213}214215String getEncoding () {216return encoding;217}218}219220class SmtpPrintStream extends java.io.PrintStream {221private SmtpClient target;222private int lastc = '\n';223224SmtpPrintStream (OutputStream fos, SmtpClient cl) throws UnsupportedEncodingException {225super(fos, false, cl.getEncoding());226target = cl;227}228229public void close() {230if (target == null)231return;232if (lastc != '\n') {233write('\n');234}235try {236target.issueCommand(".\r\n", 250);237target.message = null;238out = null;239target = null;240} catch (IOException e) {241}242}243244public void write(int b) {245try {246// quote a dot at the beginning of a line247if (lastc == '\n' && b == '.') {248out.write('.');249}250251// translate NL to CRLF252if (b == '\n' && lastc != '\r') {253out.write('\r');254}255out.write(b);256lastc = b;257} catch (IOException e) {258}259}260261public void write(byte b[], int off, int len) {262try {263int lc = lastc;264while (--len >= 0) {265int c = b[off++];266267// quote a dot at the beginning of a line268if (lc == '\n' && c == '.')269out.write('.');270271// translate NL to CRLF272if (c == '\n' && lc != '\r') {273out.write('\r');274}275out.write(c);276lc = c;277}278lastc = lc;279} catch (IOException e) {280}281}282public void print(String s) {283int len = s.length();284for (int i = 0; i < len; i++) {285write(s.charAt(i));286}287}288}289290291