docs: @Nonnull
    public ICommonsOrderedMap <IMutableEmailData, MailTransportError> send (@Nullable final Collection <IMutableEmailData> aAllMessages)
    {
      final ICommonsOrderedMap <IMutableEmailData, MailTransportError> aFailedMessages = new CommonsLinkedHashMap <> ();
      if (aAllMessages != null)
      {
        final ICommonsList <IMutableEmailData> aRemainingMessages = new CommonsArrayList <> (aAllMessages);
        MailSendException aExceptionToBeRemembered = null;
  
        try (final Transport aTransport = m_aSession.getTransport (m_bSMTPS ? SMTPS_PROTOCOL : SMTP_PROTOCOL))
        {
          // Add global listeners (if present)
          for (final ConnectionListener aConnectionListener : EmailGlobalSettings.getAllConnectionListeners ())
            aTransport.addConnectionListener (aConnectionListener);
  
          // Check if a detailed listener is present
          final ICommonsList <IEmailDataTransportListener> aEmailDataTransportListeners = EmailGlobalSettings.getAllEmailDataTransportListeners ();
  
          // Connect
          aTransport.connect (m_aSMTPSettings.getHostName (),
                              m_aSMTPSettings.getPort (),
                              m_aSMTPSettings.getUserName (),
                              m_aSMTPSettings.getPassword ());
  
          // For all messages
          for (final IMutableEmailData aEmailData : aAllMessages)
          {
            final MimeMessage aMimeMessage = new MimeMessage (m_aSession);
            try
            {
              // convert from IEmailData to MimeMessage
              MailConverter.fillMimeMessage (aMimeMessage, aEmailData, m_aSMTPSettings.getCharsetObj ());
  
              // Ensure a sent date is present
              if (aMimeMessage.getSentDate () == null)
                aMimeMessage.setSentDate (new Date ());
  
              // Get an explicitly specified message ID
              final String sMessageID = aMimeMessage.getMessageID ();
  
              // This creates a new message ID (besides other things)
              aMimeMessage.saveChanges ();
  
              if (sMessageID != null)
              {
                // Preserve explicitly specified message id...
                aMimeMessage.setHeader (HEADER_MESSAGE_ID, sMessageID);
              }
              aMimeMessage.setHeader ("X-Mailer", X_MAILER);
  
              if (LOGGER.isInfoEnabled ())
                LOGGER.info ("Delivering mail from " +
                                Arrays.toString (aMimeMessage.getFrom ()) +
                                " to " +
                                Arrays.toString (aMimeMessage.getAllRecipients ()) +
                                " with subject '" +
                                aMimeMessage.getSubject () +
                                "' and message ID '" +
                                aMimeMessage.getMessageID () +
                                "'");
  
              // Main transmit - always throws an exception
              aTransport.sendMessage (aMimeMessage, aMimeMessage.getAllRecipients ());
              throw new IllegalStateException ("Never expected to come beyong sendMessage!");
            }
            catch (final SendFailedException ex)
            {
              if (EmailGlobalSettings.isDebugSMTP ())
                LOGGER.error ("Error send mail - SendFailedException", ex);
  
              /*
               * Extract all addresses: the valid addresses to which the message
               * was sent, the valid address to which the message was not sent and
               * the invalid addresses
               */
              final ICommonsSet <String> aValidSent = CollectionHelper.newSetMapped (ex.getValidSentAddresses (),
                                                                                     Address::toString);
              final ICommonsSet <String> aValidUnsent = CollectionHelper.newSetMapped (ex.getValidUnsentAddresses (),
                                                                                       Address::toString);
              final ICommonsSet <String> aInvalid = CollectionHelper.newSetMapped (ex.getInvalidAddresses (),
                                                                                   Address::toString);
  
              final ICommonsList <MailSendDetails> aDetails = new CommonsArrayList <> ();
              Exception ex2;
              MessagingException bex = ex;
              while ((ex2 = bex.getNextException ()) != null && ex2 instanceof MessagingException)
              {
                if (ex2 instanceof SMTPAddressFailedException)
                {
                  final SMTPAddressFailedException ssfe = (SMTPAddressFailedException) ex2;
                  aDetails.add (new MailSendDetails (false,
                                                     ssfe.getAddress ().toString (),
                                                     ssfe.getCommand (),
                                                     ssfe.getMessage ().trim (),
                                                     ESMTPErrorCode.getFromIDOrDefault (ssfe.getReturnCode (),
                                                                                        ESMTPErrorCode.FALLBACK)));
                }
                else
                  if (ex2 instanceof SMTPAddressSucceededException)
                  {
                    final SMTPAddressSucceededException ssfe = (SMTPAddressSucceededException) ex2;
                    aDetails.add (new MailSendDetails (true,
                                                       ssfe.getAddress ().toString (),
                                                       ssfe.getCommand (),
                                                       ssfe.getMessage ().trim (),
                                                       ESMTPErrorCode.getFromIDOrDefault (ssfe.getReturnCode (),
                                                                                          ESMTPErrorCode.FALLBACK)));
                  }
  
                bex = (MessagingException) ex2;
              }
  
              // Map addresses to details
              final ICommonsOrderedSet <MailSendDetails> aValidSentExt = new CommonsLinkedHashSet <> ();
              final ICommonsOrderedSet <MailSendDetails> aValidUnsentExt = new CommonsLinkedHashSet <> ();
              final ICommonsOrderedSet <MailSendDetails> aInvalidExt = new CommonsLinkedHashSet <> ();
              for (final MailSendDetails aFailure : aDetails)
              {
                final String sAddress = aFailure.getAddress ();
                if (aValidSent.contains (sAddress))
                  aValidSentExt.add (aFailure);
                else
                  if (aValidUnsent.contains (sAddress))
                    aValidUnsentExt.add (aFailure);
                  else
                    aInvalidExt.add (aFailure);
              }
  
              final EmailDataTransportEvent aEvent = new EmailDataTransportEvent (m_aSMTPSettings,
                                                                                  aEmailData,
                                                                                  aMimeMessage,
                                                                                  aValidSentExt,
                                                                                  aValidUnsentExt,
                                                                                  aInvalidExt);
              if (aValidUnsent.isEmpty () && aInvalid.isEmpty () && aValidSent.isNotEmpty ())
              {
                // Message delivered
                for (final IEmailDataTransportListener aEmailDataTransportListener : aEmailDataTransportListeners)
                  aEmailDataTransportListener.messageDelivered (aEvent);
  
                // Remove message from list of remaining
                s_aStatsCountSuccess.increment ();
              }
              else
              {
                // Message not delivered
                for (final IEmailDataTransportListener aEmailDataTransportListener : aEmailDataTransportListeners)
                  aEmailDataTransportListener.messageNotDelivered (aEvent);
  
                // Sending exactly this message failed
                aFailedMessages.put (aEmailData, new MailTransportError (ex, aDetails));
                s_aStatsCountFailed.increment ();
              }
              // Remove message from list of remaining as we put it in the
              // failed message list manually in case of error
              aRemainingMessages.remove (aEmailData);
            }
            catch (final MessagingException ex)
            {
              if (EmailGlobalSettings.isDebugSMTP ())
                LOGGER.error ("Error send mail - MessagingException", ex);
  
              final ICommonsOrderedSet <MailSendDetails> aInvalid = new CommonsLinkedHashSet <> ();
              final Consumer <IEmailAddress> aConsumer = a -> aInvalid.add (new MailSendDetails (false,
                                                                                                 a.getAddress (),
                                                                                                 "<generic error>",
                                                                                                 ex.getMessage (),
                                                                                                 ESMTPErrorCode.FALLBACK));
              aEmailData.forEachTo (aConsumer);
              aEmailData.forEachCc (aConsumer);
              aEmailData.forEachBcc (aConsumer);
  
              final EmailDataTransportEvent aEvent = new EmailDataTransportEvent (m_aSMTPSettings,
                                                                                  aEmailData,
                                                                                  aMimeMessage,
                                                                                  new CommonsArrayList <> (),
                                                                                  new CommonsArrayList <> (),
                                                                                  aInvalid);
              // Message not delivered
              for (final IEmailDataTransportListener aEmailDataTransportListener : aEmailDataTransportListeners)
                aEmailDataTransportListener.messageNotDelivered (aEvent);
  
              // Sending exactly this message failed
              aFailedMessages.put (aEmailData, new MailTransportError (ex));
              // Remove message from list of remaining as we put it in the
              // failed message list manually
              aRemainingMessages.remove (aEmailData);
              s_aStatsCountFailed.increment ();
            }
          } // for all messages
        }
        catch (final AuthenticationFailedException ex)
        {
          // problem with the credentials
          aExceptionToBeRemembered = new MailSendException ("Mail server authentication failed", ex);
        }
        catch (final MessagingException ex)
        {
          if (WebExceptionHelper.isServerNotReachableConnection (ex.getCause ()))
            aExceptionToBeRemembered = new MailSendException ("Failed to connect to mail server: " +
                                                              ex.getCause ().getMessage ());
          else
            aExceptionToBeRemembered = new MailSendException ("Mail server connection failed", ex);
        }
        catch (final Exception ex)
        {
          // E.g. IllegalState from SMTPTransport ("Not connected")
          aExceptionToBeRemembered = new MailSendException ("Internal error sending mail", ex);
        }
        finally
        {
          // Was any message not sent
          if (aRemainingMessages.isNotEmpty ())
          {
            if (aExceptionToBeRemembered == null)
              aExceptionToBeRemembered = new MailSendException ("Internal error - messages are remaining but no Exception occurred!");
            for (final IMutableEmailData aRemainingMessage : aRemainingMessages)
              aFailedMessages.put (aRemainingMessage, new MailTransportError (aExceptionToBeRemembered));
          }
        }
      }
      return aFailedMessages;
    }