jueves, 6 de enero de 2011

PHP: Enviar convocatorias por mail desde una web a Outlook o GMail

Hace tiempo que necesitaba realizar convocatorias a reuniones, sitas desde una página web, por mail, hacia outlook o google calendar.
Me cansé de buscar y romperme la cabeza con codigos a medio hacer y que no funcinaban (no funcionaron).

Me cansé de enviar archivos a outlook que, aparecían como adjuntos .ics que al ejecutarlos me mostraba el fastidioso cartel de "elija usar calendario gregoriano en lugar de lunar!".

Y no fué hasta encontrar una función completa que funcionara que me dí cuenta que lo importante no eran los datos (estan en todos lados) que le enviara al mail, sino en el formato del mime que le pasabamos.

Así que tomé la función, la adapté a mis necesidades y acá te la publico, en formato de código, con comentarios y todo, para ponerla en un php, ejecutarla y ser feliz convocando gente a reuniones vía email.

Esta función no te crea el archivo .ics por separado sino que te envía el mail con los característicos botones de ACEPTAR, RECHAZAR, PROVISORIO. Al aceptarlo actualiza tu calendario con la cita creada.

Sin más acá va el código:


-----------------------------------------------------------------------------------------------------

Si querés el código fuente descargá acá el archivo .php.

-----------------------------------------------------------------------------------------------------



function sendIcalEmail($nombre_dest,$apellido_dest,$email,$fecha_inicio,$evento_nombre,$fecha_fin,$evento_desc) {

$nombre_from = "";//nombre para mostrar en el campo DE:
$email_from = "";//tu@mail.com para el campo DE:
$subject = ""; //asunto del mail
$evento_descripcion = $evento_desc."\n\n"; //Descripción del evento
$meeting_location = ""; //Lugar donde se llevará a cabo el evento


//Convertimos la fecha de formato MYSQL (YYYY-MM-DD HH:MM:SS) a formato UTC (yyyymmddThhmmssZ)
$meetingstamp = strtotime($fecha_inicio . " UTC");    
$meetingstampb = strtotime($fecha_fin . " UTC");    
$dtstart= gmdate("Ymd\THis\Z",$meetingstamp);
$dtend= gmdate("Ymd\THis\Z",$meetingstampb);
$todaystamp = gmdate("Ymd\THis\Z");

//Creamos identificador único aleatorio para el mensaje

$cal_uid = date('Ymd').'T'.date('His')."-".rand()."ejemplo.com";

//Establecemos el formato del MIME 

$mime_boundary = "----Meeting Booking----".md5(time());

//Creamos los headers del mail

$headers = "From: ".$nombre_from." <".$email_from.">\n";
$headers .= "Reply-To: ".$nombre_from." <".$email_from.">\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/alternative; boundary=\"$mime_boundary\"\n";
$headers .= "Content-class: urn:content-classes:calendarmessage\n";

//Creamos el cuerpo de texto del mail (HTML)

$message .= "--$mime_boundary\n";
$message .= "Content-Type: text/html; charset=UTF-8\n";
$message .= "Content-Transfer-Encoding: 8bit\n\n";
$message .= "<html>\n";
$message .= "<body>\n";
$message .= '<p>Hola '.$nombre_dest.',</p>';
$message .= "</body>\n";
$message .= "</html>\n";
$message .= "--$mime_boundary\n";

//Ahora armamos los datos en formato iCalendar

$ical =    'BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
VERSION:2.0
METHOD:PUBLISH
BEGIN:VEVENT
ORGANIZER:MAILTO:'.$email_from.'
DTSTART:'.$dtstart.'
DTEND:'.$dtend.'
LOCATION:'.$meeting_location.'
TRANSP:OPAQUE
SEQUENCE:0
UID:'.$cal_uid.'
DTSTAMP:'.$todaystamp.'
DESCRIPTION:'.$evento_descripcion.'
SUMMARY:'.$subject.'
PRIORITY:5
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR';

//Agregamos al cuerpo del mensaje la iCal

$message .= 'Content-Type: text/calendar;name="meeting.ics";method=REQUEST\n';
$message .= "Content-Transfer-Encoding: 8bit\n\n";
$message .= $ical;

//Enviamos el mail y validamos si se envió o no

$mail_sent = @mail( $email, $subject, $message, $headers );

if($mail_sent)     {

return true;
} else {
return false;
}   
}
A partir de aquí sólo queda llamar a nuestra función pasandole los parametros necesarios: Nombre del destinatario, Apellido del destinatario, email del destinatario, fecha de inicio, titulo, fecha de finalización y descripción (en ese orden).

sendIcalEmail("","","","","","","");
Espero que te haya servido tanto como a mí.

Esto es todo: Si tuviste algún problema copiando el código, descargá acá el archivo .php.
-----------------------------------------------------------------------------------------------------
Nota: Si este artículo te pareció interesante, por favor, visitá los enlaces patrocinados donde seguramente encontrarás más cosas útiles.




5 comentarios:

Unknown dijo...

Hola!

Tengo un problemilla, no se me envia el 'meeting.ics'. He quitado la funcion inicial y he introducido mediante consultas de mysql datos a la variables sin definir. Recibo el correo en mi bandeja de entrada pero sin archivo .ics

Gracias de Antemano

Chabat dijo...

Ojo cuando esta función anda bien el outlook (o gmail) interpresa el .ics y te lo muestra en formato de mail-convocatoria (mail con los botones de aceptar, rechazar, provisorio).
¿Es eso lo que te llega a tu casilla?

Borja dijo...

Hola Chabat,

A ver si me puedes echar un cable. Estoy tratando de implementar esta función, y creo que me ocurre lo mismo que a Alberto.

Si envío el mail a Microsoft Outlook solo recibo en el cuerpo del mail el 'Hola '.$nombre_dest', sin ningún adjunto.

Sin embargo si lo envío a Thunderbird, en el cuerpo del mail aparece la convocatoria, el ics aparece como adjunto, pero el Lighting (agenda de Thunderbird) da un error de que no es capaz de reconocerlo. El ics está bien creado con todos los datos, salvo que aparece como un evento en lugar de como una invitación, pero eso se soluiona modificando el METHOD a REQUEST.

Supongo que sea normal pero si ese ics lo envío como adjunto a Outlook lo recibo como adjunto pero no lo interpreta.

GRACIAS!!

Unknown dijo...

hola chabat teno una inquietud la funcion me funciona bien pero no me sale el boton de aceptar o rechazar en mi outlook tengo q darle agregar a mi calendario para q se cargue y por otr parte el correo en gmail me llega como spam pues el campo from no sale :(, gracias de antemano

Anónimo dijo...

Me funciona de lujo, mil gracias por el aporte.

El portal que comparte sus ingresos