package oracle.forms.fd;

import java.util.Date;
import java.util.Properties;

import javax.mail.*;
import javax.activation.*;
import javax.mail.internet.*;
import javax.mail.util.*;
import java.util.StringTokenizer;
import oracle.forms.ui.VBean;
import oracle.forms.properties.ID;

  /**
   * A javabean to send email
   * with html text and attachment
   *
   * most of the code comes from the javamail demo
   * from the Oracle Forms Demos by kprakash and drmills
   * 
   * need the JavaMail(TM) API 1.4 release
   * 
   * @author Francois Degrelle
   * @version 1.2
   *  August 2009 : added authentication
   */

public class SendMail extends VBean {
    protected static final ID setAuth   = ID.registerProperty("SET_MAIL_AUTHENTICATION");  
    protected static final ID setMail   = ID.registerProperty("SET_MAIL_INFOS");  
    protected static final ID pSetLog   = ID.registerProperty("SETLOG");        
    String sSMTPhost    = "" ;
    String sSMTPort     = "" ;
    String sFrom        = "" ;
    String sTo          = "" ;
    String sSubject     = "" ;
    String sBody        = "" ;
    String sAttachment  = "" ;
    String sUserName    = null ;
    String sPassword    = null ;
    static boolean bLog = false ;            

    public SendMail() 
    { 
      log("SendMail()");
    }

  public boolean setProperty(ID property, Object value)
  {
    /***************************
     * Build and send the mail *
     **************************/
    if (property == setMail) 
    {
      log("setMailInfos");
      String sValue="" ;
      sValue = value.toString() ;
      StringTokenizer st ;
      st = new StringTokenizer(sValue,"|");      
      if (st.hasMoreTokens()) sSMTPhost   = st.nextToken() ; 
      if (st.hasMoreTokens()) sSMTPort    = st.nextToken() ;       
      if (st.hasMoreTokens()) sFrom       = st.nextToken() ;       
      if (st.hasMoreTokens()) sTo         = st.nextToken() ;       
      if (st.hasMoreTokens()) sSubject    = st.nextToken() ;       
      if (st.hasMoreTokens()) sBody       = st.nextToken() ;             
      if (st.hasMoreTokens()) sAttachment = st.nextToken() ;             
      log("SMTPHost    = " + sSMTPhost);
      log("From        = " + sFrom);
      log("To          = " + sTo);
      log("Subject     = " + sSubject);
      log("Body        = " + sBody);
      log("Attachment  = " + sAttachment);
      try
     {
       send( sSMTPhost,
             sSMTPort,
             sFrom,
             sTo,
             sSubject,
             sBody,
             sAttachment,
             sUserName,
             sPassword) ;
     }
     catch(SendMessageException sme)
     {
       log(sme.getMessage());
     }           
      return true ;
    }
    
    else if (property == setAuth) 
    {
      log("setMailAuthentication");
      String sValue="" ;
      sValue = value.toString() ;
      StringTokenizer st ;
      st = new StringTokenizer(sValue,",");      
      if (st.hasMoreTokens()) sUserName   = st.nextToken() ; 
      else return false ;
      if (st.hasMoreTokens()) sPassword   = st.nextToken() ;       
      else return false ;
      return true ;
    }    
    
    // init the log boolean
    else if (property == pSetLog)
       {
          String sLog = (String)value ;
          if (sLog.equalsIgnoreCase("true"))
             bLog = true ;
          else
             bLog = false ;
          return true;
       }        
    
    else
    {
     return super.setProperty(property, value);
    }
  }
  
/**
 * send is a static method that performs some basic validation and then sends the e-mail
 * @param <b>SMTPhost</b> name or ip address of the SMTP mail host
 * @param <b>From</b> Email address of sender
 * @param <b>To</b> Email address(es) of the recipient(s).  If multiple addresses are specified separate them with a space.
 * @param <b>Subject</b> Subject for the Email
 * @param <b>Body</b> Email text
 * ( @param <b>Attachment</b> File to attach - must be present on the Middle tier not the Browser client )
 * Update by FD : the file are, now, searched on the client machine
 * @param <b>Attachment</b> File to attach - must be present on the Browser client machine
 */
  public static void send(String SMTPhost,
                          String SMTPort,
                          String From,
                          String To,
                          String Subject,
                          String Body,
                          String Attachment,
                          String UserName,
                          String Password ) throws SendMessageException
  {    
    int StartPos = 0;
    int EndPos;
    char LastAttachChar;
    String Filename;
    String operation = null;

    //Check if attachment is null
    if (Attachment == null||Attachment.equals(""))
    {
      EndPos=0;
    }
    else
    {
      EndPos=Attachment.length();
      LastAttachChar = Attachment.charAt(EndPos-1);

      //If Attachment is terminated by comma, delete the last character from attachment
      if (LastAttachChar==',')
      {
        Attachment = Attachment.substring(StartPos,EndPos-1);
        EndPos=Attachment.length();
      }
    }

    //Get properties and default session for the SMTP server
    Properties props = System.getProperties();

    props.put("mail.smtp.host", SMTPhost);
    props.put("mail.smtp.port", SMTPort);
    Session session = Session.getDefaultInstance(props, null);
    //Now try and create the mail message
    try
    {
      //Create a message
      Message msg = new MimeMessage(session);
      //Add sender to message
      operation = "FROM";
      msg.setFrom(new InternetAddress(From));
      //Add reciepient list to message
      operation = "TO";
      InternetAddress[] address = InternetAddress.parse(To,false);
      msg.setRecipients(Message.RecipientType.TO, address);
      //Add subject to message
      msg.setSubject(Subject);
      //Add date to message
      msg.setSentDate(new Date());
      //Add a new part to the message
      Multipart mp = new MimeMultipart();
      {
        MimeBodyPart mbp = new MimeBodyPart();
        //Add the html body to the new part
        mbp.setDataHandler(new DataHandler(new ByteArrayDataSource(Body, "text/html")));
        mp.addBodyPart(mbp);
      }
      //Parse the attachment list and add files to the new part
      if (EndPos != 0)
      {
        //Get the first and last positions of the file separator
        int FilesepPos     = Attachment.indexOf(",");
        int FilesepLastPos = Attachment.lastIndexOf(",");
        //The attachment contains only one file
        if (FilesepPos==-1)
        {
          FilesepPos=EndPos;
          EndPos=0;
        }
        while (true)
        {
          MimeBodyPart mbp = new MimeBodyPart();
          Filename = Attachment.substring(StartPos,FilesepPos);
          FileDataSource fds = new FileDataSource(Filename);
          mbp.setDataHandler(new DataHandler(fds));
          mbp.setFileName(fds.getName());
          mp.addBodyPart(mbp);
          if (EndPos==0)
          {
            break;
          }
          Attachment = Attachment.substring(FilesepPos+1,EndPos);
          EndPos = Attachment.length();
          if (FilesepPos==FilesepLastPos)
          {
            FilesepPos=EndPos;
            EndPos=0;
          }
          else
          {
            FilesepPos    = Attachment.indexOf(",");
            FilesepLastPos = Attachment.lastIndexOf(",");
          }
        }
      }
      //Add the new part to the message
      msg.setContent(mp);
      //Send the message
      if( UserName == null || Password == null)
        Transport.send(msg);
      else {
        props.put("mail.smtp.auth", "true");
        Transport tr = session.getTransport("smtp");
        tr.connect(SMTPhost, UserName, Password);
        msg.saveChanges();
     
        // tr.send(msg);
        /** Genere l'erreur. Avec l authentification, oblige d utiliser sendMessage meme pour une seule adresse... */
     
        tr.sendMessage(msg,msg.getAllRecipients());
        tr.close();
          
      }
    }
    catch (AddressException aex)
    {
      throw new SendMessageException("Email Address error " + operation + " value > " + aex.getMessage());
    }
    catch (MessagingException mex)
    {
      //Ignore the top level exception as this just tells us the main was not sent
      //The next exception will give more detail
      Exception nested = mex.getNextException();
      if(nested == null) nested = mex ;
      throw new SendMessageException(nested.getMessage());
    }
    catch (Exception ex)
    {
      throw new SendMessageException(ex.toString());
    }
  }

  void log( String sMessage )
  {
    if( bLog ) System.out.println( sMessage ) ;
  }
  

}
