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

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
 

Mashiane

Expert
Licensed User
Longtime 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.

B4X:
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..

B4X:
#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
 

Attachments

  • BANanoSendEmail.zip
    4.9 KB · Views: 396
Last edited:

Mashiane

Expert
Licensed User
Longtime 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.

B4X:
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


B4X:
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.
 

Mashiane

Expert
Licensed User
Longtime 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...

B4X:
<?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)
 

Mashiane

Expert
Licensed User
Longtime 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 [email protected], <fromemail> could be [email protected] and <toemail> might be [email protected]. 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)

B4X:
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!
 

Attachments

  • SKTextBox.bas
    9.4 KB · Views: 325
Last edited:

Mashiane

Expert
Licensed User
Longtime 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.

B4X:
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":"[email protected]", _
        "to":"[email protected]", _
        "cc":"[email protected]", _
        "subject":"Contact Us:" & sname, _
        "msg":nmsg)
        Banano.CallInlinePHP("SendEmail", se, "contactus")

Ta!
 

Attachments

  • SKTextArea.bas
    9.2 KB · Views: 339
Last edited:

Mashiane

Expert
Licensed User
Longtime User
This has been tested with XAMP and also my own ISP.
@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!
 

Mashiane

Expert
Licensed User
Longtime User
With php this is usually done by the isp without one's involvement. If you are using laragon for testing, you can use your Gmail account to test and send, set that on the laragon ui.

It's finicky and a trial and error exercise.

I have not been able to use the built in Banano smtp features.

If you want something stable rather use a 3rd party that you can use Rest API with.
 

Mashiane

Expert
Licensed User
Longtime User
Testing with Laragon for example...

Step 1: On your gmail account, ensure you enable access from 3rd party apps that are less secure. Turn it ON.

1644495515699.png


Step 2: On Laragon Mail Sender, specify your gmail account and password.
Step 3: Click Test Mail Settings, it will open up a console processing the test process.

Now, if you are able to receive a test email on your account, all you need to do is just use the example code on post 2 to send emails internally to your app.

1644495245720.png
 
Top