Faire un lien dans un email dans une application Ruby on Rails devrait être aussi simple que de faire un lien dans le reste de l’application, non ?
Mais voilà, un simple link_to root_url
renvoie une exception car il faut un nom de domaine pour faire une URL. Pour ça il faut configurer un nom de domaine par défaut pour chaque environnement.
En développement un site varie beaucoup selon les configurations et les tests. Par exemple foo.dev,
localhost
, sunny.local
et 192.168.1.42.foo.xip.io
, sont des noms de domaines possibles et utiles pour mon application en développement. Le port (80, 3000, 8080) et le protocole (http ou https) sont également des paramètres qui peuvent changer lors des différents tests.
En production votre nom de domaine peut également varier. Par exemple en.cults3d.com
et fr.cults3d.com
sont deux noms de domaines utilisés par la même application, en même temps. Il est donc impossible de trouver un nom de domaine par défaut à utiliser sur chaque lien.
C’est pénible de devoir spécifier le domaine à chaque fois, c’est source de bugs.
Pour éviter cette configuration « en dur » il existe une manipulation simple qui consiste à modifier l’URL par défaut à chaque requête.
En ajoutant à son application_controller.rb
:
before_filter :make_action_mailer_use_request_host_and_protocol
def make_action_mailer_use_request_host_and_protocol
ActionMailer::Base.default_url_options[:protocol] = request.protocol
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end
Attention, cette solution ne vous prémunit pas contre le host injection exploit.
Si votre site déclenche un email (demande de mot de passe par exemple) et qu’un méchant indique comme hôte « evil.com » alors vous allez envoyer des emails ayant des liens en « evil.com ».
Si votre site utilise du cache ces attaques touchent sans doute déjà votre application ! Pour s’en prémunir, ajoutez donc un filtre des noms de domaines autorisés en production.
Cette solution (corrigez-moi si je me trompe) souffre d’un problème de race condition. Non, ce n’est pas un problème de racisme envers certains noms de domaines qu’elle ne peut pas blairer.
Le problème est plutôt qu’une requête plus lente peut modifier sans le vouloir le domaine d’une autre requête. Une meilleure solution thread-safe existe sans doute. Si vous avez une piste élégante je suis preneur.
Et parce qu’une ligne de code testée dans une librairie dédiée vaut mieux que 2 lignes copié-collées dans votre projet, vous pouvez également ajouter ce code grâce à ma petite gemme :
action_mailer_auto_url_options.
est un développeur web vivant à Paris — Contact — Archives
Textes et contenus sous licence Creative Commons.