Method Swift_Message::__toString() must not throw an exception

Silverstripe 4.1.0

Method Swift_Message::__toString() must not throw an exception

I get this error message:

Method Swift_Message::__toString() must not throw an exception, caught Swift_IoException: Unable to open file for reading [/assets/foo/a84ca8c15f/foo.pdf]

when i attach an file to an email.
This is the code that generates the email

private function sendMailToCustomer()
    {
        $session = $this->getSession();
        $session = $session->get('TempSessionOrder');
        $customerEmail = $session->InvoiceEmailAddress;
        $email = new EmailCustomerProofshop();
        $email->setTo("$customerEmail");
        $email->setSubject('Ihre Foo-Bestellung bei Foo - ' . $session->Bestellnummer);
        $email->setData(['Order' => $session]);
        $email->addAttachment(File::get()->filter(['name' => $session->ID . '.pdf'])->first()->getURL());
        $email->send();
    }

I wrote an file extension to set permissions:


class FileExtension extends DataExtension
{
    public function canCreate($member = null, $context = [])
    {
        return true;
    }

    public function canPublish($member = null)
    {
        return true;
    }

    public function canView($member = null)
    {
        return true;
    }

    public function canEdit($member = null)
    {
        return true;
    }

}

The file that i want to attach does exist.

Do you need to add the full path to the file? That looks like a relative path.

Adding Director::baseFolder() to the start might be the key.

ie. Director::baseFolder() . DIRECTORY_SEPARATOR . File::get()->filter(['name' => $session->ID . '.pdf'])->first()->getURL();

I’ll give it a try. I used getAbsoluteURL() to get an absolute path but it did not help.

If you are looking to add a File dataobject as an attachment I highly recommend to assign as-data or as-stream rather than trying to unwrap the URL (and in turn prevent unwanted HTTP requests produced internally).

Try

$email->addAttachmentFromData($file->getString(), $file->Name, $file->getMimeType())

If you’re dealing with large files, you may be able to use getStream() instead.

Thanks! This looks like a way better solution to me. But both solutions work just in case…

AbsoluteURL() does what the name suggests and returns a URL as opposed to a path on the filesystem.
Hopefully the baseFolder() will do what you need!

That did the trick. Thank you very much! @DorsetDigital

1 Like