TALL Tales

How to Create a Contact Form and Send from Mailgun on Forge

04 Oct, 2022

For this tutorial you will need to have an account at Mailgun and your site running at Forge.

The example is this site, a Laravel 8 application with Breeze.  I am adding the Contact Form that you can now see on the menu.

Application

Add Guzzle

The Mailgun API requires Guzzle. Add this by running this command in your CLI:

composer require guzzlehttp/guzzle

Add the Contact Form

The first thing you need to do is add in your Contact Form. Create a new blade fill resources\views\contact.blade.php. Using whatever layout you have elsewhere add in a contact form as follows:

<form action="/contact" method="POST">
    @csrf
    <div>
        <label for="name">Name</label>
        <input id="name" name="name" type="text"  />
    </div>
    <div>
        <label for="email">Email</label>
        <input id="email" name="email" type="email">
    </div>
    <div>
        <label for="message">Message</label>
        <textarea id="message" name="message" rows="4"></textarea>
    </div>
    <div>
        <button type="submit">
        Submit
        </button>
    </div>
</form>

Add the Route

In the routes\web.php file, add a new line to display the Contact page:

Route::get('/contact', 'PageController@contact')->name('pages.contact');

Add the Controller

In the PageController which I already had for my static pages I add in the function for serving the Contact page:

public function contact()
  {
      return view('contact');
  }

Add the Mailable

Next we need to add the Mailable by running this command in your CLI:

php artisan make:mail ContactMail

You can learn about Mailables in the Laravel docs.

This will add ContactMail.php in app\Mail\.

In this new file, alter it so it looks like this:

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Http\Request;

class ContactMail extends Mailable
{
    use Queueable, SerializesModels;

    public $email;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(Request $request)
    {
        $this->email = $request;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        
        $name = $this->email->name;
        $email = $this->email->email;
        $message = $this->email->message;
        
        return $this->subject('New Contact Mail')
                    ->from($email)
                    ->to('sarah@example.com')
                    ->view('emails.contactmail', [$name, $email, $message]);
    }
}

Don't forget to change the email to be yours!

Add Email Content

I created a new folder in resources\views\ called emails which I will use for email sending. In here I created a new blade file called contactemail.blade.php.

In this file is the content for the email:

<h1>You have a new message from TallTales:</h1>

<h2>Name: </h2>
<p>
{{ $email->name }}
</p>

<h2>Email: </h2>
<p>
{{ $email->email }}
</p>

<h2>Message:</h2>
<p>
{{ $email->message }}
</p>

Add Route

Now we have the Mailable set up we can add in the Route for sending the email. In routes\web.php add:

Route::post('/contact', function(Request $request){
  Mail::send(new ContactMail($request));
    return redirect('/contact')->with('status', 'Message Sent!');
  });

at the top you will also need to add:

use Illuminate\Http\Request;
use App\Mail\ContactMail;

Alter the Config

We need to add in the Mailgun settings, so first change the values in the config files.

In config\mail.php:

 'default' => env('MAIL_MAILER', 'mailgun'),

In config\services.php:

  'mailgun' => [
        'domain' => env('MAILGUN_DOMAIN'),
	    'secret' => env('MAILGUN_SECRET'),
    ],

Alter the .env

In the .env file we will need to add in the Mailgun settings. This can be a bit tricky because Mailgun has different names for the settings.

The code we need to change is the Mail settings and we need to end up with something like this:

MAIL_MAILER=mailgun
MAIL_PORT=2525
MAIL_FROM_ADDRESS=enteryouremailaddresshere
MAIL_FROM_NAME="${APP_NAME}"
MAILGUN_DOMAIN=*enterdomainhere
MAILGUN_SECRET=*enterkeyhere
MAIL_ENCRYPTION=null

So for MAILGUN_DOMAIN you will need the domain name you are using in your Mailgun account or if you are just using the Sandbox add in that e.g. sandbox123fefefefefefefefefefef.mailgun.org

You will be able to see this in the sending tab once you have gone through their tutorial for sending emails. Authorised recipients are also on this page.

Remember: unless you are using a Paid account you can only send to verified addresses so for testing make sure you add in the email address that you want to send to.

The MAILGUN_SECRET is also available from the Sending page. Click on the Select button in the API box and choose PHP. You will then see the API Key. This is the value you want.

That's it for your application. Test that it works locally and if so you can commit it to Git.

Server

Alter the Environment

Your .env file will not be pushed to GitHub so in Forge you will need to add in those Mail variables to your environment file. You can find this by going to your Site and then Environment. Add then in and Save.

Deploy

If you are using a Github->Forge setup then push your local repository to Github. If it is set up Forge will have then automatically deploy it and you should have the form working on your site. Test it to see!