Rigor5353's avatar

Contact Form is not working htmlspecialchars(): Argument #1 ($string) must be of type string

Hi folks

My first time trying to use Laravel for a contact form and I'm bumping into a problem I just can't wrap my head around. This is a Laravel 10 installation.

I am following a tutorial (I can't link it, I'm too new on this forum) and adapted it to my needs, but it doesn't seem to work.

Whenever I use my contact form, I get this error from Symfony

htmlspecialchars(): Argument #1 ($string) must be of type string, Illuminate\Mail\Message given (View: /home/mysite.com/domains/mysite.com/site/resources/views/utility/contactFormEmail.blade.php)

Below is the relevant code:

app/Mail/MailableContactForm.php

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class MailableContactForm extends Mailable
{
    use Queueable, SerializesModels;

    public $firstname, $lastname, $email, $subject, $message;

    /**
     * Create a new message instance.
     */
    public function __construct($firstname, $lastname, $email, $subject, $message)
    {
        $this->firstname = $firstname;
        $this->lastname = $lastname;
        $this->email = $email;
        $this->subject = $subject;
        $this->message = $message;
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Website Contact Form',
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            view: 'utility.contactFormEmail',
            with: ['firstname' => $this->firstname,
                    'lastname' => $this->lastname,
                    'email' => $this->email,
                    'subject' => $this->subject,
                    'message' => $this->message,],
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [];
    }
}

app/Http/Controllers/Controller.php

public function contactPost(Request $request)
    {
        $firstname = $request->firstname;
        $lastname = $request->lastname;
        $email = $request->email;
        $subject = $request->subject;
        $message = $request->message;
        $recipient = '[email protected]';
        Mail::to($recipient)->send(new MailableContactForm($firstname, $lastname, $email, $subject, $message));
        return "Mail Send Successfully";
    }

routes/web.php

Route::get('/contact', [App\Http\Controllers\Controller::class, 'contact'])->name('contact');
Route::post('/contact', [App\Http\Controllers\Controller::class, 'ContactPost'])->name('contactPost');

resources/views/utility/contactFormEmail.blade.php

@component('mail::message')
<p>New website inquiry</p>
<p>Firstname: {{ $firstname }}</p>
<p>Lastname: {{ $lastname }}</p>
<p>Email: {{ $email }}</p>
<p>Subject: {{ $subject }}</p>
<br>
<p>Message: {{ $message }}</p>
@endcomponent

and this is the form on contact.blade.php

<form class="contact-form" method="POST" action="{{ route('contactPost') }}" enctype="multipart/form-data">
   @csrf
   <div class="row gy-3">
      <div class="col-lg-6">
         <label for="firstname" class="form-label">{{ __('localecontact.firstname') }}</label>
         <input name="firstname" type="text" class="form-control" id="firstname" required>
      </div>
      <div class="col-lg-6">
         <label for="lastname" class="form-label">{{ __('localecontact.lastname') }}</label>
         <input name="lastname" type="text" class="form-control" id="lastname" required>
      </div>
      <div class="col-lg-6">
         <label for="email" class="form-label">{{ __('localecontact.email') }}</label>
         <input name="email" type="email" class="form-control" id="email" required>
      </div>
      <div class="col-lg-6">
         <label for="subject" class="form-label">{{ __('localecontact.subject') }}</label>
         <input name="subject" type="text" class="form-control" id="subject" required>
      </div>
   </div>
   <div class="mb-3">
   </div>
   <div class="text-area col-12 mb-3">
      <label for="message" class="form-label">{{ __('localecontact.message') }}</label>
      <textarea name="message" class="form-control" id="message" rows="3"></textarea>
   </div>
   <button class="custom-btn2" type="submit">{{ __('localecontact.submit') }}</button>
</form>

.env

APP_NAME='My Amazing Cool Working Contact Form'

MAIL_MAILER=smtp
MAIL_HOST=myserver.com
MAIL_PORT=587
MAIL_USERNAME='[email protected]'
MAIL_PASSWORD=passwordcool
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS='[email protected]'
MAIL_FROM_NAME='${APP_NAME}'

I do not understand why it's complaining about the argument not being a string, I am literally passing strings. I even checked with dd(gettype($firstname)) before the Mail:: function in the Controller

Any hints are greatly appreciated. I simply cannot figure out what's not working here.

Thank you so much already!

0 likes
4 replies
Snapey's avatar
Snapey
Best Answer
Level 122

try a variable name other than message. Plus you don't need to pass the variables into the view. All public properties of the mailable are automatically available to the view

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class MailableContactForm extends Mailable
{
    use Queueable, SerializesModels;

    public $firstname, $lastname, $email, $subject, $contactMessage;

    /**
     * Create a new message instance.
     */
    public function __construct($firstname, $lastname, $email, $subject, $contactMessage)
    {
        $this->firstname = $firstname;
        $this->lastname = $lastname;
        $this->email = $email;
        $this->subject = $subject;
        $this->contactMessage = $contactMessage;
    }

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Website Contact Form',
        );
    }

    public function content(): Content
    {
        return new Content('utility.contactFormEmail');
    }
}

view;

@component('mail::message')
<p>New website inquiry</p>
<p>Firstname: {{ $firstname }}</p>
<p>Lastname: {{ $lastname }}</p>
<p>Email: {{ $email }}</p>
<p>Subject: {{ $subject }}</p>
<br>
<p>Message: {{ $contactMessage }}</p>
@endcomponent

You don't need to change anything in the controller or contact form

2 likes
Rigor5353's avatar

@Snapey Seems like that did a thing! Now I'm getting this error by Symfony:

No hint path defined for [mail]. (View: /home/dancedvisionbe/domains/dance-d-vision.be/site/resources/views/utility/contactFormEmail.blade.php)

I changed all instances of just "message" to contactMessage, also in the controller this is now the code:

public function contactPost(Request $request)
    {
        $firstname = $request->firstname;
        $lastname = $request->lastname;
        $email = $request->email;
        $subject = $request->subject;
        $contactMessage = $request->contactMessage;
        $recipient = '[email protected]';
        Mail::to($recipient)->send(new MailableContactForm($firstname, $lastname, $email, $subject, $contactMessage));
    }

also in the form it's now contactMessage everywhere instead of just message

Rigor5353's avatar

Edit: I changed this in the app/Mail/MailableContactForm.php

It's now using markdown: instead of view:

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            markdown: 'utility.contactFormEmail',
        );
    }

Looks like it's now doing at least something but my server is acting up, I'm now getting 504 Gateway Timeout error

Rigor5353's avatar

Working perfectly now! The 504 error was because of the SMTP server I was using. Thank you so much @snapey

Please or to participate in this conversation.