Enviar mailings con poMMo mediante CURL

poMMo es una de las mejores herramientas para envío de newsletters o mailing, el problema es que la última versión es del 2008 y no tienen ni API ni nada parecido, pero se puede simular mediante CURL, lo cual nos puede venir muy bien para añadir mailing a nuestras aplicaciones con CodeIgniter o WordPress.


$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookiefile");
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookiefile");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_URL, 'http://servidor.com/pommo/index.php');
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"); 
$post = 'referer='.urlencode('/pommo/admin/admin.php').'&username=admin&password=password&submit=Log In';
curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch); 

curl_setopt($ch, CURLOPT_URL, 'http://servidor.com/pommo/admin/mailings/mailing/setup.php');
$post = 'subject=Asunto&mailgroup=all&fromname=Yo&fromemail=mi%40email.com&frombounce=mi%40email.com&list_charset=UTF-8&submit=Continue';
curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch); 

curl_setopt($ch, CURLOPT_URL, 'http://servidor.com/pommo/admin/mailings/mailing/ajax.rpc.php?call=savebody');
$post = 'body='.urlencode('Hola a todos').'&altbody=';
curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch); 

curl_setopt($ch, CURLOPT_URL, 'http://servidor.com/pommo/admin/mailings/mailing/preview.php');
$post = 'sendaway=true';
curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);

$result = curl_exec($ch); 

Peticiones en paralelo de CURL con PHP

Cuando realizamos una petición CURL normalmente usamos el método sencillo: hacer petición, esperar respuesta. ¿Pero que ocurre cuando queremos hacer varias peticiones de forma simultánea? por ejemplo para un crawler o una aplicación parecida. En estos casos tenemos que echar mano de curl_multi_*.

Si nos encontramos en esta situación podemos echar mano de la clase ParallelCurl, que de forma muy sencilla nos ayudará en nuestra tarea:

$pc = new ParallelCurl($max_requests, $curl_options);

// 3 peticiones en paralelo que empiezan simultaneamente
$pc->startRequest($url1, 'on_request_done');
$pc->startRequest($url2, 'on_request_done');
$pc->startRequest($url3, 'on_request_done');

$pc->finishAllRequests();

Parallel cURL execution in PHP

Vía / PHPDeveloper.org

Mostrar la media semanal de lectores de Feedburner con PHP

Parece que Feedburner está dando problemas, y ahora parece que te muestra los usuarios que leyeron tu blog el día anterior, y no el numero de suscritos como se mostraba anteriormente, por lo que a los que no escribimos posts a diarios, el número que muestra Feedburner puede variar muchísimo.

Por ello, puede ser interesante mostrar la media semanal o mensual, como queramos, de los usuarios que nos leen:

function get_average_readers($feed_id,$interval = 7){
	$today = date('Y-m-d', strtotime("now"));
	$ago = date('Y-m-d', strtotime("-".$interval." days"));
	$feed_url="https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=".$feed_id."&dates=".$ago.",".$today;
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_URL, $feed_url);
	$data = curl_exec($ch);
	curl_close($ch);
	$xml = new SimpleXMLElement($data);
	$fb = $xml->feed->entry['circulation'];

	$nb = 0;
	foreach($xml->feed->children() as $circ){
		$nb += $circ['circulation'];
	}

	return round($nb/$interval);
}
$nb = get_average_readers('miusuario');
echo "tengo ".$nb." suscriptores RSS";
// o
$nb = get_average_readers('miusuario', 30);
echo "tengo ".$nb." suscriptores RSS";

How to get a more relevant Feedburner count

Vía / DZone

Conocer a quien le gusta tu post en Google Reader con PHP y CURL

No es difícil ver en blogs los retweets que hace la gente de tus posts y que estos se muestren en los comentarios. ¿Por qué no hacer lo mismo con Google Reader?. En Google Reader, es posible ver a quienes les gustan tus posts (si tienes tu propio blog en el reader), lo cual te puede ayudar a saber si tus posts interesan o no, o encontrar usuarios con gustos parecidos y así seguir sus recomendaciones y poder leer posts interesantes.

Google suele dar complicaciones a la hora de hacer uso de sus webs, pero si usamos su API de ClientLogin lo podemos hacer de forma sencilla.

Primero tendremos que loguearnos en Google, para lo cual tendremos que indicar nuestro usuario y contraseña y los datos posts que tendremos que pasarle:

$usuario = 'micorreo@gmail.com';
$password = 'mipassword';
$postdata = 'service=reader&Email='.urlencode($usuario).'&Passwd='.urlencode($password).'&continue=http://www.google.com/reader/&service=reader';

Luego nos logueamos y obtenemos el valor de Auth para usarlo en el resto de peticiones usandolo en el header de la petición HTTP:

$ch = crl_init($url);
crl_setopt( $ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)');
crl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
crl_setopt ($ch, CURLOPT_COOKIEJAR, './cookie');
crl_setopt ($ch, CURLOPT_COOKIEFILE, './cookie');
crl_setopt ($ch, CURLOPT_POSTFIELDS, $postdata);
crl_setopt ($ch, CURLOPT_POST, 1);
crl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
crl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false );

$url = 'https://www.google.com/accounts/ClientLogin';
crl_setopt($ch, CURLOPT_URL, $url);
crl_setopt($ch, CURLOPT_FOLLOWLOCATION, 4);
$res = crl_exec($ch);
preg_match('/Auth=(.*)/', $res, $m);
$auth = $m[1];

Después realizo la búsqueda, para lo cual busco el título del post y le añado el nombre del blog (chapu a la espera de encontrar algo mejor), por ejemplo “Stanford%20Javascript%20Crypto%20Library%20sentidoweb

$url = 'https://www.google.com/reader/api/0/search/items/ids?q=Stanford%20Javascript%20Crypto%20Library%20sentidoweb&output=json';
crl_setopt($ch,CURLOPT_HTTPHEADER,array('Authorization: GoogleLogin auth='.$auth)); 
crl_setopt($ch, CURLOPT_POST, 0);
crl_setopt($ch, CURLOPT_URL, $url);
$res = crl_exec($ch);
$datos = json_decode($res);

De aquí obtengo el ID del post dentro de Google Reader, y con ese ID obtengo los likers y muestro sus fotos:

if (isset($datos->results[0]->id)) {
  $url = 'https://www.google.com/reader/api/0/stream/items/contents?client=scroll';
  crl_setopt($ch, CURLOPT_POST, 1);
  crl_setopt ($ch, CURLOPT_POSTFIELDS, 'i='.$datos->results[0]->id);
  crl_setopt($ch, CURLOPT_URL, $url);
  $res = crl_exec($ch);
  
  $datos = json_decode($res);
  if (isset($datos->items[0]->id)) {
    $id = $datos->items[0]->id;
    $id = end(explode('/', $id));
    $url = 'https://www.google.com/reader/api/0/item/likers?i=tag%3Agoogle.com%2C2005%3Areader%2Fitem%2F'.$id.'&output=json&client=scroll';
    crl_setopt($ch, CURLOPT_POST, 0);
    crl_setopt($ch, CURLOPT_URL, $url);
    $res = crl_exec($ch);
    $data = json_decode($res);
    if (isset($data->friends)) {
      foreach($data->friends as $friend) {
        if (isset($friend->photoUrl)) {
          echo '';
        }
      }
    }
  }
}

De los likers se pueden obtener más datos, y si se hace un var_dump($data->friends) se podrá ver cómo acceder a ellos.

Está claro que un plugin para WordPress estaría bien, pero es algo más complejo si se quiere hacer bien, porque se debería obtener los ids segun URLs, entre otras cosas.

Realizar backups desde cURL

Interesante script que mediante cURL realiza un backup de nuestra web y lo inserta en un servidor FTP. No es el método más eficiente ni el más recomendable, pero si nos puede servir como ejemplo para realizar procesos similares o, por ejemplo, para crear sites de administración que necesiten realizar copias de seguridad.
El ejemplo es útil.
Create custom backups from your website using cURL

Conexiones en paralelo con cURL

Para aquellos que necesiten conexiones múltiples con cURL para acceder a varias web, este ejemplo es un buen comienzo:

<?php
// Create two cURL handlers
$ch1 = curl_init(); $ch2 = curl_init();
// Set options on both
curl_setopt($ch1, CURLOPT_URL, "http://example.com/");
curl_setopt($ch2, CURLOPT_URL, "http://example2.com/");
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
$mh = curl_multi_init();
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
$running=null;
do {
curl_multi_exec($mh,$running);
} while ($running > 0);
$data1 = curl_multi_getcontent($ch1);
$data2 = curl_multi_getcontent($ch2);
curl_multi_remove_handle($ch1);
curl_multi_remove_handle($ch2);
curl_multi_close($mh);
?>

Se trata de usar en vez de curl_init usar curl_multi_init y sus funciones asociadas.

Parallel web scraping in PHP: cURL multi functions

Vía / dzone

Laboratorio: publicar en Twitter mediante CURL

Para mí, uno de los mayores fracasos de Twitter es su API, una limitación de su uso increíble para algo que le podría dar mucho juego a la aplicación. Ahora mismo no sé en cuánto está el límite, pero la posibilidad de realizar una aplicación basada en Twitter es una pesadilla.

Para aquellos que no quieran sufrir lo que hemos sufrido con TwitterPoster (los espacios en blanco es porque la gente actualiza su imagen y no podemos recuperar la de todos los usuarios por el límite en el API de Twitter), les recomiendo usar Twitter mediante CURL.

Os paso un script sencillito que he realizado:

<?php
// Primer hacemos login
$url ="https://twitter.com/sessions";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
// Por si tienen limitación por navegador
curl_setopt($ch, curlOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)");
// Poned una ruta para las cookies
curl_setopt ($ch, CURLOPT_COOKIEJAR, '/temp/');
curl_setopt ($ch, CURLOPT_COOKIEFILE, '/temp/');
curl_setopt ($ch, CURLOPT_POSTFIELDS, "username_or_email=[usuario]&password=[contraseña]");
// Para que funcione el https
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, curlOPT_SSL_VERIFYHOST, 2);
curl_exec ($ch);
// Cargamos el home, porque Twitter añade dos campos ocultos para poder publicar por web
$url ="http://twitter.com/home";
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec ($ch);
// Recuperamos los campos ocultos
preg_match('//', $result, $match);
$authenticity_token = $match[1];
preg_match('//', $result, $match);
$siv = $match[1];
// Insertamos el texto
$res = $url ="http://twitter.com/status/update";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_POSTFIELDS, 'siv='.$siv.'&authenticity_token='.$auth.'&status=[texto]');
curl_exec ($ch);
curl_close ($ch);
unset($ch);
?>

¿Qué fallo tiene este script? pues que si cambian el HTML (campos de formulario, …) o las URLs deja de funcionar, pero al menos no tenemos limitaciones. Eso sí, es más costoso para sus servidores y para los nuestros, porque en vez de hacer una llamada, hacemos 3, y en nuestro caso, a parte parseamos una página para obtener dos campos ocultos.