L’une des grandes mises à jour de Rails 3 est la nouvelle API Action Mailer.
Petit rappel : dans les versions précédentes de Rails, nous pouvons transmettre des emails en créant, dans le répertoire app/models un modèle ActionMailer.
Celui-ci pourrait ressembler (dans rails 2.3) à ceci :

class UserMailer < ActionMailer::Base
    def welcome_email(user)
        recipients user.email
        from "I'm nobody <42@unknown>"
        subject "Hello World"
        body {:user => user }
    end
end

Et dans le répertoire app/views/user_mailer, nous pourrons créer un fichier welcome_email.text.erb qui sera le contenu de notre email.
Maintenant supposons que nous désirions attacher une pièce jointe à notre email.
Nous allons devoir ajouter dans notre méthode welcome_email cette pièce jointe.

attachment "application/pdf" do |a|
    a.body = contenu_du_pdf()
end

un « beurk » suffira !

Dans Rails 3, notre méthode d’envoi d’email devient la suivante :

class UserMailer < ActionMailer::Base
    default :from => "I'm nobody <42@unknown>"

    def welcome_email(user)
        @user = user
        mail(:to => user.email,  :subject => "Hello World")
    end
end

Et lorsque nous souhaitons ajouter une pièce jointe, nous n’avons qu’à faire :

attachments['terms.pdf'] = {:content => contenu_du_pdf() }

C’est déjà plus sympa.

Mais ce n’est pas tout ! Par défaut, les fichiers welcome_mail.text.erb et welcome_mail.html.erb sont inclus dans le mail.
Ainsi la personne recevant l’email peut le lire en html ou en texte.
Mais tout comme vous le faites dans vos contrôleurs pour l’html, le json, l’xml ou tout autre format, vous pouvez vouloir rendre quelque chose de différent en fonction du format html ou texte du mail.

Go ! :)

mail(:to => user.email,  :subject => "Hello World") do |format|
    format.text { render :text => "Mon email est en texte" }
    format.html { render :html => "Mon email est en <strong>HTML</strong>" }
end

Pour continuer lorsque vous envoyiez votre email, vous faisiez cela de la manière suivante :

UserMailer.deliver_welcome_email(@user)

Vous devrez maintenant faire :

UserMailer.welcome_email(@user).deliver

Le welcome_email vous renvoyant un objet Mail que vous pouvez ainsi modifier comme bon vous semble.
Voir le stocker pour l’envoyer plus tard par exemple.
Si vous désirez plus d’informations concernant cette nouvelle API, je vous recommande l’article sur guides.rails.info (encore en cours de rédaction).
Et le gist qui a servi de spécification pour cette nouvelle API.

De la même manière que en Ruby, Django propose une solution d’envoi d’email.
Mais toute application Python n’utilise pas forcément Django. Et il peut arriver d’avoir besoin d’envoyer un email sans Django.

C’est ce que j’ai fait en développant l’outil de rapport de positions par email de RefStats.

Pour cela, nous allons utiliser la librairie smtplib.
Commençons par importer cette librairie.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

Puis envoyons notre email.
msg = MIMEMultipart('alternative')
msg['Subject'] = 'Sujet de l\'email'
msg.attach(MIMEText('contenu texte', 'text'))
msg.attach(MIMEText('contenu html', 'html'))
email = smtplib.SMTP()
email.connect('localhost')
# email d'envoi - email de réception - message
email.sendmail('noreply@dmathieu.com', 'you@example.org', msg.as_string())
email.close()

Nous instancions l’email, y définissions son sujet.
Ainsi que du contenu html et du contenu texte.
Puis nous nous connectons au serveur smtp (ici localhost) et envoyons l’email.

Si vous avez déjà essayé d’envoyer un email avec rails, vous avez constaté que c’est articulièrement aisé.
Mais ruby ce n’est pas que du rails !
Dans le cas du redéveloppement de Refstats par exemple, j’ai recodé le crawler de celui-ci, qui va récupérer de manière journalière les positions de chacun de vos sites.
Et je désire être rapidement être mis au courant si j’ai une erreur qui est apparue afin de pouvoir la corriger tout aussi vite.

Du coup si je soulève une exception, je veux m’envoyer un email.
Bien évidemment, je n’ai qu’une application console.
Pas de rails derrière, bien que j’utilise Active Record.

Du coup pas d’action mailer. Et pas de fonction « mail » comme en PHP.

Il est cependant assez aisé d’envoyer un email :
require 'net/smtp'
def send_email(from, to, subject, message)
  msg = "Subject: " + subject + "\r\n\r\n" + message
  Net::SMTP.start('localhost') do |smtp|
    smtp.send_message msg, from, to
  end
end

Nous déclarons une méthode send_email, qui prends les paramètres :
email de l’envoyeur; email du destinataire; sujet de l’email et son message.

Nous créons l’entête du message avec son sujet.
Puis nou instancions un Net::SMTP avec l’adresse du serveur SMTP (et en second paramètre son port si autre que 25).
Et on envoie notre message !
Pour plus de détails, notamment l’identification, je vous invite à vous référer à la documentation de Net::SMTP.

Un petit article rapide. Lorsque vous testez vos applications, l’envoi d’email est toujours embettant. Vous n’avez pas envie de l’email parte vraiment et souhaitez vérifier qu’il pars correctement.

Du coup il faut utiliser un Mock, qui va simuler l’envoi d’email mais n’enverra, en fait, rien.
Et qui vous permettra tout de même de surveiller l’email envoyé et de vérifier qu’il est correct.

Commençons, dans notre vue, par envoyer notre email :
from django.core.mail import send_mail
def envoi(self):
  send_mail(
    'A propos des tests',
    'C\'est fun quand même',
    'from@example.com',
    'to@example.com'
)

Et testons notre méthode :
from django.core import mail
def test_send(self):
  response = self.client.post('/envoi')
  self.failUnlessEqual(response.status_code, 302)
  self.assertEquals(len(mail.outbox), 1)
  self.assertEquals(mail.outbox[0].subject, 'A propos des tests')

Ainsi lorsque nous lançons notre test, en supposant que l’url /envoi soit configurée pour diriger vers notre action envoi, celle-ci sera exécutée, l’email sera envoyé de manière fictive.
Et vous aurez accès à un tableau dans mail.outbox qui contiendra tous les emails envoyés avec leur contenu, leur sujet et les personnes à qui ils ont été envoyés.

A vous, par la suite, d’écrire les tests appropriés au bon fonctionnement de votre application.

 
Fork me on GitHub