<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed Mansoor</title>
    <description>The latest articles on DEV Community by Ahmed Mansoor (@ahmedmansoor).</description>
    <link>https://dev.to/ahmedmansoor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F408644%2F8abdf972-d710-46c7-ae47-dde02f60e97b.jpg</url>
      <title>DEV Community: Ahmed Mansoor</title>
      <link>https://dev.to/ahmedmansoor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmedmansoor"/>
    <language>en</language>
    <item>
      <title>Sending Mail in Laravel and securing it with Google reCAPTCHA</title>
      <dc:creator>Ahmed Mansoor</dc:creator>
      <pubDate>Thu, 09 Feb 2023 09:46:39 +0000</pubDate>
      <link>https://dev.to/ahmedmansoor/sending-mail-in-laravel-and-securing-it-with-google-recaptcha-471k</link>
      <guid>https://dev.to/ahmedmansoor/sending-mail-in-laravel-and-securing-it-with-google-recaptcha-471k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0igml8mev7ub4bb6tww7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0igml8mev7ub4bb6tww7.jpg" alt="contact form" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I spent some time digging up the internet on how to send mail in Laravel and integrate reCaptcha to secure. Although the &lt;a href="https://laravel.com/docs/9.x/mail#main-content" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; is pretty straightforward, I wanted some samples and a step-by-step guide. So, here I’ll show you how to integrate reCAPTCHA into your Laravel application to enhance the security of your mail forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
I’m using Laravel 9 and will be programmatically invoking the challenge when using reCAPTCHA v3. You may automatically bind the challenge to a button.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generating necessary files: the Model, Migration, Controller, and Markdown Mailable&lt;/li&gt;
&lt;li&gt;Mail setup&lt;/li&gt;
&lt;li&gt;reCAPTCHA setup&lt;/li&gt;
&lt;li&gt;Form view file&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  1. Generating necessary files: the Model, Migration, Controller, and Markdown Mailable
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:model ContactMail -mrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:mail ContactMail --markdown=emails.contact-mail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Mail setup
&lt;/h2&gt;

&lt;p&gt;Add the mail host, port, address .etc to the .env file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIL_MAILER=log
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=
MAIL_FROM_ADDRESS="email@email.com"
MAIL_FROM_NAME="${APP_NAME}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ContactMail.php&lt;/strong&gt;&lt;br&gt;
Update the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   public $data;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this-&amp;gt;data = $data;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;contact-mail.blade&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;x-mail::message&amp;gt;
email: {{ $data-&amp;gt;email }}
**{{ $data-&amp;gt;subject }}**&amp;lt;br&amp;gt;
{{ $data-&amp;gt;message }} &amp;lt;br&amp;gt;
&amp;lt;/x-mail::message&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;web.php (route)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::name('contact.')
    -&amp;gt;prefix('contact/')
    -&amp;gt;group(function () {
        Route::get('', 'ContactMailController@index')-&amp;gt;name('index');
        Route::post('store', 'ContactMailController@store')-&amp;gt;name('store');
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. reCAPTCHA setup
&lt;/h2&gt;

&lt;p&gt;Register your reCAPTCHA v3 keys on the &lt;a href="https://www.google.com/recaptcha/admin/create" rel="noopener noreferrer"&gt;reCAPTCHA Admin console&lt;/a&gt; here. Add it to your .env file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RECAPTCHA_SITE_KEY=&amp;lt;paste key here&amp;gt;
RECAPTCHA_SECRET_KEY=&amp;lt;paste key here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ContactMailController.php&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('pages.contact.index');
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // form validation
        $data = $request-&amp;gt;all();
        $rules = [
            'email' =&amp;gt; 'nullable|email',
            'subject' =&amp;gt; 'required',
            'message' =&amp;gt; 'required',
        ];

        $validator = Validator::make($data, $rules);

        // if form validation fails
        if ($validator-&amp;gt;fails()) {
            return Response::json(array(
                'validation' =&amp;gt; false,
                'message' =&amp;gt; $validator-&amp;gt;getMessageBag()-&amp;gt;toArray()

            ), 200); // 400 invalid requests
        }

        // verify and get validation
        $response = Http::asForm()-&amp;gt;post('https://www.google.com/recaptcha/api/siteverify', [
            'secret' =&amp;gt; env('RECAPTCHA_SECRET_KEY'),
            'response' =&amp;gt; $request-&amp;gt;recaptchaToken,
        ]);

        $recaptchaResponse = $response-&amp;gt;json();

        // if captcha valid
        if ($recaptchaResponse['success'] == true) {
            ContactMail::create($request-&amp;gt;all());

            $message = [
                'success' =&amp;gt; true,
                'message' =&amp;gt; 'Thank you for taking the time to report your concerns.',
            ];
            return response()-&amp;gt;json($message, 200);
        }
        // if captcha invalid
        elseif ($recaptchaResponse['success'] == false) {
            $message = [
                'success' =&amp;gt; false,
                'message' =&amp;gt; 'You a robot?',
            ];
            return response()-&amp;gt;json($message, 200);
        } else {
            $recaptchaFail = 'Something went wrong.';
            return response()-&amp;gt;json($recaptchaFail, 200);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You got to import the necessary facades.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Form view file
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;contact.blade&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form id="contactForm" method="POST" action="{{ route('contact.store') }}" class="flex flex-col space-y-4"&amp;gt;
      {{ csrf_field() }}
      &amp;lt;div class="row"&amp;gt;
          &amp;lt;div class="col-md-6 flex flex-col space-y-5"&amp;gt;
              &amp;lt;div class="flex flex-row w-full space-x-3 justify-between"&amp;gt;
                  &amp;lt;!-- from Email --&amp;gt;
                  &amp;lt;div class="w-full col-md-6"&amp;gt;
                      &amp;lt;div class="form-group flex flex-col space-y-2"&amp;gt;
                          &amp;lt;label&amp;gt;From &amp;lt;small class="p-0.5 px-1 rounded-md bg-gray-100 text-gray-500"&amp;gt;optional&amp;lt;/small&amp;gt;&amp;lt;/label&amp;gt;
                          &amp;lt;input id="email" type="email" name="email" placeholder="Your email address" value{{old('email')}}"
                          class="hover:shadow bg-gray-50 border
                      border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary
                      focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
                      dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary
                      dark:focus:border-primary dark:shadow-sm-light"&amp;gt;
                      &amp;lt;/div&amp;gt;
                  &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class="col-md-6 flex flex-col space-y-5"&amp;gt;
          &amp;lt;!-- subject --&amp;gt;
          &amp;lt;div class="form-group space-y-2"&amp;gt;
              &amp;lt;label for="subject"&amp;gt;Subject &amp;lt;small class="p-0.5 px-1 rounded-md bg-sky-100 text-sky-500"&amp;gt;required&amp;lt;/small&amp;gt;&amp;lt;/label&amp;gt;
              &amp;lt;input type="text" id="subject" name="subject" value="{{ old('subject') }}"
              class="hover:shadow bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary
              focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
              dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary
              dark:focus:border-primary dark:shadow-sm-light"&amp;gt;
          &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class="row"&amp;gt;
          &amp;lt;div class="col-md-12"&amp;gt;
              &amp;lt;div class="form-group flex flex-col space-y-2"&amp;gt;
                  &amp;lt;label&amp;gt;Message &amp;lt;small class="p-0.5 px-1 rounded-md bg-sky-100 text-sky-500"&amp;gt;required&amp;lt;/small&amp;gt;&amp;lt;/label&amp;gt;
                  &amp;lt;textarea id="message" name="message" rows="5" required class="hover:shadow bg-gray-50 border
                  border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary
                  focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
                  dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary
                  dark:focus:border-primary dark:shadow-sm-light"&amp;gt;{{ old('message') }}&amp;lt;/textarea&amp;gt;
              &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div id="success-message"&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div class="form-group"&amp;gt;
          &amp;lt;button id="submit-button"
              data-sitekey="{{env('RECAPTCHA_SITE_KEY')}}"
              data-callback='onSubmit'
              data-action='submit'
              class="g-recaptcha btn-primary"&amp;gt;
              &amp;lt;span id="submit-text"&amp;gt;Report&amp;lt;/span&amp;gt;
          &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
  &amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;
    function onSubmit(token) {
        var bodyFormData = {
            'email' : $('#email').val(),
            'subject' : $('#subject').val(),
            'message' : $('#message').val(),
            'recaptchaToken': token,
        };
        axios({
                method: "post",
                url: "{{route('contact.store')}}",
                data: bodyFormData,
            })
        .then(function (response) {
            // if form validation fails
            if (response.data.validation === false) {
                let messages = response.data.message;
                for (let key in messages) {
                    if (messages.hasOwnProperty(key)) {
                    let errorMessage = messages[key][0];
                    let formField = document.getElementById(key);
                    formField.classList.add('border-gray-300');

                    let errorElement = document.createElement('div');
                    errorElement.classList.add('text-sm','text-orange-500');
                    errorElement.innerHTML = errorMessage;

                    formField.parentNode.appendChild(errorElement);
                    }
                }
                }
            // if ok
            else if(response.data.success == true) {
                var message = response.data.message;
                var successMessage = "&amp;lt;div class='bg-primary bg-opacity-10 text-primary p-4 text-center rounded-lg'&amp;gt;" + message + "&amp;lt;/div&amp;gt;";
                $("#success-message").html(successMessage);
                setTimeout(function() {
                    $('#success-message').delay(5000).fadeOut(1000);
                }, 5000);
            }
            // if form validation fails
            else if(response.data.success == false) {
                var message = response.data.message;
                var successMessage = "&amp;lt;div class='bg-orange-500 bg-opacity-10 text-orange-500 p-4 text-center rounded-lg'&amp;gt;" + message + "&amp;lt;/div&amp;gt;";
                $("#success-message").html(successMessage);
                setTimeout(function() {
                    $('#success-message').delay(5000).fadeOut(1000);
                }, 5000);
            }
        })
         // if any other error
        .catch(function (error) {
            var message = 'Something went wrong.';
            var successMessage = "&amp;lt;div class='bg-orange-500 bg-opacity-10 text-orange-500 p-4 text-center rounded-lg'&amp;gt;" + message + "&amp;lt;/div&amp;gt;";
            $("#success-message").html(successMessage);
            setTimeout(function() {
                $('#success-message').delay(5000).fadeOut(1000);
            }, 5000);
        });
    }

&amp;lt;/script&amp;gt;
&amp;lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Integrating Google reCAPTCHA into your Laravel mail forms is an effective solution for enhancing the security of your web application. This guide provides a step-by-step approach for adding reCAPTCHA, making it easy for developers of all skill levels to send secure emails.&lt;/p&gt;

</description>
      <category>security</category>
      <category>authentication</category>
      <category>privacy</category>
      <category>howto</category>
    </item>
  </channel>
</rss>
