Adding input field to PHP emailer only if it exists, how? - php

I have a form with inputs for 'name' and 'email'. And another for 'data-1'. The user can click on add button and jQuery will dynamically add a input for 'data-2', 'data-3' etc..as needed.
The form is posted to a PHP emailer script which validates fields and places data into a template for mailing.
How can i add inputs 'data-2', 'data-3' etc.. if they are created? And if they are not how can i avoid gaps in my email template?
(is there a way to write it so if the post is received add this and if not do nothing?)
Here is an example of the code i am using:
$name = $_POST['name'];
$email = $_POST['email'];
$data-1 = $_POST['data-1'];
(do i need to add: $data-2 = $_POST['data-2'] and $data-3....up to a set value of say 10?)
$e_body = "You were contacted by $name today.\r\n\n";
$e_data = "Data Set 1: $data-1.\r\n\n";
Here is where i would like to show "Data Set 2/3/4....etc" if they exist
$e_reply = "You can contact $name via email, $email";
$msg = $e_body . $e_data . $e_reply;
if(mail($address, $e_subject, $msg, "From: $email\r\nReply-To: $email\r\nReturn-Path: $email\r\n")) {
I hope that is clear and thank you for any help or guidance
thom

You should be using input arrays for this purpose.
In your HTML, set the name of the form element to conform to this naming scheme: data[].
Then, when the form is submitted you can simply loop through this array and add fields to the email within the loop:
$name = $_POST['name'];
$email = $_POST['email'];
$data = $_POST['data'];
$e_data = '';
foreach($data as $i => $d) {
if((int) $i != $i) continue; //thanks Alex
$e_data .= "Data Set {$i}: " . $d . "\r\n\n";
}
//...
On the client side, your code should be something like this:
<input type="hidden" name="data[]"/>

As a general point form processing is trick and has many traps for the unwary. It's worth having a look at this post on best practice form processing
The crux of your problem is that you do not know how many "data" values you will get in your $_POST array. The answer is simply to iterate over the $_POST array to find your data values.
$rawData = array();
foreach ($_POST as $index => $value) {
// Test for a "data-n" index
if ((preg_match('#^data-\d+#i', $index, $matches))) {
$rawData[] = $value;
}
}
The above code will copy all the $_POST values with keys of the form 'data-0', 'data-1', etc. You can then filter and validate these values.
All we do is iterate over $_POST to get each key and value. We then test the key using preg_match to see if it starts with the string 'data-' and is followed by one or more digits. If so, we add it to our raw (unfiltered, non validated) data.
In this example, we could replace the preg_match with the strpos function -
if ( strpos ($index, 'data-') === 0) {
The use of the preg_match gives us more flexibility. For example, if you wanted to capture the numeric portion of your 'data-n' keys - 'data-23', 'data-999', 'data-5', etc. Then change the if statement to
if ((preg_match('#^data-(\d+)#i', $index, $matches))) {
$rawData[$matches[1]] = $value;
}
The variable $matches is an array that captures the results of the search. The complete matching string is is $matches[0]. However, we have enclosed the digit matching pattern in parenthesis and hence the captured digits are placed into $matches1 which we then use to key the $rawData array. In this case $rawData would have the keys = 23, 999 and 5.

Use something like this:
if(isset($_POST['data-1']))
{
// $_POST['data-1'] exists, include it.
}
else
{
// $_POST['data-1'] doesn't exists, don't include it.
}

Related

When sending PHP form, loop from a list of PHP variables each time form is submitted

I want to loop through a few emails so that every time a form is submitted to myform.php, a different user is emailed.
Please note I am not looking for any functions to send mail. It happens to be emails being used, but the point is I need to know how to loop through a variable from a list of options.
This question isn't actually about emailing, because the form already works and sends email using a variable named $mail_to. Instead, this question is about looping a PHP variable each time a form is submitted.
Whatever I can do to loop them, the rest of the form works when putting an email into $mail_to like
$mail_to = 'user1#mycompany.com';
What I want to do is instead of putting one email into $mail_to, instead I want to loop through a few emails. For example,
Emails:
user1#mycompany.com
user2#mycompany.com
user3#mycompany.com
user4#mycompany.com
In PHP form:
$email_looped = [???];
$mail_to = $email_looped;
Above, [???] is simply me saying in human terms I don't know what to do here.
Effectively, it will work like this in real time:
1st Visitor submits form from website >> $mail_to = 'user1#mycompany.com';
2nd Visitor submits form from website >> $mail_to = 'user2#mycompany.com';
3rd Visitor submits form from website >> $mail_to = 'user3#mycompany.com';
4th Visitor submits form from website >> $mail_to = 'user4#mycompany.com';
5th Visitor submits form from website >> $mail_to = 'user1#mycompany.com';
etc
How can I make it so that every time the form is posted to myform.php (from mypage.html), it chooses the next email in the list and loops them?
You could store the last index in a text file or database, retrieve that value on the next request, and use it to get the next item in the array. Tons of ways to accomplish this, some pseudo code to get you started.
function storeCurrentEmail(int $currentIndex): void
{
// return \Database::table->store('lastEmailIndex', $currentIndex);
// return file_put_contents("/path/to/cached/file.txt", $currentIndex);
}
function getNextEmail(): array
{
// $lastEmailIndex = file_get_contents("/path/to/cached/file.txt");
// $lastEmailIndex = \Database::table->get('lastEmailIndex');
$lastEmailIndex = 3; // for illustrative purposes
$emails = [
'user1#mycompany.com',
'user2#mycompany.com',
'user3#mycompany.com',
'user4#mycompany.com'
];
if ($lastEmailIndex >= sizeof($emails)) {
$lastEmailIndex = 0;
}
return [
$emails[$lastEmailIndex],
$lastEmailIndex
];
}
list($mail_to, $lastIndex) = getNextEmail();
storeCurrentEmail($lastIndex);
\Mail::sendTo($mail_to);
Here I have solved it rather simply:
first create a file in current directory named current.txt and write a 0 in it.
php code:
$emails = [
'user1#mycompany.com',
'user2#mycompany.com',
'user3#mycompany.com',
'user4#mycompany.com'
];
$lastEmailIndex = file_get_contents("current.txt");
$max = count($emails) - 1;
if ($lastEmailIndex >= $max) {
$lastEmailIndex = 0;
file_put_contents("current.txt",0);
} else {
file_put_contents("current.txt",#file_get_contents("current.txt")+1);
$lastEmailIndex = file_get_contents("current.txt");
}
usage:
echo '<script>alert("'. $emails[$lastEmailIndex] . '")</script>';
Now it will loop through all available items, and you can add as many items to the array as you want.
PHP can be brutally simple, enjoy ;)
targets.txt:
user1#example.com
user2#example.com
user3#example.com
user4#example.com
example.php
//read and trim the targets file
$targets = file_get_contents('targets.txt');
$targets = trim($targets," \r\n");
$arr = explode("\n",$targets);
$mail_to = $arr[0];
//now rotate the file
$temp = array_shift($arr);
$arr = array_merge($arr,array($temp));
file_put_contents('targets.txt', implode("\n",$arr));
echo $mail_to;

How to expand variables that are in a text file when reading the file into a string?

In the context of processing html form input and responding by sending email via php, rather than having a lengthy heredoc assignment statement in the middle of my code, I'd like to have the email text in a file and read it in when needed, expanding the embedded variables as required.
Using appropriately prepared HTML form data input, I previously had…
$message = <<<TEXT
NAME: {$_POST["fname"]} {$_POST["lname"]}
POSTAL ADDRESS: {$_POST["postal"]}
EMAIL ADDRESS: {$_POST["email"]}
[... message body etc.]
TEXT;
Moving the text to a file I then tried…
$message = file_get_contents('filename.txt');
…but found that variables in the text are not expanded, resulting in output including the variable identifiers as literals.
Is there a way to expand the variables when reading the file into a string ?
There's probably a duplicate, if found I'll delete. But there are two ways that come to mind:
If you construct your file like this:
NAME: {fname} {lname}
Then loop the $_POST variables:
$message = file_get_contents('filename.txt');
foreach($_POST as $key => $val) {
$message = str_replace('{'.$key.'}', $val, $message);
}
If you construct your file like this:
NAME: <?= $_POST["fname"] ?> <?= $_POST["lname"] ?>
If HTML .txt or other (not .php) then:
ob_start();
$file = file_get_contents('filename.txt');
eval($file);
$message = ob_get_clean();
If it's a .php file then buffer the output and include:
ob_start();
include('filename.php');
$message = ob_get_clean();
Thanks to the help from AbraCadaver I put everything into a function which will handle the file and array, returning the composed message. I constructed the file to use [key] marking the places where data is to be inserted. Works like a charm. Thank you.
function compose_message($file, $array) {
// reads content of $file
// interpolates values from $array into text of file
// returns composed message
$message = file_get_contents($file);
$keys = array_keys($array);
foreach ($keys as $key) {
$message = str_replace("[$key]", $array[$key], $message);
}
return $message;
}

How to pass Emails in Session Vars

I understand the basics of $_SESSION vars in php. I currently have a site that passes several values to and from pages that manage SQL queries throughout. I ran into a new problem:
I am using an email address as a Primary Key in my users table. I wish to pass this email to a second page (once the additional infomration is gathered from the server) and dynamically load content when the links are selected. This is my setup for my problem:
//Data returned from server:
// $FName = bob, $LName = rogers, $Email = bob#rogers.com
$_SESSION['userEmail'] = $Email;
$_SESSION['FirstName'] = $FName;
$_SESSION['LastName'] = $LName;
When I load the content on the second page, I recieve these values:
echo $_SESSION['userEmail']; //bob#rogers_com !!!!! THIS is not correct
echo $_SESSION['FirstName']; //bob
echo $_SESSION['LastName']; //rogers
The email is gathered from a POST form on the page. it is the only value within the form. On the first page, I retrieve the email using end(array_keys($_POST)), which is where "$_SESSION['userEmail'] = $Email" comes from. It is, more specifially, :: $_SESSION['userEmail'] = end(array_keys($_POST))::
How do I make it so the Email is passed safely through the request without being transformed?
After further troubleshooting, I have been able to determine that this transformation occurs in the POST request of the form. When clicked the form is using the POST method, which is intercepted in PHP using if($_SERVER['REQUEST_METHOD'] == 'POST'){}, where I capture the array of values (in my case, just the one email) - where the email is now transformed.
If you want use not transformed text such as hash, encode, etc,
you can try use alternative key alternative to your email primary key.
You can take hit from auto_increment index key each row.
Before:
select * from users where email = 'johndoe#johndoe.com';
After:
select * from users where id = '1';
This is equals to:
select * from users where id in (select id from users where email = 'johndoe#johndoe.com');
Good luck.
I have search and found this thing its work in Xampp localhost.This will be helpful.
/**
* Return parsed body in array format (without converting dots and spaces to underscore).
* #return array result parsed
*/
function fetch_parsed_body_nodots()
{
function DANODOT($string) {
$bes1= explode("&", $string);
foreach ($bes1 as $bes2) {
$bes2= explode("=",$bes2);
list($kilil, $beha) = array_map("urldecode", $bes2);
if(!empty($kilil)){
$te[$kilil] = $beha;
}
}
return $te;
}
return DANODOT($this->result_body);
}
http://forum.directadmin.com/showthread.php?t=48001
I figured out a work-around:
When you have the email, you can replace the chars '.' with a different sequence of characters; this is something that would not be found in a usual email address. I found that -#- is a decent one that works (generally). This is how I did it:
$TempFormat = strtr($row['UserEmail'], array('.' => '-#-'))
Then, when I went to my if($_SERVER['REQUEST_METHOD'] == 'POST'){} function, i transformed the string back to it's (hopefully) original state by performing:
$OriginalFormat = strtr(end(array_keys($_POST)), array('-#-' => '.'))

How to stop str_replace from changing all instances in every item in the array?

I'm looping a multidimensional array with a for loop and triggering and email for every item in the loop. I want change {{fname}} to the real name from the key.
foreach($customermarketingarray as $key => $value){
$customeremail = $value['email'];
$fname = $value['first_name'];
$body = str_replace("{{fname}}",$fname,$body);
}
For some reason everything is coming out unique except the {{fname}} is using the first name in the first loop for every fname in the loop. If the first person is Joe, it's making every fname Joe
Because you are using one $body over and over again, and once the replacement has been made there is nothing more to replace. Use a fresh version of $body on every iteration.
foreach($customermarketingarray as $key => $value){
$customeremail = $value['email'];
$fname = $value['first_name'];
$tempBody = str_replace("{{fname}}",$fname,$body);
// now use this $tempBody for display
}
This way on every iteration of your loop you get a new template from $body again and you can make replacements to it and then use it.
First time you are using str_replace it replaces occurrences of {{fname}} in entire body. There is nothing to replace in further loop iterations.
Use preg_replace which has additional parameter (limit) which states how many replacements will be made at most. In your example if there is only one {{fname}} per each name using 1 as count parameter will do.
Read the documentation. It's pretty self explanatory.
http://php.net/manual/en/function.preg-replace.php
Another thing is problem with construction of your data. You cannot distinguish, without additional rules, which {{fname}} goes to which replacement.
It is not clear whether you want to use $body as template (I've assumed as no, because you are not using $body for anything except replacement in loop iterations). My answer is valid if there are multiple occurrences of {{fname}} in body and you want to replace them one by one with names from loop iterations.
You are replacing the variable $body in each loop. Just use a new variable to store the result. See my example below.
<?php
$customermarketingarray=array(
0=>array("email"=>"1#test.com","first_name"=>"Joe1"),
1=>array("email"=>"2#test.com","first_name"=>"Joe2"),
2=>array("email"=>"3#test.com","first_name"=>"Joe3"),
3=>array("email"=>"4#test.com","first_name"=>"Joe4")
);
$body="First Name: {{fname}}<br>Email: {{email}}<br><br>";
foreach($customermarketingarray as $key => $value){
$customeremail = $value['email'];
$fname = $value['first_name'];
$email = $value['email'];
$res_body .= str_replace(array("{{fname}}","{{email}}"),array($fname,$email),$body);
}
echo $res_body;
?>
The result for the above code is
First Name: Joe1
Email: 1#test.com
First Name: Joe2
Email: 2#test.com
First Name: Joe3
Email: 3#test.com
First Name: Joe4
Email: 4#test.com
Using preg_replace
It can be done using preg_replace instead str_replace
Answer: PHP variables and loops in HTML format
go through and check deprecated, http://php.net/manual/en/function.preg-replace.php
$body_message = $body;
foreach($customermarketingarray as $key => $value){
$customeremail = $value['email'];
$fname = $value['first_name'];
// $body = str_replace("{{fname}}",$fname,$body);
$body_message = preg_replace("/{{(.*?)}}/e","#$$1", $body);
}
Using str_replace
$body_message = $body;
foreach($customermarketingarray as $key => $value){
$customeremail = $value['email'];
$fname = $value['first_name'];
$body_message = str_replace("{{fname}}",$fname,$body);
}

PHP foreach loop inside foreach loop

I'm trying to do a foreach loop inside a foreach loop.
I have a form where the user type in some text and hit send. On the server site I loop through an array with email addresses and send out the text message.
Now I also want the user to be able to use variables in the textarea, like $name.
So my loop should first loop through the emails, and then str_replace the userinput $name variable, with the names in my array.
The loop works fine with the email part ($tlf), but not the replace $name part.
Could some spot what I am doing wrong?
$message = stripslashes(strip_tags($_POST['message2']));
$tlf=array("name1","name2");
$test=array("mname1", "mname2");
$subject = "Hello world";
$from = "me#gmail.com";
$headers = "From: $from";
foreach($tlf as $name){
$to = $name. "#gmail.com";
foreach($test as $navn){
$message = str_replace('$navn', $navn, $message);}
mail($to,$subject,$message,$headers);
}
Thanks a lot.
EDIT:
The output is an email sent. Say the user type in "hello $name".
I want it to first loop through the $tlf array, in this case creating 2 emails. This goes in as $to in the first loop. This works.
Now the next loop should recognize the user input "hello $name" and loop through the $test array replacing the user $name variable.
The output would be 2 emails send.
Mail output:
to: name1#gmail.com
message: hello mname1
Mail output:
to: name1#gmail.com
message: hello mname2
Let me know if I need to explain better, its hard for me to explain sorry.
When you do the following:
str_replace('$navn', $navn, $message)
Then all literal occurences of $navn will be replaced (the first, the second, the third, ...). So running through that loop a second time can't possibly replace anything more.
You will need to define two placeholders, or make some distinction, or use preg_replace_callback if you want to declare in which order (or other logic) the possible replacement strings are applied.
If you had told us (but you haven't) you only wanted to replace the first occurence in each iteration, then a normal preg_replace(.., .., .., 1) would work.
Is this what you want?
$message = stripslashes(strip_tags($_POST['message2']));
$tlf=array(
array("email" => "name1", "name" => "mname1"),
array("email" => "name2", "name" => "mname2")
);
$subject = "Hello world";
$from = "me#gmail.com";
$headers = "From: $from";
foreach($tlf as $contact){
$to = $contact["email"] "#gmail.com";
$replacedMessage = str_replace('$navn', $contact["name"], $message);
mail($to,$subject,$replacedMessage,$headers);
}

Categories