Home > OS >  Image not accessible in email template by absolute URL when using Symfony and Webpack Encore
Image not accessible in email template by absolute URL when using Symfony and Webpack Encore

Time:08-10

What I'm trying to achieve

I am trying to add an image to an HTML email template I am testing out using Symfony Mailer, with an email controller and a twig file for my HTML template.

My environment

  • Symfony 6.0 set up on WSL2
  • Symfony Mailer
  • Webpack Encore
  • MailHog
  • localhost

Steps I've taken

  1. Set up Webpack Encore so my image directory in my assets directory is fully copied across to the build directory
  2. Run npm run watch to compile my assets into the public directory
  3. Set up an emailController which sends an email when https://localhost:8000/email is accessed
  4. Run an instance of MailHog to review my emails on http://localhost:8025/
  5. Made a Twig file accessed via the htmlTemplate method of the TemplatedEmail object
  6. Inserted an image into my email template using a src attribute of src="{{ absolute_url(asset('build/images/my-image.png')) }}" on an img tag
  7. Reload https://localhost:8000/email to send an email for review on MailHog

What I expected to happen

To open the email with the image visible and being served via https://localhost:8000/build/images/my-image.png.

What actually happens

I get a broken image and when I try accessing the image via the url https://localhost:8000/build/images/my-image.png, there is no image available.

What I've tried

  • Reviewing what files are available from my localhost site by checking Sources in dev tools, and only webpage-specific assets are ever available from the build directory
  • Tried creating a new email-images directory in my public directory to store images and access via here for my emails - but I still get broken links as the images aren't available in the public directory of localhost

Conclusion

I essentially need to set some assets to be always available and served for me to access them via localhost:8000/any/path. I believe it's something I need to configure on Webpack Encore, but I'm not too sure how to do this and couldn't find anything in the documentation.

Thanks very much for your help! And please let me know if you need any more info.

Attachments

My webpack.config.js file

// Any changes to webpack.config.js requires encore to be restarted (i.e. CTRL C and rerun npm run watch)
const Encore = require('@symfony/webpack-encore');

// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // public path used by the web server to access the output path
    .setPublicPath('/build')
    // only needed for CDN's or sub-directory deploy
    //.setManifestKeyPrefix('build/')

    /*
     * ENTRY CONFIG
     *
     * Each entry will result in one JavaScript file (e.g. app.js)
     * and one CSS file (e.g. app.scss) if your JavaScript imports CSS.
     */
    .addEntry('app', './assets/app.js')
    // Individual files - page specifc and imported where needed:
    // about-me
    .addEntry('about-img', './assets/js/about-me/about-img.js')
    // component
    .addEntry('card-animate', './assets/js/component/card-animate.js')
    .addEntry('go-to-button', './assets/js/component/go-to-button.js')
    .addEntry('modal', './assets/js/component/modal.js')
    .addEntry('parallax-scroll', './assets/js/component/parallax-scroll.js')
    .addEntry('slider-cards', './assets/js/component/slider-cards.js')
    // web-development
    .addEntry('circle-animate', './assets/js/web-development/circle-animate.js')
    // general
    .addEntry('lazy-loading', './assets/js/lazy-loading.js')
    .addEntry('remove-vsc', './assets/js/remove-vsc.js')
    // .addEntry('different_page', './assets/different_page.js')
    // To add stylesheets for pages which don't need their own js file:
    // .addStyleEntry('new_stylesheet', './assets/styles/new_stylesheet.scss')

    // enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
    .enableStimulusBridge('./assets/controllers.json')

    // When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
    .splitEntryChunks()

    // will require an extra script tag for runtime.js
    // but, you probably want this, unless you're building a single-page app
    .enableSingleRuntimeChunk()

    /*
     * FEATURE CONFIG
     *
     * Enable & configure other features below. For a full
     * list of features, see:
     * https://symfony.com/doc/current/frontend.html#adding-more-features
     */
    .cleanupOutputBeforeBuild()
    // .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    // enables hashed filenames (e.g. app.abc123.css)
    .enableVersioning(Encore.isProduction())

    .configureBabel((config) => {
        config.plugins.push('@babel/plugin-proposal-class-properties');
    })

    // enables @babel/preset-env polyfills
    .configureBabelPresetEnv((config) => {
        config.useBuiltIns = 'usage';
        config.corejs = 3;
    })

    // enables Sass/SCSS support
    .enableSassLoader()
    .enablePostCssLoader()

    // Copy files to enable their reference from twig templates
    .copyFiles({
        from: './assets/img',
        to: 'images/[path][name].[ext]'
    })

    // SVG sprite plugin
    // .addLoader({
    //     test: /\.svg-sprite-webpack-plugin$/,
    //     loader: 'svg-sprite-webpack-plugin'
    // })

    // uncomment if you use TypeScript
    //.enableTypeScriptLoader()

    // uncomment if you use React
    //.enableReactPreset()

    // uncomment to get integrity="..." attributes on your script & link tags
    // requires WebpackEncoreBundle 1.4 or higher
    //.enableIntegrityHashes(Encore.isProduction())

    // uncomment if you're having problems with a jQuery plugin
    //.autoProvidejQuery()
;

    // Use polling instead of inotify
    const config = Encore.getWebpackConfig();
    config.watchOptions = {
        poll: true,
    };

module.exports = config;

CodePudding user response:

As you are making use of TemplatedEmail object, the email variable is automatically added to the template.

For the images to be visible inside of your template, however, you should add the following line to config/packages/twig.yaml

    paths:
        'assets/images': images

Once that is done, you can simply use the following in your templates:

<img src="{{ email.image('@images/my-image.png') }}">

You can read more about it in the symfony docs.

CodePudding user response:

Absolute nightmare... After testing out the suggested solutions kindly given, I tried a different image just to check.. and it worked. sighs.

Unfortunately this was less of a dev issue, the logo I exported from Figma as a png just must have been corrupted in the process as the file wouldn't even open on my computer. I re-exported the logo and now it works fine, even using the original src="{{ absolute_url(asset('build/images/my-image.png')) }}" method of attaching the image.

No modifications to my twig.yaml file or the above code were required - always sanity check with other images I guess is the lesson from this! Thanks everyone for your time looking into my issue however

  • Related