0

im using a TinyMCE plugin for yii2 by 2amigos.

I need all the content entered within the editor to be sent by email.

It does a great job with background, heading color text as far I have tested.

But with pictures it shows the tag as shown below:

enter image description here

While in the editor it looks good:

enter image description here

My view:

<?php

/* @var $this yii\web\View */

$this->title = 'My Yii Application';
use dosamigos\tinymce\TinyMce;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use app\models\SendEmailForm;

$model = new SendEmailForm;

?>
<div class="site-index">


    <div class="body-content">

        <div class="row">
            <?php 
                $form = ActiveForm::begin([
                    'id' => 'sendemail-form',
                    'options' => ['class' => ''],
                    'action' => 'site/enviarcorreo'
                ]) 

             ?>

             <?= $form->field($model, 'correo') ?>

             <?= $form->field($model, 'contenido')->widget(TinyMce::className(), [
    'options' => ['rows' => 30],
    'language' => 'es',

    'clientOptions' => [
        'plugins' => [
           "print preview powerpaste casechange importcss tinydrive searchreplace autolink autosave directionality advcode visualblocks visualchars fullscreen image link media mediaembed template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists checklist wordcount tinymcespellchecker a11ychecker imagetools textpattern noneditable help formatpainter permanentpen pageembed charmap quickbars linkchecker emoticons advtable"
        ],
        'toolbar' => "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent |  numlist bullist checklist | forecolor backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | fullscreen  preview print | insertfile image media pageembed template link anchor codesample | a11ycheck ltr rtl",
        'menubar' => false,
        'convert_urls' => false,
        'file_picker_types' => 'image',
    ]
]);?>

<div class="form-group">
        <?= Html::submitButton('Enviar', ['class' => 'btn btn-primary']) ?>
    </div>
             <?php ActiveForm::end() ?>
        </div>

    </div>
</div>

Controller action:

 public function actionEnviarcorreo()
    {
        $model = new \app\models\SendEmailForm;

         if ($model->load(Yii::$app->request->post()) && $model->validate()) 
         {
            Yii::$app->mailer->compose()
             ->setFrom('darknightedm@gmail.com')
             ->setTo($model->correo)
             ->setSubject('Email enviado desde Yii2-Swiftmailer')
             ->setHtmlBody($model->contenido)
             ->send();
         }
    }

What can I do to make this possible?. Thanks for read.

2 Answers2

0

What you are really asking here are two separate questions...

  1. How do I take Base64 binary images from TinyMCE and store them in an appropriate format?
  2. What is the best way to include images in an HTML email?

How do I take Base64 binary images from TinyMCE and store them in an appropriate format

TinyMCE has a built in mechanism to address this via its images_upload_url configuration option. There is an entire page in the TinyMCE documentation on how this works:

https://www.tiny.cloud/docs/advanced/handle-async-image-uploads/

The net is that you can have TinyMCE send the image files to an endpoint of your choosing and then convert it to whatever format you need. You don't need to keep it as a Base64 binary and it is very rare that you want the Base64 binary as the permanent format.

As for the other question...

What is the best way to include images in an HTML email?

Ultimately, the real question you need to answer is "what is the best way (for my use case) to insert an image in an email". This is a very broad topic that has been answered many times - a little research should lead you to the most common approaches and their pros/cons:

https://sendgrid.com/blog/embedding-images-emails-facts/ https://www.campaignmonitor.com/blog/how-to/2008/08/embedding-images-in-email/ https://www.quora.com/Whats-the-best-practices-for-embedding-images-into-HTML-emails

As there are multiple options it really comes down to how the pro/cons of each stack up against your requirements.

Michael Fromin
  • 13,131
  • 2
  • 20
  • 31
  • Hey, thanks for your answer, let me if i understand, so do I have to create a javascript event to transform the url of an uplodaded image on the tinymce editor and thus be able to insert correctly in the email? – Ernesto España Feb 26 '21 at 15:19
  • It is likely not a "JavaScript event" - the `images_upload_url` sends the binary image data to the URL you provide so the conversion takes place server side. If your server is Node than it would be done in JavaScript but it your server side is in (for example) PHP then the conversion would be done in that language. – Michael Fromin Feb 26 '21 at 15:30
  • Aight, i read about async image uploads and i used the example provided for the docs. It only trigger when its loading for the first time the plugin, not each time i upload an image, still giving a blob url. – Ernesto España Feb 27 '21 at 05:01
0

Ok guys, based on Michael answer (Thanks a lot for the help), I read a little more detail about the plugin functions.

After many attempts trying to obtain the correct url of the image, I was finally able to find a solution, how it can help someone as I save it here as an experience.

I have done this based on what they asked me to do:

View:

<div class="row">
            <div class="col-lg-12">
                <?= $form->field($model, 'contenido')->widget(TinyMce::className(), [
                'options' => ['rows' => 20],
                'language' => 'es',
                'clientOptions' => [
                    'plugins' => [
                       "print preview paste importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools textpattern noneditable help charmap quickbars emoticons"
                    ],
                    'toolbar' => "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent |  numlist bullist | forecolor backcolor removeformat | pagebreak | charmap emoticons | fullscreen  preview save print | insertfile image link anchor codesample | ltr rtl",
                    'menubar' => false,
                    'convert_urls' => false,
                    'file_picker_types' => 'image',
                    'images_upload_url' => 'site/uploadtinyimg', //This is the url to upload automatically to your server and can embed later for the email
                    'autosave_ask_before_unload' => false
                ]
             ]);?>
            </div>
        </div>

Every time you upload an image to the editor, it calls the action uploadtinyimg from the site controller, so the action of this controller will do is take the file from the temporary folder and move it to a folder within the server and give an url to access through the editor:

/**
     * Realiza carga de imagenes por el editor TinyMCE.
     *
     * @return JSON
     */
    public function actionUploadtinyimg()
    {
        // Se valida si hay archivos cargados
        $temp = current($_FILES);

         if ($temp) 
         {
              // Se obtiene el nombre del usuario para crear la carpeta temporal
              $user = Yii::$app->user->identity->username;

              /*********************************************
               * Cambia esta linea para definir la ruta a almacenar imagenes *
               *********************************************/
              $imageFolder = Yii::getAlias('@tmpimages/').$user."/";

              // Se valida si la carpeta esta creada, si no es asi procedemos a crearla y darle permisos
              if (!file_exists($imageFolder)) 
              {
                // Crear carpeta
                FileHelper::createDirectory($imageFolder);
                // Otorgar permisos
                chmod($imageFolder, 0750);
              }

              // No permite la manipulacion de los datos mediante el atributo OPTIONS
              if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
                header("Access-Control-Allow-Methods: POST, OPTIONS");
                return;
              }

              reset ($_FILES);
              
              // Se valida si esta cargado algun archivo en el almacenamiento temporal
              if (is_uploaded_file($temp['tmp_name'])){

                // Se valida el nombre del archivo
                if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
                    header("HTTP/1.1 400 Invalid file name.");
                    return;
                }

                // Validamos la extensión
                if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
                    header("HTTP/1.1 400 Invalid extension.");
                    return;
                }

                // Se procede a indicar donde va a ser movido el archivo
                $filetowrite = $imageFolder.$temp['name'];

                // Movemos el archivo desde la carpeta temporal a nuestra carpeta seleccionada
                move_uploaded_file($temp['tmp_name'], $filetowrite);

                // Se responde con JSON si la carga fue exitosa.
                echo json_encode(array('location' => Yii::getAlias('@web/').$filetowrite));
              } 
              else 
              {
                // Si la carga ha fallado se indica
                header("HTTP/1.1 500 Server Error");
              }                 
         }
    }

Once the form was sent to send the content within the editor to the mail I did this in the controller:

I used a class called DOMDocument to be able to detect the images that have been used within the content and look for them inside the folder that indicates that they will be loaded to carry out the embedding process and that they can be seen in the email and thus delete the files later since These are temporary and not fixed and once the embedding process is done, the changes in the content with the embedded images are saved and sent by email:

// Se inicializa la clase DOM para incrustar las imagenes subidas en el editor y se puedan ver en el correo
            $dom = new \DOMDocument();
            // Cargamos el contenido realizado en el editor
            $dom->loadHTML($model->contenido);
            // Procedemos a buscar las imagenes
            $images = $dom->getElementsByTagName('img');

            foreach ($images as $image) 
            {
                // Obtenemos la antigua URL para luego obtener el nombre del archivo
                 $old_src = $image->getAttribute('src');
                 // Se obtiene el nombre del archivo
                 $imgname = basename($old_src);
                 // Se indica la ruta donde esta ubicada
                 $imgroute = Yii::getAlias('@app/web/images/tmp/').$user."/".$imgname;
                 // Se procede a incrustar las imagenes
                 $new_src = $message->embed($imgroute);
                 // Del codigo generado se cambia el SRC de la imagen por el generado
                 $image->setAttribute('src', $new_src);
            }

            // Guardamos los cambios y procedemos a indicar que el html editado es el contenido del correo
            $model->contenido = $dom->saveHTML();
            $message->setHtmlBody($model->contenido);