0

I just updated the Laravel version for my project from 7 to 9, which switches to using Symfony Mailer instead of SwiftMailer, under the hood. So in my emails, I'm using this method (Inline Attachments) which is specified in the documentation for embedding images. Still, all emails containing embedded images are interpreted by email clients as having attachments (meaning the attachment icon is visible, usually a paperclip). In contrast, previously, in version 7, this was not the case.

How would I fix this so the email client correctly shows the attachment icon only when I attach a separate document to the email?

Karl Hill
  • 12,937
  • 5
  • 58
  • 95
user883992158
  • 325
  • 3
  • 17

2 Answers2

4

The issue you are facing is most likely because Symfony Mailer includes inline images as attachments by default. To fix this, you need to add a Content-Disposition header to each inline image to indicate that it should be displayed inline rather than as an attachment.

https://symfony.com/doc/current/mailer.html#embedding-images

use Symfony\Component\Mime\Part\DataPart;

// ...

$imageData = file_get_contents('/path/to/image.png');

$imagePart = new DataPart($imageData, 'image/png', 'inline');
$imagePart->setFilename('image.png');
$imagePart->headers->set('Content-Disposition', 'inline');

$mail->addPart($imagePart);
  • I would also add not all email clients honour this, plenty of Mail clients still show them as attachments because technically they are all the inline does is say this should not be shown as an attachment because it's used in the body of the email. – Barkermn01 Apr 01 '23 at 10:12
  • @Barkermn01 is there another option than? base64 the images and embedding them directly in the source? – Giacomo Tüfekci Apr 05 '23 at 03:09
  • Yeah, you can host the images on a Web Server or Public AWS S3 bucket and then use them in your emails just provide the full URL to the `` `src` attribute. – Barkermn01 Apr 05 '23 at 17:15
0

Modifying the Content-Disposition header to inline for embedded images may fix this issue. You can do this by creating a custom Mailer class that extends the Symfony Mailer class and overrides the createAttachment method to set the correct header for inline images.

Below is a mailer class example:

namespace App\Mail;

use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\InlinePart;
use Symfony\Component\Mime\Part\PartInterface;
use Symfony\Component\Mime\Attachment\Attachment;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Message;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Illuminate\Contracts\Mail\Mailer as MailerContract;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailer as BaseMailer;

class Mailer extends BaseMailer implements MailerContract
{
    /**
     * Create a new message instance.
     *
     * @return \Symfony\Component\Mime\Message
     */
    protected function createMessage()
    {
        $message = new Email();
        $this->addContent($message);

        return $message;
    }

    /**
     * Create a new attachment.
     *
     * @param  string|\Symfony\Component\Mime\Part\PartInterface  $file
     * @param  array  $options
     * @return \Symfony\Component\Mime\Attachment
     */
    public function createAttachment($file, array $options = [])
    {
        if ($file instanceof PartInterface) {
            return new InlinePart($file->body(), $file->getHeaders());
        }

        $attachment = Attachment::fromPath($file);

        if (isset($options['filename'])) {
            $attachment->filename($options['filename']);
        }

        if (isset($options['mime'])) {
            $attachment->contentType($options['mime']);
        }

        if (isset($options['disposition'])) {
            $attachment->disposition($options['disposition']);
        }

        return $attachment;
    }
}

Change settings in config/mail.php like below to use custom mailer class.

'mailer' => env('MAIL_MAILER', 'smtp'),
'smtp' => [
    'transport' => 'smtp',
    'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
    'port' => env('MAIL_PORT', 587),
    'encryption' => env('MAIL_ENCRYPTION', 'tls'),
    'username' => env('MAIL_USERNAME'),
    'password' => env('MAIL_PASSWORD'),
    'timeout' => null,
    'auth_mode' => null,
],
'pretend' => false,
Balaji Kandasamy
  • 4,446
  • 10
  • 40
  • 58