B4J Tutorial [BANano] Sending Contact Us Form contents to an email with inline PHP

Discussion in 'B4J Tutorials' started by Mashiane, May 20, 2019.

  1. Mashiane

    Mashiane Expert Licensed User

    Ola

    For this exercise, you need the skeleton & sweet alert banano libraries. You will need to compile them (run + compile as library) using the latest version of BANano.

    Why a PHP based Contact Us form? Well, I wanted to send the contact us details to my SMTP based email using inline PHP.

    Note: BANano has a .SendEmail method built in it to send emails that uses smtpjs

    1. Using inline PHP, the example code below sends an email to your ISP configured email configuration. This has been tested with XAMP and also my own ISP.

    ContactForm.gif
     
    José J. Aguilar and joulongleu like this.
  2. Mashiane

    Mashiane Expert Licensed User

    Building the inline PHP script to send the email.

    To be able to make this work via inline php, one needs to ensure that the PHP configuration is working properly.

    Once BANano is initialized, where shortname is defined as ContactForm i.e. the name of my SPA.

    Code:
    BANano.PHP_NAME = "email.php"
        BANano.PHPHost = 
    "http://localhost/" & ShortName & "/"
        BANano.PHPAddHeader(
    "Access-Control-Allow-Origin: *")
    Then on the main module, I add the php script to send the email..

    Code:
    #if PHP
    function SendEmail($from,$to,$cc,$subject,$msg) {
        $msg = str_replace("\n.", "\n..", $msg);
        // use wordwrap() if lines are longer than 70 characters
        $msg = wordwrap($msg,70,"\r\n");
        //define from header
        $headers = "From:" . $from . "\r\n";
        $headers .= "Cc: " . $cc . "\r\n";
        $headers .= "X-Mailer:PHP/" . phpversion();
        // send email
        $response = (mail($to,$subject,$msg,$headers)) ? "success" : "failure";
        $output = json_encode(array("response" => $response));
        header('content-type: application/json; charset=utf-8');
        echo($output);
    }
    #End If
    As noted in this code, this php sub expects a from email address, a to email address, cc email address, the subject and the message. In the next thread we will create our contact us form, read the contents of the form and then pass then to SendEmail

    Note: The attached project is just a skeleton example, you need to copy the skeleton css and fontawesome files to the files tab to run it.

    Related Article:
    https://www.b4x.com/android/forum/threads/banano-inline-php-server-code.101224/#content
     

    Attached Files:

    Last edited: May 20, 2019
    joulongleu likes this.
  3. Mashiane

    Mashiane Expert Licensed User

    Building the contact us form

    I referenced both the sweetalert and skeleton banano libraries and created the attached form using the abstract designer.

    1. Add a container SKContainer, enlarge the container size
    2. Add a row SKRow, drag it inside the container, name it R1
    3. Add a column, SKColumn, name it R1C1, drag it inside R1 and resize appropriately
    4. Add a label, SKLabel, change size to H2 and change text to Contact Us
    5. Add text boxes, txtFullName, txtEmail, txtTelephone, a text area, txtMessage, a check box chkRobot and a button.
    6. Each time you add a component, drag and place it inside R1C1 in the sequence of appearance.
    7. Save view, generate members.

    ContactForm.png

    Now, when the button send is clicked, the details entered should be checked and if everything is complete, the PHP script should execute. For this we use CallInlinePHP

    Here everything is required. A sub called Required has been created to get each element text value and check if its blank. If there is something blank, required will be true. Next the checkbox I am not a robot should be checked.

    Code:
    Sub btnSend_Click (event As BANanoEvent)

        
    Dim bRequired As Boolean = Required(Array("txtfullname","txtemail","txttelephone","txtmessage"))
        
    If bRequired Then
            Dialog.Initialize(Me, 
    "RequiredFields""RequiredFields")
            Dialog.Title = 
    "Contact Us"
            Dialog.Content = 
    "All the fields are required!"
            Dialog.ShowCancelButton = 
    False
            Dialog.Show
            
    Return 
        
    End If
      
        
    Dim robot As Boolean = chkRobot.checked
        
    If robot = False Then
            Dialog.Initialize(Me, 
    "RequiredFields""RequiredFields")
            Dialog.Title = 
    "Contact Us"
            Dialog.Content = 
    "You need to confirm that you are not a robot!"
            Dialog.ShowCancelButton = 
    False
            Dialog.Show
            
    Return
        
    End If
        
    'use php to send the email
        Dim sname As String = txtFullName.text
        
    Dim semail As String = txtEmail.text
        
    Dim sphone As String = txtTelephone.text
        
    Dim smsg As String = txtMessage.text
        
    Dim nmsg As String = $"Full Name: ${sname}\r\nEmail Address: ${semail}\r\nTelephone: ${sphone}\r\nMessage:\r\n${smsg}"$
        
    Dim se As Map = CreateMap("from":"<fromemail>", _
            
    "to":"<toemail>", _
            
    "cc":"<ccemail>", _
            
    "subject":"Contact Us:" & sname, _
            
    "msg":nmsg)
        BANano.CallInlinePHP(
    "SendEmail", se, "contactus")
    End Sub
    In the instances that our validation is broken, we want a sweet alert to show up. As we are not sending HTML content, we needed to have break-lines in each msg item specified. For that we used \r\n.

    Come on, change the <fromemail>, <toemail> and <ccemail> to be the emails that you want to send the contact details to.

    The next step is trapping the result of the Inline PHP call.

    EmailSent.gif

    Code:
    Sub BANano_CallInlinePHPResult(Success As Boolean, UniqueID As String, Result As String)
        
    If Success Then
            
    Dim resm As Map = Json2Map(Result)
            
    Dim response As String = resm.Get("response")
            
    Select Case response
                
    Case "failure"
                    Dialog.Initialize(Me, 
    "RequiredFields""RequiredFields")
                    Dialog.Title = 
    "Contact Us"
                    Dialog.Content = 
    "There was an error sending the contact us details!"
                    Dialog.ShowCancelButton = 
    False
                    Dialog.Show
            
    Case Else
                    Dialog.Initialize(Me, 
    "RequiredFields""RequiredFields")
                    Dialog.Title = 
    "Contact Us"
                    Dialog.Content = 
    "The email was sent successfully!"
                    Dialog.ShowCancelButton = 
    False
                    Dialog.Show
            
    End Select
        
    End If
    End Sub
    We did not use the wait methodology for this, so we need a trapper. As per php code above, on success we return success or failure.

    So the result returned here is a JSON string {"response":"success"} or {"response":"failure"}. To get what we need we convert this to a map with a helper method (see example) and then get the response. Based on the response, we show the appropriate method.

    Note: As the sending method might take time, it would be better to show a loader here.
     
    joulongleu likes this.
  4. Mashiane

    Mashiane Expert Licensed User

    The generated PHP file

    BANano generates a php file named email.php based on the name we gave it. Opening this php file and going through it, one notices...

    Code:
    <?php header("Access-Control-Allow-Origin: *");$rest_json = file_get_contents("php://input");$_POST = json_decode($rest_json, true);$request='';if(isset($_POST['request'])){$request = $_POST['request'];$params = $_POST['params'];}if (!function_exists($request)) die("invalid request: '" . $request . "'");
    function SendEmail($from,$to,$cc,$subject,$msg) {
        $msg = str_replace(
    "\n.""\n..", $msg);
        // use wordwrap() 
    if lines are longer than 70 characters
        $msg = wordwrap($msg,
    70,"\r\n");
        //define from header
        $headers = 
    "From:" . $from . "\r\n";
        $headers .= 
    "Cc: " . $cc . "\r\n";
        $headers .= 
    "X-Mailer:PHP/" . phpversion();
        // send 
    email
        $response = (mail($
    to,$subject,$msg,$headers)) ? "success" : "failure";
        $output = json_encode(
    array("response" => $response));
        header(
    'content-type: application/json; charset=utf-8');
        echo($output);
    }
    $values = array_values($params);call_user_func_array($request, $values);?>
    This file is placed on the root of our server (im compiling to a xampp folder)
     
    joulongleu likes this.
  5. joulongleu

    joulongleu Active Member

    Hi Mashiane:response:success ,But the mailbox still can't receive the letter.
     
  6. Cableguy

    Cableguy Expert Licensed User

    Check the junk folder!
     
    joulongleu likes this.
  7. Mashiane

    Mashiane Expert Licensed User

    Can you do a log for se and nmsg before BANano.CallInlinePHP to ensure everything is assigned properly, I just remembered I had to tweak some of the controls inside BANanoSkeleton to use .GetValue for the getText methods.

    All the best!
     
    joulongleu likes this.
  8. joulongleu

    joulongleu Active Member

  9. Mashiane

    Mashiane Expert Licensed User

    @joulongleu you need to replace the <fromemail>, <ccemail> and <toemail> on the code with the exact email addresses you have created. For example, <ccemail> might be joulongleu@company.com, <fromemail> could be server@company.com and <toemail> might be admin@company.com. These should be actual email addresses that exist and <fromemail> address should be an email address existing on your own server.

    The text boxes are not being read, so open up the BANanoskeleton library source code and update the SKTextBox module with the code below (well this is how I managed to make it work)

    Code:
    public Sub setText(text As String)
        
    If mElement <> Null Then
            mElement.SetValue(text)
        
    End If
        mText = text
    End Sub

    public Sub getText() As String
        mText = mElement.GetValue
        
    Return mText
    End Sub
    The getText sub originally has return mText, I decided to include mText = mElement.GetValue just to ensure that the value gets read directly and not from a variable assignment. On setText I also changed the last line before the end of the sub. It should work properly after that you have recompiled and refreshed the libs in your project.

    Anyway I have included my version compiled with 2.46 here.

    Ta!
     

    Attached Files:

    Last edited: May 22, 2019
    joulongleu likes this.
  10. joulongleu

    joulongleu Active Member

    Yes,Thank You,only Message is null .

    upload_2019-5-22_21-5-47.png
     
  11. Mashiane

    Mashiane Expert Licensed User

    @joulongleu , ohh, that's a text area, eish. The same code in post #9 also applies. Here is my updates SKTextArea component, kindly update yours for the skeleton library with this one and then recompile it (run + compile to library) and then refresh your lib list in your project.

    I see you also need to update the content inside <> for ccemail, toemail, fromemail, for example with your own addresses, for example.

    Code:
    Dim nmsg As String = $"Full Name: ${sname}\r\nEmail Address: ${semail}\r\nTelephone: ${sphone}\r\nMessage:\r\n${smsg}"$
            
    Dim se As Map = CreateMap("from":"website@mysite.com", _
            
    "to":"admin@mysite.com", _
            
    "cc":"website@mysite.com", _
            
    "subject":"Contact Us:" & sname, _
            
    "msg":nmsg)
            Banano.CallInlinePHP(
    "SendEmail", se, "contactus")
    Ta!
     

    Attached Files:

    Last edited: May 22, 2019
    joulongleu likes this.
  12. joulongleu

    joulongleu Active Member

    @Mashiane:Thanks for the message ok, <fromemail>, <ccemail> and <toemail> replace "joulongleu@yahoo.com.tw" Right? But still not sent to the mailbox?

    upload_2019-5-22_21-40-45.png
     
  13. Mashiane

    Mashiane Expert Licensed User

    @joulongleu I see you are using yahoo.com.tw as your domain. This exercise has been based on OWN ISP tests and it's intended for use in own ISP domain scenarios.. I created the email addresses via my own ISP cpanel and also tested with XAMP which worked also based on How To Guides of using XAMP to send email.

    Sadly I don't think this will work with any externally controlled domains.

    If your to email address is the same as cc email address, you can just leave the cc email address blank. I'm using that because I needed another email to be sent to the cc email address.

    Remember: The fact that it says True on success does not guarantee delivery of the message (as per PHP documentation).

    Ta!
     
    joulongleu likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice