001package votorola.g.mail; // Copyright 2007-2009, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.
002
003import com.sun.mail.smtp.*;
004import java.util.*;
005import java.util.logging.*; import votorola.g.logging.*;
006import javax.mail.*;
007import votorola.g.lang.*;
008import votorola.g.script.*;
009
010
011/** A sender of messages, with access to an SMTP mail transfer service.
012  */
013public final @ThreadRestricted class MailSender
014{
015
016
017     /** Constructs a MailSender.
018       */
019     public MailSender( final SMTPTransportX.ConstructionContext cc )
020       throws MisconfigurationException
021     {
022        authentication = cc.getAuthenticationMethod();
023        serverName = cc.getServerName();
024        serverPort = cc.getServerPort();
025
026        final String enc = cc.getEncryptionMethod();
027        if( enc == null ) protocolID = "smtp";
028        else if( "ssl".equals( enc )) protocolID = "smtps";
029        else throw new MisconfigurationException( "unrecognized encryption method: " + enc, cc.startupConfigurationFile() );
030     }
031
032
033
034   // ------------------------------------------------------------------------------------
035
036
037    /** Returns true if this mail sender is to run without actually sending any mail;
038      * while doing everything else, as far as possible.
039      *
040      *     @see #setDryRun(boolean)
041      */
042    public boolean isDryRun() { return dryRun; }
043
044
045        private boolean dryRun;
046
047
048        /** Sets whether the mail sender is to run without actually sending any mail.
049          * The default value is false; mail will actually be sent.
050          *
051          *     @see #isDryRun()
052          */
053        public final void setDryRun( boolean newDryRun ) { dryRun = newDryRun; }
054
055
056
057    /** Attempts to send a message. Returns any exception that occured,
058      * as a result of the attempt.
059      *
060      *     @return any exception that occured; or null, if the attempt succeeded
061      */
062    public Exception trySend( final Message message, Session session )
063    {
064        try
065        {
066            message.setSentDate( new Date() );
067            logger.fine( "sending From=" + MessageX.getFirstFrom(message) + ", To[0]=" + MessageX.getFirstRecipient(message,Message.RecipientType.TO) );
068
069            final SMTPTransport transport = (SMTPTransport)session.getTransport( protocolID );
070            if( dryRun ) return null;
071
072            try
073            {
074                if( authentication == null )
075                {
076                    transport.connect( serverName, serverPort, null, null );
077                }
078                else
079                {
080                    transport.connect( serverName, serverPort,
081                      authentication.name(), authentication.password() );
082                }
083                transport.sendMessage( message, message.getAllRecipients() );
084            }
085            finally
086            {
087                final String s = transport.getLastServerResponse();
088                final StringBuilder b = new StringBuilder( s == null? "(no response)": s );
089                StringBuilderX.trim( b );
090                logger.fine( "server responds: " + b.toString() );
091                transport.close();
092            }
093        }
094        catch( Exception x ) { return x; }
095        return null;
096    }
097
098
099
100//// P r i v a t e ///////////////////////////////////////////////////////////////////////
101
102
103    private final SMTPTransportX.SimpleAuthentication authentication;
104
105
106
107    private static final Logger logger = LoggerX.i( MailSender.class );
108
109
110
111    private final String protocolID;
112
113
114
115    private final String serverName;
116
117
118
119    private final int serverPort;
120
121
122
123}