Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

RileyGWeb's avatar

Email attachments (FileUpload) throwing Cannot access offset of type string on string

I have the following simple email form in Filament:

public static function form(Form $form): Form
{
    return $form
        ->schema([
            TextInput::make('subject')
                ->required()
                ->label('Email Subject'),
            RichEditor::make('body')
                ->required()
                ->label('Email Body'),
            FileUpload::make('attachments')
                ->multiple()
                ->label('Attachments')
                ->disk('public')
        ])
        ->statePath('data');
}
public function submit()
{
    $subjectLine = $this->form->getState()['subject'];
    $emailBody = $this->form->getState()['body'];
    $attachments = $this->form->getState()['attachments'];

    $emailAddresses = $this->records['emails'];
    
    foreach ($emailAddresses as $emailAddress) {
        Mail::to($emailAddress)->send(new BulkEventEmail($subjectLine, $emailBody, $attachments));
    }
}

It works just fine if I only send a subject line and body. If I add any attachments however, it gives me: Cannot access offset of type string on string

I am not doing that anywhere in my code, so I also logged it like:

Log::info('Attachments:', ['attachments' => $attachments])

Here is the results of that:

[2024-09-21 01:10:23] production.INFO: Attachments: {["UaJx4a4GXjJdbU03KMFztS5EHyqQat-metacm91dGVzX291dHB1dC5jc3Y=-.csv"]} 

Not super helpful, so I spaced out my attachments function to see which line is highlighted in the error message:

Mail::to(
    $emailAddress
    )->send( // this one
        new BulkEventEmail(
            $subjectLine, 
            $emailBody, 
            $attachments
        )
    );

Also not the most helpful, so I sleuthed through vendor frames, and found this suspicious looking one in Mail/Mailable:

protected function buildAttachments($message)
{
    foreach ($this->attachments as $attachment) {
        $message->attach($attachment['file'], $attachment['options']); // this line is highlighted by the error message
    }

    foreach ($this->rawAttachments as $attachment) {
        $message->attachData(
            $attachment['data'], $attachment['name'], $attachment['options']
        );
    }

    $this->buildDiskAttachments($message);

    return $this;
}

This would indicate that the files need to be structured in an array like that with keys file and options but when I do, the file path string is still added at the root of the nested array which throws the same error.

At this point I'm at a bit of a loss. Any ideas how to do this properly?

0 likes
1 reply
LaryAI's avatar
Level 58

The issue you're encountering is due to the way the attachments are being passed to the BulkEventEmail mailable. The buildAttachments method in the Mailable class expects each attachment to be an array with file and options keys, but your attachments are being passed as a simple array of file paths.

To resolve this, you need to structure your attachments correctly before passing them to the mailable. Here's how you can modify your submit method to achieve this:

  1. Ensure each attachment is an array with the required keys.
  2. Pass the structured attachments to the BulkEventEmail mailable.

Here's the updated code:

public function submit()
{
    $subjectLine = $this->form->getState()['subject'];
    $emailBody = $this->form->getState()['body'];
    $attachments = $this->form->getState()['attachments'];

    // Structure the attachments correctly
    $structuredAttachments = array_map(function ($attachment) {
        return [
            'file' => $attachment,
            'options' => [],
        ];
    }, $attachments);

    $emailAddresses = $this->records['emails'];
    
    foreach ($emailAddresses as $emailAddress) {
        Mail::to($emailAddress)->send(new BulkEventEmail($subjectLine, $emailBody, $structuredAttachments));
    }
}

In your BulkEventEmail mailable, you should handle the attachments accordingly. Here's an example of how you might do that:

class BulkEventEmail extends Mailable
{
    public $subjectLine;
    public $emailBody;
    public $attachments;

    public function __construct($subjectLine, $emailBody, $attachments)
    {
        $this->subjectLine = $subjectLine;
        $this->emailBody = $emailBody;
        $this->attachments = $attachments;
    }

    public function build()
    {
        $email = $this->view('emails.bulk_event')
                      ->subject($this->subjectLine)
                      ->with([
                          'body' => $this->emailBody,
                      ]);

        // Attach the files
        foreach ($this->attachments as $attachment) {
            $email->attach($attachment['file'], $attachment['options']);
        }

        return $email;
    }
}

This should ensure that your attachments are correctly structured and passed to the mailable, avoiding the "Cannot access offset of type string on string" error.

Please or to participate in this conversation.