private static void sendInternal()

in geronimo-mail_2.1_spec/src/main/java/jakarta/mail/Transport.java [69:181]


    private static void sendInternal(final Message message, final Address[] addresses, final String user, final String password) throws MessagingException {
        
        if (addresses == null || addresses.length == 0) {
            throw new SendFailedException("No recipient addresses");
        }
        
        final Session session = message.session;
        final Map<Transport, List<Address>> msgsByTransport = new HashMap<Transport, List<Address>>();
        for (int i = 0; i < addresses.length; i++) {
            final Address address = addresses[i];
            final Transport transport = session.getTransport(address);
            List<Address> addrs = msgsByTransport.get(transport);
            if (addrs == null) {
                addrs = new ArrayList<Address>();
                msgsByTransport.put(transport, addrs);
            }
            addrs.add(address);
        }

        message.saveChanges();

        // Since we might be sending to multiple protocols, we need to catch and process each exception
        // when we send and then throw a new SendFailedException when everything is done.  Unfortunately, this
        // also means unwrapping the information in any SendFailedExceptions we receive and building
        // composite failed list.
        MessagingException chainedException = null;
        final List<Address> sentAddresses = new ArrayList<Address>();
        final List<Address> unsentAddresses = new ArrayList<Address>();
        final List<Address> invalidAddresses = new ArrayList<Address>();


        for (final Iterator<Entry<Transport, List<Address>>> i = msgsByTransport.entrySet().iterator(); i.hasNext();) {
            final Entry<Transport, List<Address>> entry = i.next();
            final Transport transport = entry.getKey();
            final List<Address> addrs = entry.getValue();
            try {
                // we MUST connect to the transport before attempting to send.
                if(user != null) {
                    transport.connect(user, password);
                } else {
                    transport.connect();
                }
                transport.sendMessage(message, addrs.toArray(new Address[addrs.size()]));
                // if we have to throw an exception because of another failure, these addresses need to
                // be in the valid list.  Since we succeeded here, we can add these now.
                sentAddresses.addAll(addrs);
            } catch (final SendFailedException e) {
                // a true send failure.  The exception contains a wealth of information about
                // the failures, including a potential chain of exceptions explaining what went wrong.  We're
                // going to send a new one of these, so we need to merge the information.

                // add this to our exception chain
                if (chainedException == null) {
                    chainedException = e;
                }
                else {
                    chainedException.setNextException(e);
                }

                // now extract each of the address categories from
                Address[] exAddrs = e.getValidSentAddresses();
                if (exAddrs != null) {
                    for (int j = 0; j < exAddrs.length; j++) {
                        sentAddresses.add(exAddrs[j]);
                    }
                }

                exAddrs = e.getValidUnsentAddresses();
                if (exAddrs != null) {
                    for (int j = 0; j < exAddrs.length; j++) {
                        unsentAddresses.add(exAddrs[j]);
                    }
                }

                exAddrs = e.getInvalidAddresses();
                if (exAddrs != null) {
                    for (int j = 0; j < exAddrs.length; j++) {
                        invalidAddresses.add(exAddrs[j]);
                    }
                }

            } catch (final MessagingException e) {
                // add this to our exception chain
                if (chainedException == null) {
                    chainedException = e;
                }
                else {
                    chainedException.setNextException(e);
                }
            }
            finally {
                transport.close();
            }
        }

        // if we have an exception chain then we need to throw a new exception giving the failure
        // information.
        if (chainedException != null) {
            // if we're only sending to a single transport (common), and we received a SendFailedException
            // as a result, then we have a fully formed exception already.  Rather than wrap this in another
            // exception, we can just rethrow the one we have.
            if (msgsByTransport.size() == 1 && chainedException instanceof SendFailedException) {
                throw chainedException;
            }

            // create our lists for notification and exception reporting from this point on.
            final Address[] sent = sentAddresses.toArray(new Address[0]);
            final Address[] unsent = unsentAddresses.toArray(new Address[0]);
            final Address[] invalid = invalidAddresses.toArray(new Address[0]);

            throw new SendFailedException("Send failure", chainedException, sent, unsent, invalid);
        }
    }