Laravel 5.3 - Attach Multiple Files To Mailables
Asked Answered
E

3

16

How does one go about attaching multiple files to laravel 5.3 mailable?

I can attach a single file easily enough using ->attach($form->filePath) on my mailable build method. However, soon as I change the form field to array I get the following error:

basename() expects parameter 1 to be string, array given

I've searched the docs and also various search terms here on stack to no avail. Any help would be greatly appreciated.

Build Method:

public function build()
{
    return $this->subject('Employment Application')
                ->attach($this->employment['portfolio_samples'])
                ->view('emails.employment_mailview');
}

Mail Call From Controller:

Mail::to(config('mail.from.address'))->send(new Employment($employment));
Eury answered 17/3, 2017 at 2:49 Comment(0)
S
42

You should store your generated email as a variable, then you can just add multiple attachments like this:

public function build()
{
    $email = $this->view('emails.employment_mailview')->subject('Employment Application');
    
    // $attachments is an array with file paths of attachments
    foreach ($attachments as $filePath) {
        $email->attach($filePath);
    }

    return $email;
}

In this case your $attachments variable should be an array with paths to files:

$attachments = [
    // first attachment
    '/path/to/file1',

    // second attachment
    '/path/to/file2',
    ...
];

Also you can attach files not only by file paths, but with MIME type and desired filename, see documentation about second case of use for the `attachment` method: https://laravel.com/docs/master/mail#attachments

For example, your $attachments array can be something like this:

$attachments = [
    // first attachment
    'path/to/file1' => [
        'as' => 'file1.pdf',
        'mime' => 'application/pdf',
    ],
    
    // second attachment
    'path/to/file12' => [
        'as' => 'file2.pdf',
        'mime' => 'application/pdf',
    ],
    
    ...
];

After you can attach files from this array:

// $attachments is an array with file paths of attachments
foreach ($attachments as $filePath => $fileParameters) {
    $email->attach($filePath, $fileParameters);
}
Syneresis answered 17/3, 2017 at 4:58 Comment(7)
This solution works perfectly in L5.8, but make sure to use a different name instead of $attachments as the internal Mailable class already has a property with the name $attachments. Using the same name overwrites the property and causes errors.Timeless
@Sven, thanks for your comment. However, you're wrong about the name of this example variable. Even if some class has an $attachments property, we still can create a variable with the same name $attachments because non-static properties can via the pseudo-variable $this, so our variable doesn't interfere with the properties of this hypothetical class. Static properties of any class can be accessed using static keyword, so again — our variable doesn't cause any troubles there.Syneresis
@AlexanderReznikov I'm not sure what's the issue then but there might be side effects: https://mcmap.net/q/747853/-laravel-illegal-string-offset-39-file-39-on-line-342-file-illuminate-mail-mailable-php/1815847 (source)Timeless
In case you mentioned user @Matt E. tries to create an own class property $attachments and it overwrites a Laravel $attachment class property. You can you variables with the "same" names without any worries, see an example: sandbox.onlinephpfunctions.com/code/…Syneresis
@AlexanderReznikov You're right. It's only an issue with $this->attachments. Thank you for your patience.Timeless
Sure, no problem.Syneresis
There's no need to store it in the email variable since you're working with an object. In the end you can just return $this.Operand
P
0

Best solution work for me

$email = $this->from($from)->subject("Employment Application")
    ->view('emails.employment_mailview');

foreach ($files as $file) {
    $path = '/path/to/'.$file->file;
    $attachments->push($path);
}

$attachments = collect([]);

foreach ($attachments as $filePath) {
    $email->attach($filePath);
}

return $email;
Peroration answered 30/9, 2021 at 14:30 Comment(0)
J
0

This worked for me, maybe it will work for more people. As I am getting the files via $request this was the solution works for me.

obs: sorry I'm using translate. From Portuguese(Brazil) to English.

thanks @AlexanderReznikov, it helped me a lot.

class SendMailextends Mailable
   {

      protected $inputs;
      protected $files;

    public function __construct(array $inputs, array $files)
    {
            $this->inputs = $inputs;
            $this->files = $files;

    }

public function build()
{

if (isset($this->files)){
 $email =  $this->from('you@mail')->view('email.email-contact')->subject('Email teste mulptiple files');

        for ($indice = 0; $indice < count($this->files['files']); $indice++) {

                $files = $this->files[$indice];

                $pathName = $files->getPathname();

                $attachments = $pathName;

                $fileName = $files->getClientOriginalName();

                $email->attach($attachments,['as' => "$fileName"]);

            }

        return $email;

    }else{
        // file empty, send email
        return $this->from('you@mail','name')->subject('Email teste mulptiple files')
            ->view('email.email-contact');
    }
}
}
Javierjavler answered 15/12, 2022 at 21:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.