entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Leer buzón con PHP para hacer un reenvío de un correo

Me gustaría realizar la siguiente tarea:

  • Un correo electrónico llega a un buzón de correo en nuestro servidor exchange (alojado en 192.168.1.100)
  • Lo seleccionamos y mediante PHP se asocia ese correo a una referencia en base de datos (select * from reflist -> se reproduce la lista en una dropbox y se elige una)
  • Esa referencia nos da una lista de correos electrónicos que hay que excluir del reenvío (select exclude_mails from claimslist where reference = 'valor seleccionado en dropbox')
  • Reenviamos ese correo a todos los usuarios menos la lista obtenida en la consulta anterior.

La pregunta es como hacemos los pasos 1 y 2 con PHP. El código para los pasos tercero y cuarto lo tengo ya desarrollado en VBA y sólo tendría que convertirlo a PHP. Pero necesitamos de alguna manera hacerlo todo en entorno web porque el problema es el siguiente: el script VBA desarrollado para hacer esta misma tarea en outlook precisa de demasiados "clicks"; primero pregunta la referencia, la seleccionamos (ya van tres clics, uno para el botón VBA, otro para desplegar el dropdown y otro para picar la referencia). Luego outlook pregunta si deseamos permitir que una aplicación externa envíe correos en tu nombre a lo que debes pulsar "Permitir", luego te sale una segunda confirmación con un timing de unos 5 segundos. Esto hace un total de unos 5-6 clicks y de un tiempo de espera de unos 7 segundos por correo. Teniendo en cuenta que esa bandeja puede recibir unos 50 correos diarios que deben todos pasar por este proceso hace que para el usuario sea muy tedioso por lo que hemos pensado en la opción web. Cargar la bandeja de correo en PHP y que la selección del correo sea en PHP así como la selección de la referencia asociada a ese correo.

Usamos bases de datos SQL Server y servidor Exchange 2010. Tenemos activado el POP en exchange y también el imap... He intentado usar imap_open para leer los correos de mi buzón (a modo de pruebas) pero no doy con la clave y he probado cientos de combinaciones.

Me podéis echar una mano??

P.D.: Acabo de darme cuenta que no he comentado que ya había adoptado Políticas de Grupo en el servidor para no preguntar si se permitía el envío de correos mediante aplicaciones externas. Lo digo por si a alguien se le ocurre esa solución... no ha funcionado :-(

2 Respuestas

1voto

ankeorum Puntos7210

Ya he solucionado el problema, os pongo el código limpiando las líneas con datos de la configuración:

$mailserver = '192.168.1.100';
    $port = '110';
    $user = 'domain\user';
    $pass = 'password';

    if ($mbox=imap_open( "{".$mailserver.":".$port."/pop3/novalidate-cert}INBOX", $user, $pass )) 
    {
        //echo "Connected\n<br/>"; 
        echo "Database is: $database<br/>";

    }
    else 
    {
        exit ("Can't connect: " . imap_last_error() ."\n"); 
    } 

    //Connecting to the mailbox end\\

    if ($hdr = imap_check($mbox)) 
    {

        $msgCount = $hdr->Nmsgs;
        //echo "We have ".$msgCount." mail(s)<br/>";

    }
    else 
    {

        echo "Failed to get mail";

    }

    $result = imap_search($mbox, 'ALL', SE_UID);
    $output='';

    foreach($result as $uid) 
    {

        /* get information specific to this email */
        $overview = imap_fetch_overview($mbox,$uid,0);
        $message = imap_body($mbox,$uid);
        $s = imap_fetchstructure($mbox,$uid);
        //var_dump($s);
        if ($s->encoding==4)

            $message = quoted_printable_decode($message);

        elseif ($s->encoding==3)

            $message = base64_decode($message);

        /* output the email header information */
        $output.= '<form action = "conflict.php" method="post">';
        $output.= '<input name = "uid" value="'.$uid.'" type="text" hidden="true"/>';
        $output.= '<br/><span class="subject">Subject: '.$overview[0]->subject.'</span><br/> ';
        $output.= '<span class="from">From: '.$overview[0]->from.'</span><br/>';
        $output.= '<span class="date">Sent on: '.date("d/m/Y H:i",strtotime($overview[0]->date)).'</span><br/>';
        $output.= '</div>';

        /* output the email body */
        $output.= '<div class="body">Message: '.$message.'<br/> End of message</div>';

        $sql = "select referencia from tabla where status = 'Open'";

        $output.= '<select onChange="this.form.submit()" class="required" id="referencia" name="referencia" style="font-size:1.2em; width:97%; text-align:left; margin-left:1.4em">
            <option value="">Please select...</option>';

        $myformfield="";
        $result_spec = sqlsrv_query($dbh,$sql);
        while($row_spec = sqlsrv_fetch_array($result_spec))
        {
            $myformfield = $myformfield."<option ";
            $myformfield = $myformfield."value=\"".htmlspecialchars(trim($row_spec{'referencia '}))."\">".htmlspecialchars(trim($row_spec{'referencia '}))."</option>";
        }
        sqlsrv_cancel($result_spec);
        $output.=$myformfield;
        $output.= '</select></form>';

    }

    echo $output;

Con eso consigo mostrar el correo y debajo un desplegable donde seleccionar la referencia, una vez seleccionado realiza automáticamente un envío de un correo usando la referencia seleccionada.

Conflict.php

function forward_email($uniqueid,$to)
{
//Setting for connecting to the mailbox\\
    $port = '110';
    $user = 'domain\user';
    $pass = 'password';

    if ($mbox=imap_open( "{".$mailserver.":".$port."/pop3/novalidate-cert}INBOX", $user, $pass )) 
    {
        //echo "Connected\n<br/>"; 
        //echo $database."<br/>";

    }
    else 
    {
        exit ("Can't connect: " . imap_last_error() ."\n"); 
    } 

    //Connecting to the mailbox end\\

    if ($hdr = imap_check($mbox)) 
    {

        $msgCount = $hdr->Nmsgs;
        //echo "We have ".$msgCount." mail(s)<br/>";

    }
    else 
    {

        echo "Failed to get mail";

    }

    $result = imap_search($mbox, 'ALL', SE_UID);
    $output='';

    foreach($result as $uid) 
    {
        if ($uid == $uniqueid)
        {

            /* get information specific to this email */
            $overview = imap_fetch_overview($mbox,$uid,0);
            $message = imap_body($mbox,$uid);
            $s = imap_fetchstructure($mbox,$uid);
            //var_dump($s);
            if ($s->encoding==4)

                $message = quoted_printable_decode($message);

            elseif ($s->encoding==3)

                $message = base64_decode($message);

            $mailstructure = imap_fetchstructure($mbox, $uid, FT_UID); 
            $type = $mailstructure->type;

            $parameters = $mailstructure->parameters;
            $attribute = $parameters[0]->attribute;

            prepare_mail($overview[0]->subject,$overview[0]->from,$message,strtolower($mailstructure->subtype),$parameters[0]->value,$to);
        }

        //}*/
    }
}
function prepare_mail($subjct, $frm,$message,$subtype,$value,$to)
{
    # prepare the mail
    $send_to=$to;
    $subject=$subjct;
    $body="\r\nThis is a multipart message in MIME format.\r\n";
    $body.=$message;
    $headers ="From:" . $frm . "\r\n";
    $headers .="Date: " . date("r") . "\r\n";
    $headers .="MIME-Version: 1.0\r\n";
    $headers .="Content-Type: text/".$subtype. ";
    \t boundary=\"" . $value . "\""."\r\n";
    //echo "Subject: ".$subject."<br/>To:".$send_to."<br/>Body:".$body;
    //$sendmail = mail($to, $subject, $body, $headers);

}
$to_list = array("mail1","mail2","mail3");

$conflict_sql = "select conflict_users from tabla1 where referencia= '".$_POST['referencia']."'";
$conflict_result = sqlsrv_query($dbh,$conflict_sql);

while ($row = sqlsrv_fetch_array($conflict_result))
{
    $conflict_users = $row{'conflict_users'};
}

$user = explode(",",$conflict_users);
$conflict_list = array();

foreach ($user as $user1)
{
    $sql_mail = "select user_mail from user where userid = '".trim($user1)."'";
    $mail = sqlsrv_query($dbh,$sql_mail);
    while ($row_mail = sqlsrv_fetch_array($mail))
    {
        //echo $user1.": ".$row_mail{'user_mail'}."<br/>";
        $conflict_list[] = $row_mail{'user_mail'};

    }
}
/*echo "Original to: ";
var_dump($to_list);
echo "<br/><br/>";
echo "Conflict users with this claim: ";
var_dump($conflict_list);
echo "<br/><br/>";*/

$final_to = array_diff($to_list,$conflict_list);
//echo "Final list of emails in to: ".implode(",",$final_to)."<br/><br/>";

forward_email($_POST['uid'],implode(",",$final_to));

header('location: testpop3.php');
?>

Creo que no me he dejado nada, espero que le valga a alguien el trabajo!

0voto

Peter comentado

Gracias por compartir la solución :)

1voto

Ra-Hulk Puntos1490

Hola en .Net yo hago esos mismos pasos, usando "Microsoft.Office.Interop.Outlook" y el exchange con Outlook

No conosco PHP pero igual y lo puedes converitir.

Te anexo el código que yo uso.

Imports OutLook = Microsoft.Office.Interop.Outlook

Module Module2

    Sub LeerCoreo()
        '* Creamos un Objeto que hará referencia a nuestra aplicación Outlook
        'Dim m_OutLook As Outlook.Application
        Dim m_OutLook As OutLook.Application
        Try
            '* Creamos un Objeto tipo Mail
            Dim objMail As OutLook.MailItem
            '* Inicializamos nuestra apliación OutLook
            m_OutLook = New OutLook.Application
            '* Creamos una instancia de un objeto tipo MailItem

            objMail = m_OutLook.CreateItem(OutLook.OlItemType.olMailItem)

            Dim tempApp As OutLook.Application
            Dim tempInbox As OutLook.MAPIFolder
            'Dim InboxItems As OutLook.Items
            tempApp = CreateObject("Outlook.Application")
            tempInbox = tempApp.GetNamespace("Mapi").GetDefaultFolder(OutLook.OlDefaultFolders.olFolderInbox) ' AQUI SLEECIONO LA BANDEJA DE ENTRADA
            Dim lei2 As OutLook.MailItem
            For Each lei2 In tempInbox.Items
                If lei2.UnRead = True Then ' AQUI LE VALIDO QUE EL ELEMENTO NO ESTE LEIDO
                    If InStr(1, lei2.Subject, "ASUNTO DEL CORREO") > 0 Then ' AQUI LE DIGO QUE SI EN EL ASUNTO CORRESPONDE A ...

                        ' AQUI YA PUEDES PONER TU PROCEDIMIENTO PARA GUARDAR EN TU BASE

                        'lei2.Body ' con este recuperas el cuerpo del Correo
                        'lei2.HTMLBody ' con este recuperas el cuerpo del Correo
                        'lei2.LastModificationTime ' con este recuperas la fecha en llego
                        'lei2.Subject ' Con este el asunto
                        'lei2.To ' Recuperas el Remitente

                        lei2.UnRead = False ' LEE EL ELEMENTO
                        lei2.Move(tempInbox.Folders("Leidos")) ' LO MUEVE A OTRA CARPETA PARA TENERLOS MEJOR CLASIFICADOS
                    End If
                End If
            Next
        Finally
            m_OutLook = Nothing
        End Try
        m_OutLook = Nothing
        MsgBox("Proceso Finalizado")
    End Sub

End Module

Saludos

0voto

ankeorum comentado

El problema de esa solución @Ra-Hulk es que cuando haga llamada al procedimiento de reenvío del correo Outlook me va a preguntar de nuevo si permito realizar el envío en mi nombre de correos a través de una aplicación de terceros (en este caso ese plugin) con lo que tendríamos el mismo problema. La única forma de solucionar este problema es o bien implementando una app web (php) que conecte con el servidor exchange y a través de la cual se realicen los envíos o bien averiguando la fórmula correcta a través de la cual outlook no te pida permiso para reenviar un correo.

Gracias de todas formas.

1voto

Ra-Hulk comentado

Pasan 2 Cosas

En Outlook en el Menu - Archivo - Opciones - Centro de Confianza - Configuración del Centro de Confianza - Acceso mediante Programación, aparecen unas opciones.

Ahi seleccionaras la ultima, "No avisarme nunca sobre la Actividad sospechosa" y ya con eso te evitas el mensajito de Seguridad.

Usando el interop tambien puedes enviar el correo sin la necesidad de deshabilitar la opcion que te comente arriba.

Te pongo el Script, solo conviertelo a PHP, Yo tengo lo mismo en una web pero con .net

    '* Creamos un Objeto que hará referencia a nuestra aplicación Outlook
    'Dim m_OutLook As Outlook.Application
    Dim m_OutLook As OutLook.Application
    Try
        '* Creamos un Objeto tipo Mail
        Dim objMail As OutLook.MailItem
        '* Inicializamos nuestra apliación OutLook
        m_OutLook = New OutLook.Application
        '* Creamos una instancia de un objeto tipo MailItem
        objMail = m_OutLook.CreateItem(OutLook.OlItemType.olMailItem)
        '* Asignamos las propiedades a nuestra Instancial del objeto
        '* MailItem
        objMail.To = "[email protected]"
        objMail.Subject = "Prueba de envio con Outlook usando Interop"
        objMail.HTMLBody = "<html><body><h1>Esto es una prueba Para enviar un mail</h1></body></html>"
        '* Enviamos nuestro Mail y listo!
        objMail.Send()
        '* Desplegamos un mensaje indicando que todo fue exitoso
        MessageBox.Show("Mail Enviado", "Integración con OutLook", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
    Catch ex As Exception

        '* Si se produce algun Error Notificar al usuario
        MessageBox.Show("Error enviando mail")
    Finally
        m_OutLook = Nothing
    End Try

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta