📄 smtpconnection.java
字号:
/* * SMTPConnection.java * Copyright (C) 2003 Chris Burdess <dog@gnu.org> * * This file is part of GNU inetlib, a library. * * GNU inetlib is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GNU inetlib 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 for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obliged to do so. If you do not wish to do so, delete this * exception statement from your version. */package gnu.inet.smtp;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.InputStream;import java.io.IOException;import java.io.OutputStream;import java.net.InetSocketAddress;import java.net.ProtocolException;import java.net.Socket;import java.security.GeneralSecurityException;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;import javax.security.auth.callback.CallbackHandler;import javax.security.sasl.Sasl;import javax.security.sasl.SaslClient;import javax.security.sasl.SaslException;import gnu.inet.util.BASE64;import gnu.inet.util.CRLFInputStream;import gnu.inet.util.CRLFOutputStream;import gnu.inet.util.EmptyX509TrustManager;import gnu.inet.util.LineInputStream;import gnu.inet.util.MessageOutputStream;import gnu.inet.util.SaslCallbackHandler;import gnu.inet.util.SaslCramMD5;import gnu.inet.util.SaslInputStream;import gnu.inet.util.SaslLogin;import gnu.inet.util.SaslOutputStream;import gnu.inet.util.SaslPlain;import gnu.inet.util.TraceLevel;/** * An SMTP client. * This implements RFC 2821. * * @author <a href="mailto:dog@gnu.org">Chris Burdess</a> */public class SMTPConnection{ /** * The logger used for SMTP protocol traces. */ public static final Logger logger = Logger.getLogger("gnu.inet.smtp"); /** * The network trace level. */ public static final Level SMTP_TRACE = new TraceLevel("smtp"); /** * The default SMTP port. */ public static final int DEFAULT_PORT = 25; protected static final String MAIL_FROM = "MAIL FROM:"; protected static final String RCPT_TO = "RCPT TO:"; protected static final String SP = " "; protected static final String DATA = "DATA"; protected static final String FINISH_DATA = "\n."; protected static final String RSET = "RSET"; protected static final String VRFY = "VRFY"; protected static final String EXPN = "EXPN"; protected static final String HELP = "HELP"; protected static final String NOOP = "NOOP"; protected static final String QUIT = "QUIT"; protected static final String HELO = "HELO"; protected static final String EHLO = "EHLO"; protected static final String AUTH = "AUTH"; protected static final String STARTTLS = "STARTTLS"; protected static final int INFO = 214; protected static final int READY = 220; protected static final int OK = 250; protected static final int OK_NOT_LOCAL = 251; protected static final int OK_UNVERIFIED = 252; protected static final int SEND_DATA = 354; protected static final int AMBIGUOUS = 553; /** * The underlying socket used for communicating with the server. */ protected Socket socket; /** * The input stream used to read responses from the server. */ protected LineInputStream in; /** * The output stream used to send commands to the server. */ protected CRLFOutputStream out; /** * The last response message received from the server. */ protected String response; /** * If true, there are more responses to read. */ protected boolean continuation; /** * The greeting message given by the server. */ protected final String greeting; /** * Creates a new connection to the specified host, using the default SMTP * port. * @param host the server hostname */ public SMTPConnection(String host) throws IOException { this(host, DEFAULT_PORT, 0, 0, false, null); } /** * Creates a new connection to the specified host, using the specified * port. * @param host the server hostname * @param port the port to connect to */ public SMTPConnection(String host, int port) throws IOException { this(host, port, 0, 0, false, null); } /** * Creates a new connection to the specified host, using the specified * port. * @param host the server hostname * @param port the port to connect to * @param connectionTimeout the connection timeout in milliseconds * @param timeout the I/O timeout in milliseconds */ public SMTPConnection(String host, int port, int connectionTimeout, int timeout) throws IOException { this(host, port, connectionTimeout, timeout, false, null); } /** * Creates a new connection to the specified host, using the specified * port. * @param host the server hostname * @param port the port to connect to * @param connectionTimeout the connection timeout in milliseconds * @param timeout the I/O timeout in milliseconds * @param secure true to create an SMTPS connection * @param tm a trust manager used to check SSL certificates, or null to * use the default */ public SMTPConnection(String host, int port, int connectionTimeout, int timeout, boolean secure, TrustManager tm) throws IOException { if (port <= 0) { port = DEFAULT_PORT; } response = null; continuation = false; // Initialise socket try { socket = new Socket(); InetSocketAddress address = new InetSocketAddress(host, port); if (connectionTimeout > 0) { socket.connect(address, connectionTimeout); } else { socket.connect(address); } if (timeout > 0) { socket.setSoTimeout(timeout); } if (secure) { SSLSocketFactory factory = getSSLSocketFactory(tm); SSLSocket ss = (SSLSocket) factory.createSocket(socket, host, port, true); String[] protocols = { "TLSv1", "SSLv3" }; ss.setEnabledProtocols(protocols); ss.setUseClientMode(true); ss.startHandshake(); socket = ss; } } catch (GeneralSecurityException e) { IOException e2 = new IOException(); e2.initCause(e); throw e2; } // Initialise streams InputStream in = socket.getInputStream(); in = new BufferedInputStream(in); in = new CRLFInputStream(in); this.in = new LineInputStream(in); OutputStream out = socket.getOutputStream(); out = new BufferedOutputStream(out); this.out = new CRLFOutputStream(out); // Greeting StringBuffer greetingBuffer = new StringBuffer(); boolean notFirst = false; do { if (getResponse() != READY) { throw new ProtocolException(response); } if (notFirst) { greetingBuffer.append('\n'); } else { notFirst = true; } greetingBuffer.append(response); } while (continuation); greeting = greetingBuffer.toString(); } /** * Returns the server greeting message. */ public String getGreeting() { return greeting; } /** * Returns the text of the last response received from the server. */ public String getLastResponse() { return response; } // -- 3.3 Mail transactions -- /** * Execute a MAIL command. * @param reversePath the source mailbox(from address) * @param parameters optional ESMTP parameters * @return true if accepted, false otherwise */ public boolean mailFrom(String reversePath, ParameterList parameters) throws IOException { StringBuffer command = new StringBuffer(MAIL_FROM); command.append('<'); command.append(reversePath); command.append('>'); if (parameters != null) { command.append(SP); command.append(parameters); } send(command.toString()); switch (getAllResponses()) { case OK: case OK_NOT_LOCAL: case OK_UNVERIFIED: return true; default: return false; } } /** * Execute a RCPT command. * @param forwardPath the forward-path(recipient address) * @param parameters optional ESMTP parameters * @return true if successful, false otherwise */ public boolean rcptTo(String forwardPath, ParameterList parameters) throws IOException { StringBuffer command = new StringBuffer(RCPT_TO); command.append('<'); command.append(forwardPath); command.append('>'); if (parameters != null) { command.append(SP); command.append(parameters); } send(command.toString()); switch (getAllResponses()) { case OK: case OK_NOT_LOCAL: case OK_UNVERIFIED: return true; default: return false; } } /** * Requests an output stream to write message data to. * When the entire message has been written to the stream, the * <code>flush</code> method must be called on the stream. Until then no * further methods should be called on the connection. * Immediately after this procedure is complete, <code>finishData</code> * must be called to complete the transfer and determine its success. * @return a stream for writing messages to */ public OutputStream data() throws IOException { send(DATA); switch (getAllResponses()) { case SEND_DATA: return new MessageOutputStream(out); default: throw new ProtocolException(response); } } /** * Completes the DATA procedure. * @see #data * @return true id transfer was successful, false otherwise */ public boolean finishData() throws IOException { send(FINISH_DATA); switch (getAllResponses()) { case OK: return true; default: return false; } } /** * Aborts the current mail transaction. */ public void rset() throws IOException { send(RSET); if (getAllResponses() != OK) { throw new ProtocolException(response); } } // -- 3.5 Commands for Debugging Addresses -- /** * Returns a list of valid possibilities for the specified address, or * null on failure. * @param address a mailbox, or real name and mailbox */ public List vrfy(String address) throws IOException { String command = VRFY + ' ' + address;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -