
package datos;

import encapsuladores.Correo;
import encapsuladores.Mensaje;
import encapsuladores.SistemaArchivos;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class FacturaMail {
    
    public void enviar(String nombreArchivoXML, Correo correo) throws Exception{
        
            Properties properties = new Properties();        
            properties.setProperty("mail.smtp.host", correo.getServidorSMTP());                             // HOST correo saliente
            properties.setProperty("mail.smtp.starttls.enable", "true");
            properties.setProperty("mail.smtp.port", correo.getPuertoSMTP());                               // puerto correo saliente                       
            properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 
            properties.setProperty("mail.smtp.user", correo.getCuentaRemitente());                          // remitente
            properties.setProperty("mail.smtp.auth", "true");

            Session session = Session.getDefaultInstance(properties);           

            MimeMessage mensaje = new MimeMessage(session);   
            mensaje.setFrom(new InternetAddress(correo.getCuentaRemitente()));                                   // cuenta remitente
            mensaje.addRecipient(Message.RecipientType.TO,new InternetAddress(correo.getCuentaDestinataria()));  // cuenta destinataria
            mensaje.setSubject("Factura:  "+nombreArchivoXML.substring(nombreArchivoXML.indexOf("Factura")+8 , nombreArchivoXML.length()-4)+"  en formato XML");
            
            String textoPlain ="Adjuntamos factura número :\n"+nombreArchivoXML.substring(nombreArchivoXML.indexOf("Factura")+8 , nombreArchivoXML.length()-4);
            BodyPart textoPlainPart = new MimeBodyPart(); 
            textoPlainPart.setText(textoPlain);    
            
           
            String textoHTML = "<div style=\"font-size: 1.5em;"
                             + "             color: #999;\">"                  
                             + "   <p>"
                             + "      <br><br>"
                             + "      MATERIALES DE CONSTRUCCION, S.L.<br>"
                             + "      Av./Montes Universales, 58<br>"
                             + "      Pol.Industrial METROPOLITANO<br>"
                             + "      MADRID"                                     
                             + "   </p>"
                             + "</div>";                                                            
            BodyPart textoHTMLPart = new MimeBodyPart();
            textoHTMLPart.setContent(textoHTML, "text/html");                    
            
            BodyPart adjuntoPart = new MimeBodyPart();    
            adjuntoPart.setDataHandler(new DataHandler(new FileDataSource(nombreArchivoXML)));
            adjuntoPart.setFileName(nombreArchivoXML.substring(nombreArchivoXML.indexOf("Factura"), nombreArchivoXML.length()));
            
            MimeMultipart mimeMultipart= new MimeMultipart(); 
            mimeMultipart.addBodyPart(textoPlainPart);
            mimeMultipart.addBodyPart(textoHTMLPart);
            mimeMultipart.addBodyPart(adjuntoPart);
            mensaje.setContent(mimeMultipart);
                                 
            Transport transport = session.getTransport("smtp");
                            //  HOST correo saliente           remitente                    password
            transport.connect(correo.getServidorSMTP(), correo.getCuentaRemitente(), correo.getPasswordRemitente());
            transport.sendMessage(mensaje, mensaje.getAllRecipients());

            transport.close();    
            //  La siguiente temporización se activaría en el caso de que nos encontrásemos ante un envío masivo de emails
            //  En ese caso aplicaríamos una estructura de control repetitiva que proporcionase cada una de las direcciones de correo destinatarias
            //  En cada repetición de dicha estructura repetitiva se abriría Session y cerraría Transport
            //  El temporizador lo ubicaríamos en cada repetición después del cierre a efectos de espaciar en el tiempo cada uno de los envíos
            //  y que no fuese interpretado como SPAM   
            //  Establecido a 10 segundos, caso de repetición aplicaríamos varios minutos
            //  Thread.sleep(10000);   
    }
    
    public List<Mensaje> leer(Object[] repositorio) throws Exception {
        
        Correo correo = (Correo) repositorio[0];
        
        List<Mensaje> listaMensajes = new ArrayList();           
        
        Properties properties = new Properties();
        properties.setProperty("mail.pop3.starttls.enable", "false");                               //deshabilitamos TLS.
        properties.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");  // establecemos como obtener un socketSSL
        properties.setProperty("mail.pop3.socketFactory.fallback", "false");                        // establecemos que en caso de que falle el socketSSL no busque con un socket normal ya que no funcionaria, para email solo se admiten socketSSL
        properties.setProperty("mail.pop3.port", correo.getPuertoPOP3());                           // puerto correo entrante
        properties.setProperty("mail.pop3.socketFactory.port", correo.getPuertoPOP3());             // puerto 
        
        Session sesion = Session.getInstance(properties); 
        
           // Obtenemos la carpeta de correo entrante de nuestro servidor de correo.
           // Se obtiene el Store y el Folder, para poder leer el correo.
            Store store = sesion.getStore("pop3"); //Obtenemos el almacen de correos indicando el protocolo "pop3" con nuestro servidor de correo.
                       //  HOST correo entrante            destinatario                    password      
            store.connect(correo.getServidorPOP3(), correo.getCuentaDestinataria(), correo.getPasswordDestinataria());
            Folder folder = store.getFolder("INBOX"); //  Carpeta de la que queremos leer el correo. 
            folder.open(Folder.READ_ONLY); 

            Message[] mensajes = folder.getMessages();    
            
            for (int i = 0; i < mensajes.length; i++)
            {     
                Mensaje mensaje = new Mensaje();
                mensaje.setRemitente(mensajes[i].getFrom()[0].toString());               
                mensaje.setFechaEnvio(mensajes[i].getSentDate());               
                mensaje.setAsunto(mensajes[i].getSubject());
                
                if (mensajes[i].getContentType().contains("multipart")) {                    
                    Multipart multiPart = (Multipart) mensajes[i].getContent();
                    
                    mensaje.setNombreFicheroAdjunto(null);
                     
                    for (int k=0; k<multiPart.getCount(); k++) {
                        MimeBodyPart  mimeBodyPart = (MimeBodyPart) multiPart.getBodyPart(k);
                        
                        if (Part.ATTACHMENT.equalsIgnoreCase(mimeBodyPart.getDisposition())) {  
                           String extensionFichero = mimeBodyPart.getFileName().substring( mimeBodyPart.getFileName().length()-3 ,  mimeBodyPart.getFileName().length() );
                                    // La única comprobación que aplicamos para tratar el fichero adjunto es que tenga extensión  "xml"
                                    // También habría que aplicar las comprobaciones oportunas de que dicho "xml" se acoge al esquema que corresponda
                           if (extensionFichero.compareTo("xml") == 0) {
                                    // Sólo en caso de que proceda tratar el fichero "xml" adjunto, al atributo nombreFicheroAdjunto almacena dicho nombre de fichero
                                    // en cualquier otro caso este atributo es "null"
                               mensaje.setNombreFicheroAdjunto(mimeBodyPart.getFileName());
                               guardarFicheroAdjunto(mimeBodyPart, (SistemaArchivos)repositorio[1]);
                           }
                        } 
                        else {
                           if (mimeBodyPart.isMimeType("text/plain"))      // también podría ser con el comodín * : "text/*" pero englobaria plain, html, ...
                               mensaje.setTexto(mimeBodyPart.getContent().toString());
                        }
                    }
                } 
                listaMensajes.add(mensaje);
            }
            
            folder.close(false);
            store.close();   
            
        return listaMensajes;
    } 
       
    
    private void guardarFicheroAdjunto(Part part, SistemaArchivos sistemaArchivos ) throws Exception {
        FileOutputStream fileOutputStream = new FileOutputStream(sistemaArchivos.getRutaDescarga() + part.getFileName());
        InputStream inputStream = part.getInputStream();
        byte[] bytes = new byte[4096];
        int leidos = 0;

        while ((leidos = inputStream.read(bytes)) > 0)
            fileOutputStream.write(bytes, 0, leidos);
    }            
}
