getgrav / grav-plugin-email

Grav Email Plugin
http://getgrav.org
MIT License
37 stars 29 forks source link

how can I attach an *existing* file to an email? #121

Closed skinofthesoul closed 1 year ago

skinofthesoul commented 5 years ago

Hello there, I have a form underneath pages of a certain type. These pages also have a pdf file associated with them (in the page header). Upon submitting the form I would like to send an email with that page's pdf file attached. But I don't know how to give the details? I currently have a hidden field:

<input type="hidden" name="data[pdf-file]" value="path/to/file.pdf" />

and I reference this in the form header like this:

    process:
        -
            email:
                to: '{{ form.value.email }}'
                subject: 'test test'
                body: '{% include ''forms/data.html.twig'' %}'
                attachments:
                  - 'form.value.pdf-file'

This does not attach the file though. What format do the file details need to have?

daddyfix commented 4 years ago

I just spent a few days learning how the back end of GRAV CMS Email works.

This is my hack to embed a static image

Edit to form.md

Added embedimages:

form.md

...
process:
    email:
        from: '{{ config.plugins.email.from }}'
        to:
            - '{{ config.plugins.email.from }}'
            - '{{ form.value.email }}'
        subject: '[Contact] {{ form.value.name|e }}'
        body: '{% include ''forms/email_template.html.twig'' %}'
    attachments:
        - 'my-file'
    embedimages:
        - /images/cover_3_email_header.jpg
    save:
        fileprefix: contact-
        dateformat: Ymd-His-u
        extension: txt
        body: '{% include ''forms/data.txt.twig'' %}'
    message: 'Thank you from contacting me. I will get back to you soon.'
    display: /form/thankyou

Edit to email.php

Adjusted function sendFormEmail

user/plugins/email/email.php

    protected function sendFormEmail($form, $params, $vars)
    {
        // Build message
        $message = $this->email->buildMessage($params, $vars);

        if (isset($params['attachments'])) {
            $filesToAttach = (array)$params['attachments'];
            if ($filesToAttach) foreach ($filesToAttach as $fileToAttach) {
                $filesValues = $form->value($fileToAttach);

                if ($filesValues) foreach($filesValues as $fileValues) {
                    if (isset($fileValues['file'])) {
                        $filename = $fileValues['file'];
                    } else {
                        $filename = ROOT_DIR . $fileValues['path'];
                    }

                    try {
                        $message->attach(\Swift_Attachment::fromPath($filename));
                    } catch (\Exception $e) {
                        // Log any issues
                        $this->grav['log']->error($e->getMessage());
                    }
                }
            }
        }

        /*************************************************
          Attach Embeded Images
          DaddyFix Hack May 5 2020

         Make sure you edit you form.html.twig file and add and 
         img tag with 'cid:' or '[CID]' for the src
         ie. <img src="cid:' border="0">

        Issue: embedimages needs an array of images but
                   there is only the last one item in the array that is embedded.
                   I'm too tired to fix this tonight.
         *************************************************/
        if (isset($form->process['embedimages'])) {

            $filesToAttach = (array)$form->process['embedimages'];
            if ($filesToAttach) foreach ($filesToAttach as $fileToAttach) {
                    // DIR is your plugin dir (user/plugins/email)
                    $filename = __DIR__ . $fileToAttach;

                    try {
                        $cid = $message->embed(\Swift_Image::fromPath($filename));

                        $temp = $message->getBody();
                        $pattern=array();
                        $pattern[0]='/\"cid:.*?\"/';
                        $pattern[1]='/\"\[CID\]\"/';
                        $replacements=array();
                        $replacements[0] = $replacements[1] = '"'.$cid.'"';
                        $adjustedBody = preg_replace($pattern, $replacements, $temp);

                        if (strcmp($temp, $adjustedBody) !== 0) {
                            $message->setBody($adjustedBody);
                        }

                    } catch (\Exception $e) {
                        // Log any issues
                        $this->grav['log']->error($e->getMessage());
                    }
            }
        }
        else {
            $this->grav['log']->info('embedimages array is not set');
        }

        // Send e-mail
        $this->email->send($message);
    }
...

Adjusted the base.html.twig

Added the embed image tag. NOTE You have to have the image tag in the following two formats <img src="cid:">

or

<img src="[CID]">

user/plugins/email/templates/email/base.html.twig

<!-- body -->
<table class="body-wrap" bgcolor="#f6f6f6">
    <tr>
        <td></td>
        <td class="container" bgcolor="#FFFFFF">
            <div class="content">
                <table>
                    <tr>
                        <td>
                            <!-- JPG Email Header -->
                            <div style="margin-left: auto; margin-right: auto; margin-bottom: 20px;">
                                <img src="cid:" border="0">
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            {% block content %}
                            {{ content|raw }}
                            {% endblock content %}
                        </td>
                    </tr>
                </table>
            </div>
        </td>
        <td></td>
    </tr>
</table>
<!-- /body -->

Extra Info

Turns out that the Swift PHP Mailer already has an function (& class) to embed files user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php

Hope this helps someone.

ricardo118 commented 4 years ago

btw you do not need to edit the user/plugins/email/email.php function grav has an event that you can attach to onFormProcessed and do the same thing you are doing directly from your theme and or plugin.

The same goes for editing user/plugins/email/templates/email/base.html.twig you do not need to edit the plugin itself. simply copy the structure /templates/email/base,html.twig to your theme and for there you can edit. Theme templates take priority over plugin's

daddyfix commented 4 years ago

Oh- Boy! Im a loser! Thanks

On Wed, May 6, 2020 at 10:16 AM ricardo118 notifications@github.com wrote:

btw you do not need to edit the user/plugins/email/email.php function grav has an event that you can attach to onFormProcessed and do the same thing you are doing directly from your theme and or plugin.

The same goes for editing user/plugins/email/templates/email/base.html.twig you do not need to edit the plugin itself. simply copy the structure /templates/email/base,html.twig to your theme and for there you can edit. Theme templates take priority over plugin's

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/getgrav/grav-plugin-email/issues/121#issuecomment-624674114, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABEIKUZV3RHNT7JAM3NSP4LRQFWMHANCNFSM4IJLIS5A .

-- Michael Connors B.S. C.S.

madduci commented 3 years ago

Hi @ricardo118 ,

could you please formulate it better? How can be done via Plugin or Theme? e.g. I want to inject some PDF files (e.g. whitepapers), how can it be done, so the Email Plugin can send emails with attachment?

Thanks

rhukster commented 1 year ago

With 4.0 this behavior is changing a bit. There are now more flexible attachment options: https://symfony.com/doc/current/mailer.html#file-attachments

You would just need to get the email object and manually add your attachment:

$email = Grav::instance()['Email']->message($subject, $body)->to($to)->from($from)->getEmail();
$email->attachFromPath('/path/to/your/file.pdf');

Of course you can use ->buildMessage() instead of ->message() if you want to pass in an array of properties.