/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
* or LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package javax.mail;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.mail.event.*;
An abstract class that models a message transport.
Subclasses provide actual implementations.
Note that Transport
extends the Service
class, which provides many common methods for naming transports,
connecting to transports, and listening to connection events.
Author: John Mani, Max Spivak, Bill Shannon See Also:
/**
* An abstract class that models a message transport.
* Subclasses provide actual implementations. <p>
*
* Note that <code>Transport</code> extends the <code>Service</code>
* class, which provides many common methods for naming transports,
* connecting to transports, and listening to connection events.
*
* @author John Mani
* @author Max Spivak
* @author Bill Shannon
*
* @see javax.mail.Service
* @see javax.mail.event.ConnectionEvent
* @see javax.mail.event.TransportEvent
*/
public abstract class Transport extends Service {
Constructor.
Params: - session – Session object for this Transport.
- urlname – URLName object to be used for this Transport
/**
* Constructor.
*
* @param session Session object for this Transport.
* @param urlname URLName object to be used for this Transport
*/
public Transport(Session session, URLName urlname) {
super(session, urlname);
}
Send a message. The message will be sent to all recipient
addresses specified in the message (as returned from the
Message
method getAllRecipients
),
using message transports appropriate to each address. The
send
method calls the saveChanges
method on the message before sending it.
If any of the recipient addresses is detected to be invalid by
the Transport during message submission, a SendFailedException
is thrown. Clients can get more detail about the failure by examining
the exception. Whether or not the message is still sent successfully
to any valid addresses depends on the Transport implementation. See
SendFailedException for more details. Note also that success does
not imply that the message was delivered to the ultimate recipient,
as failures may occur in later stages of delivery. Once a Transport
accepts a message for delivery to a recipient, failures that occur later
should be reported to the user via another mechanism, such as
returning the undeliverable message.
In typical usage, a SendFailedException reflects an error detected
by the server. The details of the SendFailedException will usually
contain the error message from the server (such as an SMTP error
message). An address may be detected as invalid for a variety of
reasons - the address may not exist, the address may have invalid
syntax, the address may have exceeded its quota, etc.
Note that send
is a static method that creates and
manages its own connection. Any connection associated with any
Transport instance used to invoke this method is ignored and not
used. This method should only be invoked using the form
Transport.send(msg);
, and should never be invoked
using an instance variable.
Params: - msg – the message to send
Throws: - SendFailedException – if the message could not
be sent to some or any of the recipients.
- MessagingException – for other failures
See Also:
/**
* Send a message. The message will be sent to all recipient
* addresses specified in the message (as returned from the
* <code>Message</code> method <code>getAllRecipients</code>),
* using message transports appropriate to each address. The
* <code>send</code> method calls the <code>saveChanges</code>
* method on the message before sending it. <p>
*
* If any of the recipient addresses is detected to be invalid by
* the Transport during message submission, a SendFailedException
* is thrown. Clients can get more detail about the failure by examining
* the exception. Whether or not the message is still sent successfully
* to any valid addresses depends on the Transport implementation. See
* SendFailedException for more details. Note also that success does
* not imply that the message was delivered to the ultimate recipient,
* as failures may occur in later stages of delivery. Once a Transport
* accepts a message for delivery to a recipient, failures that occur later
* should be reported to the user via another mechanism, such as
* returning the undeliverable message. <p>
*
* In typical usage, a SendFailedException reflects an error detected
* by the server. The details of the SendFailedException will usually
* contain the error message from the server (such as an SMTP error
* message). An address may be detected as invalid for a variety of
* reasons - the address may not exist, the address may have invalid
* syntax, the address may have exceeded its quota, etc. <p>
*
* Note that <code>send</code> is a static method that creates and
* manages its own connection. Any connection associated with any
* Transport instance used to invoke this method is ignored and not
* used. This method should only be invoked using the form
* <code>Transport.send(msg);</code>, and should never be invoked
* using an instance variable.
*
* @param msg the message to send
* @exception SendFailedException if the message could not
* be sent to some or any of the recipients.
* @exception MessagingException for other failures
* @see Message#saveChanges
* @see Message#getAllRecipients
* @see #send(Message, Address[])
* @see javax.mail.SendFailedException
*/
public static void send(Message msg) throws MessagingException {
msg.saveChanges(); // do this first
send0(msg, msg.getAllRecipients(), null, null);
}
Send the message to the specified addresses, ignoring any
recipients specified in the message itself. The
send
method calls the saveChanges
method on the message before sending it.
Params: - msg – the message to send
- addresses – the addresses to which to send the message
Throws: - SendFailedException – if the message could not
be sent to some or any of the recipients.
- MessagingException – for other failures
See Also:
/**
* Send the message to the specified addresses, ignoring any
* recipients specified in the message itself. The
* <code>send</code> method calls the <code>saveChanges</code>
* method on the message before sending it. <p>
*
* @param msg the message to send
* @param addresses the addresses to which to send the message
* @exception SendFailedException if the message could not
* be sent to some or any of the recipients.
* @exception MessagingException for other failures
* @see Message#saveChanges
* @see #send(Message)
* @see javax.mail.SendFailedException
*/
public static void send(Message msg, Address[] addresses)
throws MessagingException {
msg.saveChanges();
send0(msg, addresses, null, null);
}
Send a message. The message will be sent to all recipient
addresses specified in the message (as returned from the
Message
method getAllRecipients
).
The send
method calls the saveChanges
method on the message before sending it.
Use the specified user name and password to authenticate to
the mail server.
Params: - msg – the message to send
- user – the user name
- password – this user's password
Throws: - SendFailedException – if the message could not
be sent to some or any of the recipients.
- MessagingException – for other failures
See Also: Since: JavaMail 1.5
/**
* Send a message. The message will be sent to all recipient
* addresses specified in the message (as returned from the
* <code>Message</code> method <code>getAllRecipients</code>).
* The <code>send</code> method calls the <code>saveChanges</code>
* method on the message before sending it. <p>
*
* Use the specified user name and password to authenticate to
* the mail server.
*
* @param msg the message to send
* @param user the user name
* @param password this user's password
* @exception SendFailedException if the message could not
* be sent to some or any of the recipients.
* @exception MessagingException for other failures
* @see Message#saveChanges
* @see #send(Message)
* @see javax.mail.SendFailedException
* @since JavaMail 1.5
*/
public static void send(Message msg,
String user, String password) throws MessagingException {
msg.saveChanges();
send0(msg, msg.getAllRecipients(), user, password);
}
Send the message to the specified addresses, ignoring any
recipients specified in the message itself. The
send
method calls the saveChanges
method on the message before sending it.
Use the specified user name and password to authenticate to
the mail server.
Params: - msg – the message to send
- addresses – the addresses to which to send the message
- user – the user name
- password – this user's password
Throws: - SendFailedException – if the message could not
be sent to some or any of the recipients.
- MessagingException – for other failures
See Also: Since: JavaMail 1.5
/**
* Send the message to the specified addresses, ignoring any
* recipients specified in the message itself. The
* <code>send</code> method calls the <code>saveChanges</code>
* method on the message before sending it. <p>
*
* Use the specified user name and password to authenticate to
* the mail server.
*
* @param msg the message to send
* @param addresses the addresses to which to send the message
* @param user the user name
* @param password this user's password
* @exception SendFailedException if the message could not
* be sent to some or any of the recipients.
* @exception MessagingException for other failures
* @see Message#saveChanges
* @see #send(Message)
* @see javax.mail.SendFailedException
* @since JavaMail 1.5
*/
public static void send(Message msg, Address[] addresses,
String user, String password) throws MessagingException {
msg.saveChanges();
send0(msg, addresses, user, password);
}
// send, but without the saveChanges
private static void send0(Message msg, Address[] addresses,
String user, String password) throws MessagingException {
if (addresses == null || addresses.length == 0)
throw new SendFailedException("No recipient addresses");
/*
* protocols is a map containing the addresses
* indexed by address type
*/
Map<String, List<Address>> protocols
= new HashMap<>();
// Lists of addresses
List<Address> invalid = new ArrayList<>();
List<Address> validSent = new ArrayList<>();
List<Address> validUnsent = new ArrayList<>();
for (int i = 0; i < addresses.length; i++) {
// is this address type already in the map?
if (protocols.containsKey(addresses[i].getType())) {
List<Address> v = protocols.get(addresses[i].getType());
v.add(addresses[i]);
} else {
// need to add a new protocol
List<Address> w = new ArrayList<>();
w.add(addresses[i]);
protocols.put(addresses[i].getType(), w);
}
}
int dsize = protocols.size();
if (dsize == 0)
throw new SendFailedException("No recipient addresses");
Session s = (msg.session != null) ? msg.session :
Session.getDefaultInstance(System.getProperties(), null);
Transport transport;
/*
* Optimize the case of a single protocol.
*/
if (dsize == 1) {
transport = s.getTransport(addresses[0]);
try {
if (user != null)
transport.connect(user, password);
else
transport.connect();
transport.sendMessage(msg, addresses);
} finally {
transport.close();
}
return;
}
/*
* More than one protocol. Have to do them one at a time
* and collect addresses and chain exceptions.
*/
MessagingException chainedEx = null;
boolean sendFailed = false;
for(List<Address> v : protocols.values()) {
Address[] protaddresses = new Address[v.size()];
v.toArray(protaddresses);
// Get a Transport that can handle this address type.
if ((transport = s.getTransport(protaddresses[0])) == null) {
// Could not find an appropriate Transport ..
// Mark these addresses invalid.
for (int j = 0; j < protaddresses.length; j++)
invalid.add(protaddresses[j]);
continue;
}
try {
transport.connect();
transport.sendMessage(msg, protaddresses);
} catch (SendFailedException sex) {
sendFailed = true;
// chain the exception we're catching to any previous ones
if (chainedEx == null)
chainedEx = sex;
else
chainedEx.setNextException(sex);
// retrieve invalid addresses
Address[] a = sex.getInvalidAddresses();
if (a != null)
for (int j = 0; j < a.length; j++)
invalid.add(a[j]);
// retrieve validSent addresses
a = sex.getValidSentAddresses();
if (a != null)
for (int k = 0; k < a.length; k++)
validSent.add(a[k]);
// retrieve validUnsent addresses
Address[] c = sex.getValidUnsentAddresses();
if (c != null)
for (int l = 0; l < c.length; l++)
validUnsent.add(c[l]);
} catch (MessagingException mex) {
sendFailed = true;
// chain the exception we're catching to any previous ones
if (chainedEx == null)
chainedEx = mex;
else
chainedEx.setNextException(mex);
} finally {
transport.close();
}
}
// done with all protocols. throw exception if something failed
if (sendFailed || invalid.size() != 0 || validUnsent.size() != 0) {
Address[] a = null, b = null, c = null;
// copy address lists into arrays
if (validSent.size() > 0) {
a = new Address[validSent.size()];
validSent.toArray(a);
}
if (validUnsent.size() > 0) {
b = new Address[validUnsent.size()];
validUnsent.toArray(b);
}
if (invalid.size() > 0) {
c = new Address[invalid.size()];
invalid.toArray(c);
}
throw new SendFailedException("Sending failed", chainedEx,
a, b, c);
}
}
Send the Message to the specified list of addresses. An appropriate
TransportEvent indicating the delivery status is delivered to any
TransportListener registered on this Transport. Also, if any of
the addresses is invalid, a SendFailedException is thrown.
Whether or not the message is still sent succesfully to
any valid addresses depends on the Transport implementation.
Unlike the static send
method, the sendMessage
method does not call the saveChanges
method on
the message; the caller should do so.
Params: - msg – The Message to be sent
- addresses – array of addresses to send this message to
Throws: - SendFailedException – if the send failed because of
invalid addresses.
- MessagingException – if the connection is dead or not in the
connected state
See Also:
/**
* Send the Message to the specified list of addresses. An appropriate
* TransportEvent indicating the delivery status is delivered to any
* TransportListener registered on this Transport. Also, if any of
* the addresses is invalid, a SendFailedException is thrown.
* Whether or not the message is still sent succesfully to
* any valid addresses depends on the Transport implementation. <p>
*
* Unlike the static <code>send</code> method, the <code>sendMessage</code>
* method does <em>not</em> call the <code>saveChanges</code> method on
* the message; the caller should do so.
*
* @param msg The Message to be sent
* @param addresses array of addresses to send this message to
* @see javax.mail.event.TransportEvent
* @exception SendFailedException if the send failed because of
* invalid addresses.
* @exception MessagingException if the connection is dead or not in the
* connected state
*/
public abstract void sendMessage(Message msg, Address[] addresses)
throws MessagingException;
// Vector of Transport listeners
private volatile Vector<TransportListener> transportListeners = null;
Add a listener for Transport events.
The default implementation provided here adds this listener
to an internal list of TransportListeners.
Params: - l – the Listener for Transport events
See Also:
/**
* Add a listener for Transport events. <p>
*
* The default implementation provided here adds this listener
* to an internal list of TransportListeners.
*
* @param l the Listener for Transport events
* @see javax.mail.event.TransportEvent
*/
public synchronized void addTransportListener(TransportListener l) {
if (transportListeners == null)
transportListeners = new Vector<>();
transportListeners.addElement(l);
}
Remove a listener for Transport events.
The default implementation provided here removes this listener
from the internal list of TransportListeners.
Params: - l – the listener
See Also:
/**
* Remove a listener for Transport events. <p>
*
* The default implementation provided here removes this listener
* from the internal list of TransportListeners.
*
* @param l the listener
* @see #addTransportListener
*/
public synchronized void removeTransportListener(TransportListener l) {
if (transportListeners != null)
transportListeners.removeElement(l);
}
Notify all TransportListeners. Transport implementations are
expected to use this method to broadcast TransportEvents.
The provided default implementation queues the event into
an internal event queue. An event dispatcher thread dequeues
events from the queue and dispatches them to the registered
TransportListeners. Note that the event dispatching occurs
in a separate thread, thus avoiding potential deadlock problems.
Params: - type – the TransportEvent type
- validSent – valid addresses to which message was sent
- validUnsent – valid addresses to which message was not sent
- invalid – the invalid addresses
- msg – the message
/**
* Notify all TransportListeners. Transport implementations are
* expected to use this method to broadcast TransportEvents.<p>
*
* The provided default implementation queues the event into
* an internal event queue. An event dispatcher thread dequeues
* events from the queue and dispatches them to the registered
* TransportListeners. Note that the event dispatching occurs
* in a separate thread, thus avoiding potential deadlock problems.
*
* @param type the TransportEvent type
* @param validSent valid addresses to which message was sent
* @param validUnsent valid addresses to which message was not sent
* @param invalid the invalid addresses
* @param msg the message
*/
protected void notifyTransportListeners(int type, Address[] validSent,
Address[] validUnsent,
Address[] invalid, Message msg) {
if (transportListeners == null)
return;
TransportEvent e = new TransportEvent(this, type, validSent,
validUnsent, invalid, msg);
queueEvent(e, transportListeners);
}
}