// SMTPAppender.java

/**
*    Copyright (C) 2008 10gen Inc.
*  
*    This program is free software: you can redistribute it and/or  modify
*    it under the terms of the GNU Affero General Public License, version 3,
*    as published by the Free Software Foundation.
*  
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*  
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package ed.log;

import ed.js.JSObjectBase;
import ed.js.engine.Scope;
import ed.util.FastQueue;
import ed.util.MailUtil;

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;

import com.sun.mail.smtp.SMTPMessage;
import com.sun.mail.smtp.SMTPTransport;
import com.sun.mail.smtp.SMTPSSLTransport;

/**
 * turns log messages into emails and sends them
 * the subject should be the logger name
 * all the other info should go in the body
 */
public class SMTPAppender extends Thread implements Appender {

    public long PAUSE_TIME = 10000;

    /**
     * @param fromEmail the email the message should seems like it comes from
     * @param toEmail who to send alerts to
     */
    SMTPAppender( String toEmail , String fromEmail, long interval ) {
        _toEmail = toEmail;
        _fromEmail = fromEmail;

        _formatter = new EventFormatter.DefaultEventFormatter();
        _interval = interval;

        // PAUSE_TIME seconds after init, send any messages
        _lastRun = System.currentTimeMillis() + PAUSE_TIME - _interval;
    }
    
    public void append( Event e ){
        String s = _formatter.format( e );
        _q.add( s );
        if( _loggerName == null ) 
            _loggerName = e._loggerName;
    }

    public void start() {
        _session = MailUtil.createSession( _props , _username, _password );
        _message = new SMTPMessage( _session );

        try {
            _message.setRecipient( Message.RecipientType.TO, new InternetAddress( _toEmail ) );

            // cover all the bases on "from:" field
            _message.setEnvelopeFrom( _fromEmail );
            _message.setSubmitter( _fromEmail );
            _message.setFrom( new InternetAddress( _fromEmail ) );
            _message.setSender( new InternetAddress( _fromEmail ) );
        }
        catch( MessagingException e ) {
            e.printStackTrace();
            return;
        }

        super.start();
    }

    public void run() {
        while( true ) {
            long now = System.currentTimeMillis();
            try {
                if( now - _lastRun >= _interval && _q.size() > 0 ) {
                    createMessage();
                    setSubject( now );
                    sendMessage();
                    _lastRun = now;
                }
                sleep( Math.max( PAUSE_TIME, (_lastRun + _interval) - now ) );
            }
            catch( MessagingException e ) {}
            catch( InterruptedException e ) {}
        }
    }

    /** Empties the queue and turns any messages in it into the body of an email
     */
    private void createMessage() 
        throws MessagingException {

        StringBuilder m = new StringBuilder();
        while( _q.size() > 0 ) {
            m.append( _q.poll() );
        }
        _message.setText( m.toString() );
    }

    private void setSubject( long now) 
        throws MessagingException {
        _message.setSubject( _loggerName + ": " + 
                             new Date( _lastRun ) + " to " + new Date( now ) );
    }

    private void sendMessage()
        throws MessagingException {

        if( _ssl ) 
            SMTPSSLTransport.send( _message );
        else
            SMTPTransport.send( _message );
    }

    public void setMailInfo( String server, int port, boolean ssl ) {
        _props = new Properties();
        _props.setProperty( "mail.smtp.host" , server );
        _props.setProperty( "mail.smtp.auth" , "true" );
        _props.setProperty( "mail.smtp.port" , port+"" );
        _props.setProperty( "mail.smtp.socketFactory.port" , port+"" );
        _props.setProperty( "mail.smtp.socketFactory.fallback" , "false" );
        
        _ssl = ssl;
        if( _ssl )
            _props.setProperty( "mail.smtp.socketFactory.class" , "javax.net.ssl.SSLSocketFactory" );
    }

    public void setAccountInfo( String username, String password ) {
        _username = username;
        _password = password;
    }

    private final long _interval;
    private long _lastRun;

    private final String _fromEmail;
    private final String _toEmail;

    private String _username = "";
    private String _password = "";

    private final EventFormatter _formatter;
    private Session _session;
    private SMTPMessage _message;
    private Properties _props;
    private boolean _ssl = false;

    private final FastQueue<String> _q = new FastQueue<String>();

    private String _loggerName;
}

@@ -1332,45 +1332,8 @@
  %7B%0A%0A
-    public long PAUSE_TIME = 10000;%0A%0A
     
@@ -1533,24 +1533,170 @@
 nterval ) %7B%0A
+        this( toEmail, fromEmail, interval, %22Log%22 );%0A    %7D%0A%0A    SMTPAppender( String toEmail , String fromEmail, long interval, String logger ) %7B%0A
         _toE
@@ -1842,69 +1842,8 @@
 val;
-%0A%0A        // PAUSE_TIME seconds after init, send any messages
 %0A   
@@ -1888,33 +1888,39 @@
 is()
- + PAUSE_TIME - _interval
+;%0A%0A        _loggerName = logger
 ;%0A  
@@ -2023,24 +2023,25 @@
 q.add( s );%0A
+%0A
         if( 
@@ -2045,70 +2045,325 @@
 f( _
-loggerName == null ) %0A            _loggerName = e._loggerName;
+firstMessage ) %7B%0A            long now = System.currentTimeMillis();%0A            try %7B%0A                createMessage();%0A                setSubject( now );%0A                sendMessage();%0A            %7D%0A            catch( MessagingException ex ) %7B%7D%0A            _lastRun = now;%0A            _firstMessage = false;%0A        %7D
 %0A   
@@ -3438,30 +3438,8 @@
 eep(
- Math.max( PAUSE_TIME,
  (_l
@@ -3459,26 +3459,24 @@
 erval) - now
- )
  );%0A        
@@ -5047,32 +5047,74 @@
 assword;%0A    %7D%0A%0A
+    private boolean _firstMessage = true;%0A
     private fina

send first message right away, configurable log name