public class SMTPTransport extends Transport
See the com.sun.mail.smtp package documentation for further information on the SMTP protocol provider.
This class includes many protected methods that allow a subclass to
extend this class and add support for non-standard SMTP commands.
The issueCommand(java.lang.String, int)
and sendCommand(java.lang.String)
methods can be
used to send simple SMTP commands. Other methods such as the
mailFrom()
and data()
methods can be overridden to
insert new commands before or after the corresponding SMTP commands.
For example, a subclass could do this to send the XACT command
before sending the DATA command:
protected OutputStream data() throws MessagingException { if (supportsExtension("XACCOUNTING")) issueCommand("XACT", 25); return super.data(); }
ConnectionEvent
,
TransportEvent
Modifier and Type | Class and Description |
---|---|
private class |
SMTPTransport.Authenticator
Abstract base class for SMTP authentication mechanism implementations.
|
private class |
SMTPTransport.BDATOutputStream
An SMTPOutputStream that wraps a ChunkedOutputStream.
|
private class |
SMTPTransport.ChunkedOutputStream
An OutputStream that buffers data in chunks and uses the
RFC 3030 BDAT SMTP command to send each chunk.
|
private class |
SMTPTransport.DigestMD5Authenticator
Perform the authentication handshake for DIGEST-MD5 authentication.
|
private class |
SMTPTransport.LoginAuthenticator
Perform the authentication handshake for LOGIN authentication.
|
private class |
SMTPTransport.NtlmAuthenticator
Perform the authentication handshake for NTLM authentication.
|
private class |
SMTPTransport.OAuth2Authenticator
Perform the authentication handshake for XOAUTH2 authentication.
|
private class |
SMTPTransport.PlainAuthenticator
Perform the authentication handshake for PLAIN authentication.
|
Modifier and Type | Field and Description |
---|---|
private Address[] |
addresses |
private boolean |
allowutf8 |
private java.util.Map<java.lang.String,SMTPTransport.Authenticator> |
authenticators |
private java.lang.String |
authorizationID |
private int |
chunkSize |
private static byte[] |
CRLF |
private SMTPOutputStream |
dataStream |
private boolean |
debugpassword |
private boolean |
debugusername |
private java.lang.String |
defaultAuthenticationMechanisms |
private int |
defaultPort |
private boolean |
enableSASL |
private MessagingException |
exception |
private java.util.Hashtable<java.lang.String,java.lang.String> |
extMap |
private static char[] |
hexchar |
private java.lang.String |
host |
private static java.lang.String[] |
ignoreList
Headers that should not be included when sending
|
private Address[] |
invalidAddr |
private boolean |
isSSL |
private int |
lastReturnCode |
private java.lang.String |
lastServerResponse |
private LineInputStream |
lineInputStream |
private java.lang.String |
localHostName |
private MailLogger |
logger |
private MimeMessage |
message |
private java.lang.String |
name |
private boolean |
noauthdebug |
private boolean |
noopStrict |
private boolean |
notificationDone |
private java.lang.String |
ntlmDomain |
private boolean |
quitWait |
private boolean |
reportSuccess |
private boolean |
requireStartTLS |
private SaslAuthenticator |
saslAuthenticator |
private java.lang.String[] |
saslMechanisms |
private java.lang.String |
saslRealm |
private boolean |
sendPartiallyFailed |
private java.io.BufferedInputStream |
serverInput |
private java.io.OutputStream |
serverOutput |
private java.net.Socket |
serverSocket |
private TraceInputStream |
traceInput |
private MailLogger |
traceLogger |
private TraceOutputStream |
traceOutput |
private static java.lang.String |
UNKNOWN |
private static java.lang.String[] |
UNKNOWN_SA |
private boolean |
useCanonicalHostName |
private boolean |
useRset |
private boolean |
useStartTLS |
private Address[] |
validSentAddr |
private Address[] |
validUnsentAddr |
Modifier | Constructor and Description |
---|---|
|
SMTPTransport(Session session,
URLName urlname)
Constructor that takes a Session object and a URLName
that represents a specific SMTP server.
|
protected |
SMTPTransport(Session session,
URLName urlname,
java.lang.String name,
boolean isSSL)
Constructor used by this class and by SMTPSSLTransport subclass.
|
Modifier and Type | Method and Description |
---|---|
private void |
addressesFailed()
The send failed, fix the address arrays to report the failure correctly.
|
private boolean |
authenticate(java.lang.String user,
java.lang.String passwd)
Authenticate to the server.
|
protected java.io.OutputStream |
bdat()
Return a stream that will use the SMTP BDAT command to send data.
|
protected void |
checkConnected()
Check if we're in the connected state.
|
void |
close()
Close the Transport and terminate the connection to the server.
|
private void |
closeConnection() |
void |
connect(java.net.Socket socket)
Start the SMTP protocol on the given socket, which was already
connected by the caller.
|
private boolean |
convertTo8Bit(MimePart part)
If the Part is a text part and has a Content-Transfer-Encoding
of "quoted-printable" or "base64", and it obeys the rules for
"8bit" encoding, change the encoding to "8bit".
|
protected java.io.OutputStream |
data()
Send the
DATA command to the SMTP host and return
an OutputStream to which the data is to be written. |
protected boolean |
ehlo(java.lang.String domain)
Issue the
EHLO command. |
private void |
expandGroups()
Expand any group addresses.
|
protected void |
finalize()
Stop the event dispatcher thread so the queue can be garbage collected.
|
protected void |
finishBdat()
Terminate the sent data.
|
protected void |
finishData()
Terminate the sent data.
|
java.lang.String |
getAuthorizationId()
Gets the authorization ID to be used for authentication.
|
java.lang.String |
getExtensionParameter(java.lang.String ext)
Return the parameter the server provided for the specified
service extension, or null if the extension isn't supported.
|
int |
getLastReturnCode()
Return the return code from the last response we got from the server.
|
java.lang.String |
getLastServerResponse()
Return the last response we got from the server.
|
java.lang.String |
getLocalHost()
Get the name of the local host, for use in the EHLO and HELO commands.
|
boolean |
getNoopStrict()
Is the NOOP command required to return a response code
of 250 to indicate success?
|
java.lang.String |
getNTLMDomain()
Gets the NTLM domain to be used for NTLM authentication.
|
boolean |
getReportSuccess()
Should we report even successful sends by throwing an exception?
If so, a
SendFailedException will always be thrown and
an SMTPAddressSucceededException will be included in the exception
chain for each successful address, along with the usual
SMTPAddressFailedException for each unsuccessful address. |
boolean |
getRequireStartTLS()
Should we require the STARTTLS command to secure the connection?
|
boolean |
getSASLEnabled()
Is SASL authentication enabled?
|
java.lang.String[] |
getSASLMechanisms()
Get the list of SASL mechanisms to consider if SASL authentication
is enabled.
|
java.lang.String |
getSASLRealm()
Gets the SASL realm to be used for DIGEST-MD5 authentication.
|
boolean |
getStartTLS()
Should we use the STARTTLS command to secure the connection
if the server supports it?
|
boolean |
getUseCanonicalHostName()
Should SASL use the canonical host name?
|
boolean |
getUseRset()
Should we use the RSET command instead of the NOOP command
in the @{link #isConnected isConnected} method?
|
protected void |
helo(java.lang.String domain)
Issue the
HELO command. |
private void |
initStreams() |
private boolean |
is8Bit(java.io.InputStream is)
Check whether the data in the given InputStream follows the
rules for 8bit text.
|
boolean |
isConnected()
Check whether the transport is connected.
|
private boolean |
isNotLastLine(java.lang.String line) |
boolean |
isSSL()
Is this Transport using SSL to connect to the server?
|
void |
issueCommand(java.lang.String cmd,
int expect)
Send the command to the server.
|
private void |
issueSendCommand(java.lang.String cmd,
int expect)
Issue a command that's part of sending a message.
|
private boolean |
isTracing()
Is protocol tracing enabled?
|
protected void |
mailFrom()
Issue the
MAIL FROM: command to start sending a message. |
private java.lang.String |
normalizeAddress(java.lang.String addr) |
protected void |
notifyTransportListeners(int type,
Address[] validSent,
Address[] validUnsent,
Address[] invalid,
Message msg)
Notify all TransportListeners.
|
private void |
openServer()
Start the protocol to the server on serverSocket,
assumed to be provided and connected by the caller.
|
private void |
openServer(java.lang.String host,
int port)
Connect to host on port and start the SMTP protocol.
|
protected boolean |
protocolConnect(java.lang.String host,
int port,
java.lang.String user,
java.lang.String password)
Performs the actual protocol-specific connection attempt.
|
protected void |
rcptTo()
Sends each address to the SMTP host using the
RCPT TO:
command and copies the address either into
the validSentAddr or invalidAddr arrays. |
protected int |
readServerResponse()
Reads server reponse returning the
returnCode
as the number. |
private void |
resumeTracing()
Resume protocol tracing, if it was enabled to begin with.
|
private boolean |
sasllogin(java.lang.String[] allowed,
java.lang.String realm,
java.lang.String authzid,
java.lang.String u,
java.lang.String p)
SASL-based login.
|
private void |
sendCommand(byte[] cmdBytes) |
protected void |
sendCommand(java.lang.String cmd)
Sends command
cmd to the server terminating
it with CRLF . |
void |
sendMessage(Message message,
Address[] addresses)
Send the Message to the specified list of addresses.
|
private void |
sendMessageEnd() |
private void |
sendMessageStart(java.lang.String subject) |
void |
setAuthorizationID(java.lang.String authzid)
Sets the authorization ID to be used for authentication.
|
void |
setLocalHost(java.lang.String localhost)
Set the name of the local host, for use in the EHLO and HELO commands.
|
void |
setNoopStrict(boolean noopStrict)
Set whether the NOOP command is required to return a response code
of 250 to indicate success.
|
void |
setNTLMDomain(java.lang.String ntlmDomain)
Sets the NTLM domain to be used for NTLM authentication.
|
void |
setReportSuccess(boolean reportSuccess)
Set whether successful sends should be reported by throwing
an exception.
|
void |
setRequireStartTLS(boolean requireStartTLS)
Set whether the STARTTLS command should be required.
|
void |
setSASLEnabled(boolean enableSASL)
Set whether SASL authentication is enabled.
|
void |
setSASLMechanisms(java.lang.String[] mechanisms)
Set the list of SASL mechanisms to consider if SASL authentication
is enabled.
|
void |
setSASLRealm(java.lang.String saslRealm)
Sets the SASL realm to be used for DIGEST-MD5 authentication.
|
void |
setStartTLS(boolean useStartTLS)
Set whether the STARTTLS command should be used.
|
void |
setUseCanonicalHostName(boolean useCanonicalHostName)
Set whether SASL should use the canonical host name.
|
void |
setUseRset(boolean useRset)
Set whether the RSET command should be used instead of the
NOOP command in the @{link #isConnected isConnected} method.
|
protected int |
simpleCommand(byte[] cmd)
Send the command to the server and return the response code
from the server.
|
int |
simpleCommand(java.lang.String cmd)
Send the command to the server and return the response code
from the server.
|
protected void |
startTLS()
Issue the
STARTTLS command and switch the socket to
TLS mode if it succeeds. |
protected boolean |
supportsAuthentication(java.lang.String auth)
Does the server we're connected to support the specified
authentication mechanism? Uses the extension information
returned by the server from the EHLO command.
|
boolean |
supportsExtension(java.lang.String ext)
Return true if the SMTP server supports the specified service
extension.
|
private void |
suspendTracing()
Temporarily turn off protocol tracing, e.g., to prevent
tracing the authentication sequence, including the password.
|
private byte[] |
toBytes(java.lang.String s)
Convert the String to either ASCII or UTF-8 bytes
depending on allowutf8.
|
private java.lang.String |
tracePassword(java.lang.String password) |
private java.lang.String |
traceUser(java.lang.String user) |
protected static java.lang.String |
xtext(java.lang.String s)
Convert a string to RFC 1891 xtext format.
|
protected static java.lang.String |
xtext(java.lang.String s,
boolean utf8)
Like xtext(s), but allow UTF-8 strings.
|
addTransportListener, removeTransportListener, send, send, send, send
addConnectionListener, connect, connect, connect, connect, getURLName, notifyConnectionListeners, queueEvent, removeConnectionListener, setConnected, setURLName, toString
private java.lang.String name
private int defaultPort
private boolean isSSL
private java.lang.String host
private MimeMessage message
private Address[] addresses
private Address[] validSentAddr
private Address[] validUnsentAddr
private Address[] invalidAddr
private boolean sendPartiallyFailed
private MessagingException exception
private SMTPOutputStream dataStream
private java.util.Hashtable<java.lang.String,java.lang.String> extMap
private java.util.Map<java.lang.String,SMTPTransport.Authenticator> authenticators
private java.lang.String defaultAuthenticationMechanisms
private boolean quitWait
private java.lang.String saslRealm
private java.lang.String authorizationID
private boolean enableSASL
private boolean useCanonicalHostName
private java.lang.String[] saslMechanisms
private java.lang.String ntlmDomain
private boolean reportSuccess
private boolean useStartTLS
private boolean requireStartTLS
private boolean useRset
private boolean noopStrict
private MailLogger logger
private MailLogger traceLogger
private java.lang.String localHostName
private java.lang.String lastServerResponse
private int lastReturnCode
private boolean notificationDone
private SaslAuthenticator saslAuthenticator
private boolean noauthdebug
private boolean debugusername
private boolean debugpassword
private boolean allowutf8
private int chunkSize
private static final java.lang.String[] ignoreList
private static final byte[] CRLF
private static final java.lang.String UNKNOWN
private static final java.lang.String[] UNKNOWN_SA
private java.io.BufferedInputStream serverInput
private LineInputStream lineInputStream
private java.io.OutputStream serverOutput
private java.net.Socket serverSocket
private TraceInputStream traceInput
private TraceOutputStream traceOutput
private static char[] hexchar
public SMTPTransport(Session session, URLName urlname)
session
- the Sessionurlname
- the URLName of this transportprotected SMTPTransport(Session session, URLName urlname, java.lang.String name, boolean isSSL)
session
- the Sessionurlname
- the URLName of this transportname
- the protocol name of this transportisSSL
- use SSL to connect?public java.lang.String getLocalHost()
public void setLocalHost(java.lang.String localhost)
localhost
- the local host namepublic void connect(java.net.Socket socket) throws MessagingException
socket
- the already connected socketMessagingException
- for failurespublic java.lang.String getAuthorizationId()
public void setAuthorizationID(java.lang.String authzid)
authzid
- the authorization ID to use for
authentication.public boolean getSASLEnabled()
public void setSASLEnabled(boolean enableSASL)
enableSASL
- should we enable SASL authentication?public java.lang.String getSASLRealm()
public void setSASLRealm(java.lang.String saslRealm)
saslRealm
- the name of the realm to use for
SASL authentication.public boolean getUseCanonicalHostName()
public void setUseCanonicalHostName(boolean useCanonicalHostName)
useCanonicalHostName
- should SASL use the canonical host name?public java.lang.String[] getSASLMechanisms()
public void setSASLMechanisms(java.lang.String[] mechanisms)
mechanisms
- the array of SASL mechanisms to considerpublic java.lang.String getNTLMDomain()
public void setNTLMDomain(java.lang.String ntlmDomain)
ntlmDomain
- the name of the domain to use for
NTLM authentication.public boolean getReportSuccess()
SendFailedException
will always be thrown and
an SMTPAddressSucceededException
will be included in the exception
chain for each successful address, along with the usual
SMTPAddressFailedException
for each unsuccessful address.public void setReportSuccess(boolean reportSuccess)
reportSuccess
- should we throw an exception on success?public boolean getStartTLS()
public void setStartTLS(boolean useStartTLS)
useStartTLS
- should we use the STARTTLS command?public boolean getRequireStartTLS()
public void setRequireStartTLS(boolean requireStartTLS)
requireStartTLS
- should we require the STARTTLS command?public boolean isSSL()
public boolean getUseRset()
public void setUseRset(boolean useRset)
useRset
- should we use the RSET command?public boolean getNoopStrict()
public void setNoopStrict(boolean noopStrict)
noopStrict
- is NOOP required to return 250?public java.lang.String getLastServerResponse()
public int getLastReturnCode()
protected boolean protocolConnect(java.lang.String host, int port, java.lang.String user, java.lang.String password) throws MessagingException
Unless mail.smtp.ehlo is set to false, we'll try to identify ourselves using the ESMTP command EHLO. If mail.smtp.auth is set to true, we insist on having a username and password, and will try to authenticate ourselves if the server supports the AUTH extension (RFC 2554).
protocolConnect
in class Service
host
- the name of the host to connect toport
- the port to use (-1 means use default port)user
- the name of the user to login aspassword
- the user's passwordMessagingException
- for non-authentication failuresprivate boolean authenticate(java.lang.String user, java.lang.String passwd) throws MessagingException
MessagingException
private boolean sasllogin(java.lang.String[] allowed, java.lang.String realm, java.lang.String authzid, java.lang.String u, java.lang.String p) throws MessagingException
allowed
- the allowed SASL mechanismsrealm
- the SASL realmauthzid
- the authorization IDu
- the user name for authenticationp
- the password for authenticationMessagingException
- for failurespublic void sendMessage(Message message, Address[] addresses) throws MessagingException, SendFailedException
If all the addresses
succeed the SMTP check
using the RCPT TO:
command, we attempt to send the message.
A TransportEvent of type MESSAGE_DELIVERED is fired indicating the
successful submission of a message to the SMTP host.
If some of the addresses
fail the SMTP check,
and the mail.smtp.sendpartial
property is not set,
sending is aborted. The TransportEvent of type MESSAGE_NOT_DELIVERED
is fired containing the valid and invalid addresses. The
SendFailedException is also thrown.
If some of the addresses
fail the SMTP check,
and the mail.smtp.sendpartial
property is set to true,
the message is sent. The TransportEvent of type
MESSAGE_PARTIALLY_DELIVERED
is fired containing the valid and invalid addresses. The
SMTPSendFailedException is also thrown.
MessagingException is thrown if the message can't write out
an RFC822-compliant stream using its writeTo
method.
sendMessage
in class Transport
message
- The MimeMessage to be sentaddresses
- List of addresses to send this message toSMTPSendFailedException
- if the send failed because of
an SMTP command errorSendFailedException
- if the send failed because of
invalid addresses.MessagingException
- if the connection is dead
or not in the connected state or if the message is
not a MimeMessage.TransportEvent
private void addressesFailed()
public void close() throws MessagingException
close
in interface java.lang.AutoCloseable
close
in class Service
MessagingException
- for errors while closingConnectionEvent
private void closeConnection() throws MessagingException
MessagingException
public boolean isConnected()
isConnected
in class Service
protected void notifyTransportListeners(int type, Address[] validSent, Address[] validUnsent, Address[] invalid, Message msg)
notifyTransportListeners
in class Transport
type
- the TransportEvent typevalidSent
- valid addresses to which message was sentvalidUnsent
- valid addresses to which message was not sentinvalid
- the invalid addressesmsg
- the messageprivate void expandGroups()
private boolean convertTo8Bit(MimePart part)
private boolean is8Bit(java.io.InputStream is)
protected void finalize() throws java.lang.Throwable
Service
protected void helo(java.lang.String domain) throws MessagingException
HELO
command.domain
- our domainMessagingException
- for failuresprotected boolean ehlo(java.lang.String domain) throws MessagingException
EHLO
command.
Collect the returned list of service extensions.domain
- our domainMessagingException
- for failuresprotected void mailFrom() throws MessagingException
MAIL FROM:
command to start sending a message. Gets the sender's address in the following order:
MessagingException
- for failuresprotected void rcptTo() throws MessagingException
RCPT TO:
command and copies the address either into
the validSentAddr or invalidAddr arrays.
Sets the sendFailed
flag to true if any addresses failed.MessagingException
- for failuresprotected java.io.OutputStream data() throws MessagingException
DATA
command to the SMTP host and return
an OutputStream to which the data is to be written.MessagingException
- for failuresprotected void finishData() throws java.io.IOException, MessagingException
java.io.IOException
- for I/O errorsMessagingException
- for other failuresprotected java.io.OutputStream bdat() throws MessagingException
MessagingException
- for failuresprotected void finishBdat() throws java.io.IOException, MessagingException
java.io.IOException
- for I/O errorsMessagingException
- for other failuresprotected void startTLS() throws MessagingException
STARTTLS
command and switch the socket to
TLS mode if it succeeds.MessagingException
- for failuresprivate void openServer(java.lang.String host, int port) throws MessagingException
MessagingException
private void openServer() throws MessagingException
MessagingException
private void initStreams() throws java.io.IOException
java.io.IOException
private boolean isTracing()
private void suspendTracing()
private void resumeTracing()
public void issueCommand(java.lang.String cmd, int expect) throws MessagingException
cmd
- the command to sendexpect
- the expected response code (-1 means don't care)MessagingException
- for failuresprivate void issueSendCommand(java.lang.String cmd, int expect) throws MessagingException
MessagingException
public int simpleCommand(java.lang.String cmd) throws MessagingException
cmd
- the commandMessagingException
- for failuresprotected int simpleCommand(byte[] cmd) throws MessagingException
cmd
- the commandMessagingException
- for failuresprotected void sendCommand(java.lang.String cmd) throws MessagingException
cmd
to the server terminating
it with CRLF
.cmd
- the commandMessagingException
- for failuresprivate void sendCommand(byte[] cmdBytes) throws MessagingException
MessagingException
protected int readServerResponse() throws MessagingException
returnCode
as the number. Returns -1 on failure. Sets
lastServerResponse
and lastReturnCode
.MessagingException
- for failuresprotected void checkConnected()
java.lang.IllegalStateException
- if not connectedprivate boolean isNotLastLine(java.lang.String line)
private java.lang.String normalizeAddress(java.lang.String addr)
public boolean supportsExtension(java.lang.String ext)
ext
- the service extension namepublic java.lang.String getExtensionParameter(java.lang.String ext)
ext
- the service extension nameprotected boolean supportsAuthentication(java.lang.String auth)
auth
- the authentication mechanismprotected static java.lang.String xtext(java.lang.String s)
xtext = *( xchar / hexchar ) xchar = any ASCII CHAR between "!" (33) and "~" (126) inclusive, except for "+" and "=". ; "hexchar"s are intended to encode octets that cannot appear ; as ASCII characters within an esmtp-value. hexchar = ASCII "+" immediately followed by two upper case hexadecimal digits
s
- the string to convertprotected static java.lang.String xtext(java.lang.String s, boolean utf8)
s
- the string to convertutf8
- convert string to UTF-8 first?private java.lang.String traceUser(java.lang.String user)
private java.lang.String tracePassword(java.lang.String password)
private byte[] toBytes(java.lang.String s)
private void sendMessageStart(java.lang.String subject)
private void sendMessageEnd()