lunes, 15 de junio de 2015

Evitar la carpeta de SPAM al enviar emails - obviedades, tecnicismos y falsos mitos

Un compañero que está mareando con el tema del envío de e-mails me he pasado un enlace de Sendgrid, nuestro antiguo proveedor para envío de newsletters y emails:
10 Tips to Keep Email Out of the Spam Folder
  • Algunas son reglas de sentido común: no envíes correos a quien no quiere recibirlos, no uses palabras que puedan disparar filtros antispam (viagra, penis enlargement... you know), no adjuntes ejecutables, pide a los receptores que incluyan tu email en su agenda de contactos...
  • Otras son más técnicas: comprobar que están bien configurados tus DKIM, SPF, Sender-ID and Domain Keys , verificar que no estés en listas negras, hacer una comprobación previa antes del envío...
  • Y otras, pues bueno, da la impresión de que el que lo ha escrito tenía que llegar a 10 consejos, y las ha puesto de relleno: ratio texto/imágenes, enviar también versión texto... y como nosotros no estamos enviando versión texto de los emails, esto lo planteaba mi compañero como un aspecto a mejorar... aunque francamente, yo no creo que esto tenga ningún efecto en que los emails vayan o no a la bandeja de spam.
De las 10 reglas del artículo, la segunda es la que históricamente más impacto nos ha supuesto:
 2. Avoid Spam Trigger Words and Phishing Phrases
Debido a que "Rankia", nuestro dominio principal, es considerada una "spam trigger word", porque en latam dicen "la página más rankia" para webs de dudosísima reputación.... cosa que descubrimos después de dar muchísimas vueltas y leer mucha documentación.
Y bueno, en la extensa documentación que por este motivo leí en su día, no vi nunca que el enviarlas sólo en formato HTML fuera a influir en que vayan a spam. Sí que he visto en algún sitio que es una buena práctica hacerlo (no por el spam, sino por los clientes de correo "tontos"), y de hecho al principio lo hacía (en nuestra web hay algunos de los más antiguos que están en ambos formatos), pero como todo el mundo usa clientes HTML hoy en día, en algún momento dejé de hacerlo porque mientras hacía eso no estaba haciendo otras cosas, y no lo he vuelto a retomar porque nunca nadie lo ha echado en falta... y también por miedo a que después hayan cambios en una plantilla que no se acaben portando a la otra, y tengamos inconsistencias, con dos versiones del mismo correo pero que no digan lo mismo.
Tratando de contrastar este punto en Google, he buscado "spam folder text version", y los resultados no son de pááginas de Gmail, Yahoo! o Microsoft, sino posts de "10 consejos antispam" de distintos sitios (los de sendgrid han fusilado su post, u otros se lo han fusilado a sendgrid); y el único link que hay de un proveedor de correo es éste de Microsoft:
    Review email messages moved to the Junk Email folder
donde no dice que hay que enviar versión texto, sino que los mensajes se convierten a versión texto cuando entran a la bandeja de spam... me da que alguien leyó esto y lió los conceptos, y de ahí se han inventado que la versión texto tiene algo que ver con la bandeja de spam.
Conclusión: Empezad primero por las cosas de sentido común, que es lo más fácil y barato de hacer y también lo que más funciona; y no hay que perder nunca el espíritu crítico de lo que se lee, si algo no es obvio y quien lo dice no es la fuente primaria, contrastarlo nos puede sacar de dudas...
s2

lunes, 8 de junio de 2015

Inserción múltiple de registros: SQLs INSERT SELECT en Rails

Un problema típico de cualquier aplicación, sea Rails o no (o sea web o no), es el querer hacer una copia de un bloque de datos a otro sitio, con algún pequeño cambio y/o filtrado. Por ejemplo, puedo querer copiar los banners de la sección de depositos a una tabla de banners activos...

Un enfoque "de programador novato", pero que también puede verse en libros de programación de nivel básico, es hacerlo con un bucle:

  Ad.where(section: 'depositos').each do |ad|
    ActiveAd.create(title: ad.title, image_active: ad.image, url_active: ad.url)
  end

Pero si te miras los logs (algo que siempre debe hacerse), verás que este enfoque genera una SQL de INSERT por cada registro (más una para el SELECT):

  SELECT * FROM ads WHERE title = 'depositos'
  INSERT INTO active_ads (title, image_active, url_active) VALUES ('728x90 sup', 'http://images.example.org/728-dep.jpg', '/shop')
  INSERT INTO active_ads (title, image_active, url_active) VALUES ('468x60 med', 'http://images.example.org/468-dep.jpg', '/shop')
  INSERT INTO active_ads (title, image_active, url_active) VALUES ('300x250 lat', 'http://images.example.org/300-dep.jpg', '/shop')

Si el número de registros es pequeño, no pasará nada; si es mediano, el tiempo de respuesta empeorará ligeramente, y los logs se ensuciarán bastante y dejarán de ser útiles (lo cual en sí ya es un daño no despreciable)... y si el número de registros es grande, el impacto de esto hará que rendimiento del servidor se vea perjudicado, afectando también a páginas que no tengan nada que ver con este código, y entraremos en la dinámica del "Rails no escala"...

Obviamente, el problema no es que Rails no escala, sino que las cosas no deben hacerse así. Hay una instrucción SQL capaz de hacer esto en un solo paso, y es la que debe usarse:

  INSERT INTO active_ads (title, image_active, url_active) SELECT title, image, url FROM ads WHERE ads.section = 'depositos'

Este es uno de los pocos casos para los que ActiveRecord no nos da "de fábrica" una sintaxis elegante y railera para escribir la consulta. No todo está perdido: si lo usas con cierta frecuencia, la gema ar-extensions te permite hacer esto:

  ActiveAd.insert_select(
    into: [:title, :image_active, :url_active],
    select: [:title, :image, :url],
    from: :ads,
    conditions: ['section = ?', 'depositos'],
  )

Pero si es para un uso puntual, quizá no valga la pena añadir una gema al proyecto sólo para limpiar unas pocas consultas... Si este es el caso, la opción es lanzar la SQL directamente:

  sql = "INSERT INTO active_ads (title, image_active, url_active) SELECT title, image, url FROM ads WHERE ads.section = 'depositos'"
  ActiveRecord::Base.connection.execute(sql)

No nos engañemos: esto no es la panacea, insertar muchos registros nunca va a ser una tarea ligera para el servidor. Pero al menos, habremos optimizado el rendimiento en una zona crítica, y además dejaremos de ensuciar los logs, y por si fuera poco la query aparecerá en el log de consultas lentas de MySQL y podremos detectar más fácilmente los problemas para tratar de optimizarlos.

lunes, 1 de junio de 2015

Hosting en Rails

Tras más de siete años en Rails, con necesidades que han ido evolucionando a medida que multiplicamos por 10 el tráfico, hemos pasado ya por bastantes proveedores de hosting en Rails, y nos gustaría compartir nuestra experiencia por si os es de utilidad...

Railsplayground, nuestro primer hosting de desarrollo en Rails

En la etapa del primer desarrollo de la web en Rails, buscamos un hosting que por poco dinero nos permitiera tener un entorno de pruebas "real". Probablemente hoy Heroku sería la mejor opción para el hosting de una aplicación en desarrollo, pero era 2007 y no existía Heroku, así que nos decantamos por Railsplayground... y francamente, la experiencia fue muy buena; por 9 euros/mes, teníamos un Virtual Private Server (VPS) bastante decente, y ayuda por parte de sus técnicos para "montar la paraeta" desde cero, lo cual venía muy bien porque en aquella época las cosas no estaban aún demasiado documentadas...
Dada la calidad del servicio de Railsplayground, nos hubiera encantado mantener con ellos el hosting en producción; pero para meter nuestra base de datos en un servidor americano, la ley nos obligaba a que fuera uno que cumpliera con Safe Harbor, y lamentablemente Railsplayground no estaba entre ellos, así que tuvimos que buscar uno que lo cumpliera... o uno español, para evitarnos líos legales.

Ferca, nuestro primer hosting de producción en Rails

Ferca (actualmente fusionada en Acens) fue una buena muestra de lo que vienen siendo los hosting españoles: mucho más caros y con peor servicio que los equivalentes americanos. Nuestra aplicación rails corría en un servidor dedicado, de varios cientos de euros al mes, y sin embargo el servicio de atención al cliente estaba muy lejos de la atención que nos daban con nuestro servidor VPS de 9 euros en Railsplayground... afortunadamente, pudimos contar con los servicios de Eduardo Fernandez (gracias, Edu!!) para mantenerlo todo funcionando sin tener en casa un especialista en sistemas.
Tener el hosting en España tiene una serie de ventajas importantes:
  • No hay complicaciones legales.
  • Tienes un menor tiempo de latencia.
  • El horario del servicio al cliente coincide con el tuyo, y hablan tu idioma.
Pero francamente, la diferencia de precio y de servicio entre Railsplayground y Ferca era abismal, y sobrepasaba con creces estas ventajas... a cualquiera que vaya a buscar un hosting de rails en España, le recomendaría que al menos valore también los hosting de fuera de España, especialmente los hosting especializados en Rails.

OVH, un hosting barato realmente barato

En parte porque se nos empezaba a quedar pequeño, y en parte por la cuestión económica, empezamos a mirar otros servidores dedicados, y acabamos pillando uno en OVH que tenía seis veces más de memoria y cuatro veces más de procesador que el de Ferca, por una tercera parte de lo que nos costaba el anterior. El cambio no fue trivial, pero valió la pena... ahora, eso sí, OVH es un hosting low cost para lo bueno y para lo malo!! Con OVH, como tengas un problema que no sepas resolver tú y dependas de ellos, te vas a arrepentir de todo lo que has ahorrado en hosting...

BrightBox, un hosting especializado en Rails con buen servicio... para proyectos pequeños

Para que los programadores nos dedicáramos a programar y no a mantenimiento de sistemas, empezamos a buscar alternativas de hosting que nos dieran ya no sólo el hosting, sino también el servicio de mantenerlo todo a punto. Y eso nos llevó a BrightBox, un hosting realmente especializado en Rails. Y como los experimentos se hacen con gaseosa, pues movimos a BrightBox la web pequeñita del grupo, Mimandote.com.
La experiencia fue una maravilla, todo funcionaba muy bien y era muy fácil de instalar y configurar, así que después movimos la mediana, Verema.com, y después la grande, Rankia.com... y aquí vino el infierno.
Por decirlo claramente: BrightBox no está preparado para webs grandes. Su servicio de atención al cliente fue impecable, se volcaron con nosotros, nos ayudaron a configurarlo todo, nos asesoraron... pero aquello no soportaba la carga de nuestra web. Contratamos más instancias ("brightboxes"), añadiendo un balanceador; el precio se nos disparó, pero la web tenía que funcionar... y aún así no funcionaba.
Sin nada que perder, porque la web se nos estaba cayendo permanentemente, buscamos una alternativa de urgencia y que nos diera el nivel de servicio que queríamos; Heroku no era una opción, porque no cumplía Safe Harbor (no sé si hoy lo cumplirá), así que acabamos en EngineYard casi por eliminación. Hicimos el cambio con urgencia y sin tiempo para probar las cosas, pero afortunadamente la web funcionó bien.

EngineYard, un hosting especializado en Rails con buen servicio... para proyectos grandes

EngineYard, más que una empresa de hosting, es una empresa de servicios que se encarga de que todo lo relacionado con el hosting de tu aplicación Rails funcione bien, utilizando los servicios de hosting de Amazon (de forma transparente para el cliente) y cargandote aproximadamente un 20% adicional a lo que cuesta el hosting de Amazon.
¿Y cuanto cuesta? Pues depende de lo que necesites... para Rankia (hablamos de 10 millones de páginas/mes) tenemos tres instancias medium (una de BD y dos de aplicaciones), que son algo más de $500/mes; para Verema, tenemos dos medium ($350), una de BD y otra de aplicaciones y vamos sobrados; y para Mimandote, que es más pequeña, nos apañamos bien con una small ($90/mes). No es barato, considerando que teníamos un dedicado por 80 euros/mes, pero ahora nos dedicamos a programar y no a sistemas, y el número de incidencias relacionadas con el hosting se ha reducido bastante. Y el servicio que nos dan cada vez que necesitamos algo es muy bueno, esa atención al cliente es algo que los americanos hacen realmente bien.
Eso sí, aparte del hosting, hay otros servicios que en un servidor dedicado tienes, pero con EngineYard no:
  • Resolución de DNS
  • Envío de correos
  • Almacenamiento de archivos estáticos
Todo eso se tiene que contratar con terceros, y aunque no es tampoco muy caro, y además obtienes un servicio mejor que el que tendrías en tu servidor dedicado (los que se dedican a eso lo tienen muy "currao"), es un dinero con el que también debes contar a la hora de valorar el cambio. Por si os sirve de algo, nosotros lo tenemos con DNSimple.com , SendGrid.com y Amazon S3
Eso sí, lo que no tiene EngineYard es un plan gratuito para empezar al estilo de Heroku (sí que tiene un trial de 30 días, pero pasados los 30 dias te toca pagar mínimo $90/mes, aunque sea un mini-proyecto), por lo que sólo lo considero óptimo para aplicaciones que ya hayan alcanzado cierto tamaño...