2010-08-06 12 views
0

Je tente d'envoyer un e-mail HTML à partir d'une tâche symfony (1.4.6), je ne veux pas envoyer la totalité de la sortie HTML rendue à partir d'un module/action particulier , donc je rends un partiel. Tout va bien, le problème est que le partiel contient des références CSS.Incluant CSS dans un e-mail envoyé depuis une tâche dans symfony

Existe-t-il une manière symfonique d'inclure un fichier CSS dans un email HTML à partir d'une tâche symfony, alors que tout ce que je fais est de rendre un partiel spécifique? Ou est la seule solution pour construire la tête/corps HTML manuellement à l'intérieur de la tâche, en utilisant file_get_contents(cssFile) pour récupérer le fichier CSS, puis en concaténant la partie rendue?

Toutes les pensées seraient appréciées.

+2

Theres d'autres informations sur CSS dans les courriels que vous pouvez regarder : http://www.campaignmonitor.com/css/ – Navarr

+0

OK, c'est utile, merci. Je suppose qu'une solution consiste à ajouter tout le style directement aux balises HTML, mais j'espérais éviter de le faire ... Le CSS que je veux inclure n'est pas complexe du tout. – chattsm

Répondre

2

J'ai rencontré le même problème dans mon projet. Voici comment je l'ai fixé:

  1. Pour garder le CSS séparé, mais l'obtenir en ligne avant d'envoyer l'e-mail, nous utilisons Emogrifier. Téléchargez le code source et placez-le au %sf_lib_dir%/vendor/emogrifier.

  2. Créez une classe myMailer qui étend sfMailer. Le mien est ci-dessous. Il existe quelques fonctions distinctes, mais la fonction clé est composeAndSendPartial, qui prend un nom partiel (sous la forme d'une chaîne), insère tous les CSS en ligne et l'envoie. J'ai essayé d'enlever tout le code qui est spécifique à mon projet, mais j'ai peut-être laissé un peu dedans. Faites-moi savoir si cela ne fonctionne pas pour vous ou si vous avez des questions.

  3. En factories.yml, définissez le mailer: à myMailer

myMailer.class.php:

<?php 
class myMailer extends sfMailer 
{ 
    /** 
    * Creates a new message with 2 bodies: 
    * * 1 with $body and MIME type text/html. 
    * * 1 with $body and tags stripped with MIME type text/plain. Stipped <br/>, </p>, and </div> tags and replaced with \n 
    * 
    * @param string|array $from The from address 
    * @param string|array $to  The recipient(s) 
    * @param string  $subject The subject 
    * @param string  $body The body 
    * 
    * @return Swift_Message A Swift_Message instance 
    */ 
    public function composeAndSendHtml($from, $to, $subject, $body) 
    { 
    return $this->send($this->composeHtml($from, $to, $subject, $body)); 
    } 


    /** 
    * Sends a message using composeHtml. 
    * 
    * @param string|array $from The from address 
    * @param string|array $to  The recipient(s) 
    * @param string  $subject The subject 
    * @param string  $body The body 
    * 
    * @return int The number of sent emails 
    */ 
    public function composeHtml($from = null, $to = null, $subject = null, $body = null) 
    { 
    return Swift_Message::newInstance() 
     ->setFrom($from) 
     ->setTo($to) 
     ->setSubject($subject) 
     ->addPart($this->createPlainTextBody($body), 'text/plain') 
     ->addPart($body, 'text/html'); 
    } 


    /** 
    * Attempts to create a plaintext message with all html tags stripped out and new lines inserted as necessary 
    * @param $body 
    * @return $body 
    */ 
    public function createPlainTextBody($body) 
    { 
    $body = preg_replace('/\<br\s*\/?\>/i', "\n", $body); //replace all <br/s> with new lines 
    $body = preg_replace('/\<\/p\s*\>/i', "</p>\n\n", $body); //append 2 newlines to the end of each </p> 
    $body = preg_replace('/\<\/div\s*\>/i', "</div>\n\n", $body); //append 2 newlines to the end of each </div> 
    $body = strip_tags($body); //strip all tags from the body 
    return $body; 
    } 

    /** 
    * Composes and sends an email with a body from rendering $partial with $parameters 
    * @param string $from 
    * @param string $to 
    * @param string $subject 
    * @param string $partial the partial as a string. Feel free to change the default module name below 
    * @param array $parameters Parameters for the partial 
    * @param array $globalStylesheets The stylesheets that are included globally (usually global.css, maybe others) 
    */ 
    public function composeAndSendPartial($from, $to, $subject, $partial, $parameters = array(), $globalStylesheets = array()) 
    { 
    require_once(sfConfig::get('sf_lib_dir') . '/vendor/emogrifier/emogrifier.php'); 

    $context = sfContext::getInstance(); 
    $response = $context->getResponse(); 
    $originalStylesheets = $response->getStylesheets(); 

    if (false !== $sep = strpos($partial, '/')) 
    { 
     $moduleName = substr($partial, 0, $sep); 
     $templateName = '_' . substr($partial, $sep + 1); 
    } 
    else 
    { 
     $moduleName = 'email'; 
     $templateName = '_' . $partial; 
    } 

    sfConfig::set('sf_is_email', true); 
    $view = new sfPHPView($context, $moduleName, $templateName, ''); #not sure what 4th parameter does 
    $view->getAttributeHolder()->add($parameters); 
    $view->setDecorator(true); 
    $view->setDecoratorTemplate('email.php'); 
    $html = $view->render(); 
    sfConfig::set('sf_is_email', false); 

    $emailStylesheets = array_keys(array_diff_key($response->getStylesheets(), $originalStylesheets)); 

    $css = ''; 
    foreach($globalStylesheets as $globalStylesheet) 
    { 
     $css .= file_get_contents(sfConfig::get('sf_web_dir') . '/css/' . $globalStylesheet . '.css'); 
    } 
    foreach ($emailStylesheets as $stylesheet) 
    { 
     $css .= file_get_contents(sfConfig::get('sf_web_dir') . '/css/' . $stylesheet . '.css'); 
     $response->removeStylesheet($stylesheet); 
    } 

    $emog = new Emogrifier($html, $css); 
    $body = $emog->emogrify(); 

    $this->composeAndSendHtml($from, $to, $subject, $body); 
    } 
}