Am not sure if the strpos() is the right function to use for this
task.
PROBLEM:
if the user input hate or another string in my spam variable
it return the spam filter message which is correct, but if the user
input a spam variable mixed with any string not in the various it
passes for processing.
I want the input to to check from the first string to the last string
and that t doesn't contains any of the spam variable string then
return process, here is my code
<?php
//messgae
error_reporting(E_ALL ^ E_NOTICE);
$msg = array();
$spam = "hate partisan party kill maim murder violence love sex fight beat assasinate thug steal sell bribe protest baricade bullets militia fear ";
$spam_array = explode(" ",$spam);
$check = strpos($spam, $_POST['message']);
if ($check == true) {
//do nothing
$msg['invalid'] = 'Spam filter test didnt allow your message';
} else {
$msg['valid'] = 'process';
}
if(isset($_POST['send'])){
$message= $_POST['message'];
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Strpos</title>
</head>
<body>
<?php
if (isset($msg)) {
echo '<ul>';
foreach ($msg as $alert) {
echo "<li class='warning'>$alert</li>\n";
}
echo '</ul>';
}?>
<form action="" method="post">
<input name="message" type="text" />
<input name="send" type="submit" value="Submit" id="send" />
</form>
</body>
</html>
You started something there, with the $spam_array.
They you check it know, you check if the exact string of bad words are found in your message.
Also stripos instead of strpos so that it will be case insensitive.
$spam = "hate partisan party kill maim murder violence love sex fight beat assasinate thug steal sell bribe protest baricade bullets militia fear ";
$spam_array = explode(" ",$spam);
$isSpam = isSpam($_POST['message'], $spam_array);
function isSpam($content, $spamList)
{
foreach($spamList as $badWord) {
if(stripos($content, $badWord) !== false) {
return true;
}
}
return false;
}
You need to improve your check with word boundaries or you would have false positives for words like "gloves" (love) and "Essex" (sex). You should also make it case-insensitive.
The following approach (check function) uses a preg_match with word boundary metacharacters when looking for each "spam word" within the message. The i modifier also makes it case-insensitive:
function check($msg, $spam_array) {
foreach ($spam_array as $spam_word) {
if (preg_match("/\b" . $spam_word ."\b/i", $msg)) {
return false;
}
}
return true;
}
function test($msg, $spam_array) {
echo "$msg => ", check($msg, $spam_array) ? 'OK' : 'not OK', PHP_EOL;
}
$spam = "hate partisan party kill maim murder violence love sex fight beat "
. "assasinate thug steal sell bribe protest baricade bullets militia fear";
$spam_array = explode(" ", $spam);
test("I'm known for my cookie munching skills.", $spam_array);
test("I could kill for some cookies right now!", $spam_array);
Output:
I'm known for my cookie munching skills. => OK
I could kill for some cookies right now! => not OK
Related
I'm similar to php and don't undestand what is the problem.
Sometimes php function send me empty messages like
Vanema nimi
Lapse nimi:
Linn:
Telefoninumber:
Email:
Sünnikuupäev:
Sõnumi tekst:
But it should be filled with values like this
Vanema nimi test
Lapse nimi: test
Linn: test
Telefoninumber: test
Email: test#test
Sünnikuupäev: 21313
Sõnumi tekst:test
Here is my php code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Обратная Связь</title>
</head>
<body>
<?php
if (isset($_POST['parent'])) {$parent = $_POST['parent'];}
if (isset($_POST['child'])) {$child = $_POST['child'];}
if (isset($_POST['contacts'])) {$contacts = $_POST['contacts'];}
if (isset($_POST['email'])) {$email = $_POST['email'];}
if (isset($_POST['bbd'])) {$bbd = $_POST['bbd'];}
if (isset($_POST['city'])) {$city = $_POST['city'];}
if (isset($_POST['mess'])) {$mess = $_POST['mess'];}
$to = "info#test.ee"; /*Укажите ваш адрес электоронной почты*/
$headers = "Content-type: text/plain; text/html; charset=utf-8";
$subject = "Kontakti Info";
$message = "Vanema nimi $parent \n Lapse nimi: $child \nLinn:
$city \nTelefoninumber: $contacts \nEmail: $email \nSünnikuupäev: $bbd \nSõnumi tekst: $mess";
$send = mail ($to, $subject, $message, $headers);
if ($send == 'true')
{
echo "<b>Спасибо за отправку вашего сообщения!<p>";
echo "<a href=index.php>Нажмите,</a> чтобы вернуться на главную страницу";
}
else
{
echo "<p><b>Ошибка. Сообщение не отправлено!";
}
?>
</body>
</html>
<?php
header('Location: https://test.ee/aitah.html ');
?>
Please give me advice what is wrong.
If your script is a form processor only, you could e.g. add if(empty($_POST)) { die('No form data!'); } to the top to prevent it from running, except in response to a form submission.
If you require all fields to be filled in, you will have to check each of them before you process your email. You could cram all of those issets into one monster if(isset(...) statement. However, there's a simpler and more readable way to do it. First, let's set up a couple of variables:
// Your required fields:
$fields = ['parent', 'child', 'contacts', 'email', 'bbd', 'city', 'mess'];
// Your data is collected here:
$data = [];
// Any errors are collected here:
$errors = [];
Then, we loop over the fields and if values exist, add to $data, otherwise we add an error note.
// Loop to check your required fields:
foreach($fields as $field) {
// If value exists, add to $data:
if(!empty($_POST[$field])) {
$data[$field] = $_POST[$field];
}
// Else add error:
else {
$errors[] = 'Missing field: ' . $field;
}
}
if(empty($errors)) {
// No errors, send your email
// You can use "Vanema nimi {$data['parent']}...",
// ... otherwise: extract($data) to use $parent etc.
}
else {
// You could report those errors, or redirect back to the form, or whatever.
}
If there are errors (= missing fields), e-mails won't be sent. As a bonus, you now have a reusable piece of code that you can use for other forms with similar functionality simply by modifying the $fields array. (Wrapping it into a function is a good idea if you do need to reuse it; don't copy-paste code. function x($post, $fields) { ... } for a basic helper function.)
Note that here we are using empty in place of isset. If a blank form is submitted, the fields are set (to empty strings ""). Also note that empty returns true for anything that equals false (ie. "", 0, false, null, []). (If "0" is an expected and acceptable value, be aware of its "emptiness"!) On the other hand, isset returns true for anything not null.
P.S. If your code above is the complete code, and your script simply processes the form data and redirects, then you don't really need the HTML wrapper at all. It will never be displayed.
Removing empty lines in Notepad++
As described in the thread above you are able to remove empty lines with notepad++. I did try those methods but I am always receiving weird T_Variable Syntax Errors (mostly in line 1-6). There definitely is no error in those lines and I can not see one anywhere.
It also happens when I manually delete the empty lines in some areas of the code (first 5 lines for example). I am guessing this is an encoding problem but also reencoding in UTF-8, Ascii etc. did not help.
Those lines were added when I used an online editor from a webhoster a couple of months ago (1 empty line between the lines that were there before).
I do not get it, maybe you do (thanks in advance!). The file is at http://lightningsoul.com/index.php
And here is the first block of code:
<?php
include("db/lg_db_login.php");
//require 'fb/facebook.php';
if (isset($_GET['c'])) { $content = $_GET['c']; }
else { $content = ""; }
if (isset($_GET['sc'])) { $subcontent = $_GET['sc']; }
else { $subcontent = ""; }
if (isset($_GET['setlang'])) { $setlang = $_GET['setlang']; }
else { $setlang = "eng"; }
$cat = $_GET['cat'];
// Check if Lightningsoul.de or .com
$findme = '.de';
$posde = strpos($thisurl, $findme);
// Note our use of ===. Simply == would not work as expected
// because the position of 'a' was the 0th (first) character.
if ($posde === false) {
$lang = "en";
} else {
$lang = "de";
}
include("db/pageturn_class.php");
$findStr = '/lightningsoulcom';
$isApp = strpos($thisurl, $findStr);
// Beachten Sie die Verwendung von ===. Ein einfacher Vergleich (==) liefert
// nicht das erwartete Ergebnis, da die Position von 'a' die nullte Stelle
// (also das erste Zeichen) ist
/*if ($isApp == false) {
$getStyle = "css/get_style.php";
} else {
$getStyle = "css/get_style_small.php";
} */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The problem was in line 181 where something (notepad++?!) must have changed
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
to
<meta http-equiv="content-type" content="text/html; charset=Windows-1250" />
That produced lots of errors as one would expect. I only found it by removing the head part by part.
I have a problem that I need help fixing. I am trying to create a script that crawls websites for mailing addresses. Mostly German addresses, but I am unsure of how to create said script, I have created one already that extracts email addresses from said websites. But the address one is puzzling because there isn't a real format.. Here is a couple German addresses for examples on a way to possibly extract this data.
Ilona Mustermann
Hauptstr. 76
27852 Musterheim
Andreas Mustermann
Schwarzwaldhochstraße 1
27812 Musterhausen
D. Mustermann
Kaiser-Wilhelm-Str.3
27852 Mustach
Those are just a few examples of what I am looking to extract from the websites. Is this possible to do with PHP?
Edit:
This is what I have so far
function extract_address($str) {
$str = strip_tags($str);
$Name = null;
$zcC = null;
$Street = null;
foreach(preg_split('/([^A-Za-z0-9üß\-\#\.\(\) .])+/', $str) as $token) {
if(preg_match('/([A-Za-z\.])+ ([A-Za-z\.])+/', $token)){
$Name = $token;
}
if(preg_match('/ /', $token)){
$Street = $token;
}
if(preg_match('/[0-9]{5} [A-Za-zü]+/', $token)){
$zcC = $token;
}
if(isset($Name) && isset($zcC) && isset($Street)){
echo($Name."<br />".$Street."<br />".$zcC."<br /><br />");
$Name = null;
$Street = null;
$zcC = null;
}
}
}
It works to retrieve $Name(IE: Ilona Mustermann and City/zipcode(27852 Musterheim) but unsure of a regex to always retrieve streets?
Well this is what I have came up with so far, and it seems to be working about 60% of the time on streets, zip/city work 100% and so does name. But when it tries to extract the street occasionally it fails.. Any idea why?
function extract_address($str) {
$str = strip_tags($str);
$Name = null;
$zcC = null;
$Street = null;
foreach(preg_split('/([^A-Za-z0-9üß\-\#\.\(\)\& .])+/', $str) as $token) {
if(preg_match('/([A-Za-z\&.])+ ([A-Za-z.])+/', $token) && !preg_match('/([A-Za-zß])+ ([0-9])+/', $token)){
//echo("N:$token<br />");
$Name = $token;
}
if(preg_match('/(\.)+/', $token) || preg_match('/(ß)+/', $token) || preg_match('/([A-Za-zß\.])+ ([0-9])+/', $token)){
$Street = $token;
}
if(preg_match('/([0-9]){5} [A-Za-züß]+/', $token)){
$zcC = $token;
}
/*echo("<br />
N:$Name
<br />
S:$Street
<br />
Z:$zcC
<br />
");*/
if(isset($Name) && isset($zcC) && isset($Street)){
echo($Name."<br />".$Street."<br />".$zcC."<br /><br />");
$Name = null;
$Street = null;
$zcC = null;
}
}
}
Of course it is possible you need to use preg_match() function. It is all about making a good regex pattern.
For example to get post-code
<?php
$str = "YOUR ADRESSES STRING HERE";
preg_match('/([0-9]+) ([A-Za-z]+)/', $str, $matches);
print_r($matches);
?>
this regex matches adresses you've given you need to put in it also your native characters.
[A-Za-züß.]+ [A-Za-z.üß]+\s[A-Za-z. 0-9ß-]+\s[0-9]+ [A-Za-züß.]+
It's impossible to get a reliable answer with regex with such a complicated string. That's the only correct answer to this question.
Vlad Bondarenko is right.
In CS speak: Postal addresses do not form a regular language.
Extracting information is an active research topic. Regular expressions are not completely bogus, but will have a higher failure rate than approaches that use dictionaries ("gazetteers") or more advanced machine learning algorithms.
A nice stack overflow q/a is How to parse freeform street/postal address out of text, and into components
I read this post: What is a good invisible captcha? about using a hidden field in a web form to stop basic bots from pelting your website with spam mail via your web sites form mail. I'm currently using a php script to process my form mail. I built the script by following a 'bullet proff web form' tutorial I found. It looks like this:
<?php
// Pick up the form data and assign it to variables
$name = $_POST['name'];
$email = $_POST['email'];
$topic = $_POST['topic'];
$comments = $_POST['comments'];
// Build the email (replace the address in the $to section with your own)
$to = 'hello#cipherbunny.com';
$subject = "New message: $topic";
$message = "$name said: $comments";
$headers = "From: $email";
// Data cleaning function
function clean_data($string) {
if (get_magic_quotes_gpc()) {
$string = stripslashes($string);
}
$string = strip_tags($string);
return mysql_real_escape_string($string);
}
// Mail header removal
function remove_headers($string) {
$headers = array(
"/to\:/i",
"/from\:/i",
"/bcc\:/i",
"/cc\:/i",
"/Content\-Transfer\-Encoding\:/i",
"/Content\-Type\:/i",
"/Mime\-Version\:/i"
);
$string = preg_replace($headers, '', $string);
return strip_tags($string);
}
// Pick up the cleaned form data
$name = remove_headers($_POST['name']);
$email = remove_headers($_POST['email']);
$topic = remove_headers($_POST['topic']);
$comments = remove_headers($_POST['comments']);
// Send the mail using PHPs mail() function
mail($to, $subject, $message, $headers);
// Redirect
header("Location: http://foobar/success.html");
I'd like to modify this script so that if a hidden field with the identifier 'other_email' was filled in then the form email wouldn't get sent. I'm guess it's as straight forward as wrapping the above code in an if statement to check if the field is complete. I've tried adding this under the "//Pick up the form data and assign it to variables" code:
$testBot = $_POST['other_email'];
then writing:
if(other_email == "") //If other_email form section is blank then...
{
run all the code above inserted here;
}
else
{
Don't know what I should put here to stop it posting, yet still show the success form so
the spam bot don't know
}
any help much appreciated. I have to say I don't really have a lot of php knowledge, I'm just starting to learn about it and thought form mail would be a good start.
How do I make this work in PhP?
if(other_email == "") //If other_email form section is blank then...
{
run all the code above inserted here;
}
else
{
header("Location: http://foobar/success.html");
}
keeping it very simple, it will work for you..
actually, it will
not submit / mail you anything...so NO SPAM
a simple bot will take it as it did it...
if you can use php on success page, then set a session variable (to make bot think it did its job, something like email_sent=true or success=true) and use that variable in success page, you will do it in else case where bot submitted the form..
Do you mean send message with fields?
Try this:
<?php
// Pick up the form data and assign it to variables
$name = $_REQUEST['name'];
$email = $_REQUEST['email'];
$topic = $_REQUEST['topic'];
$comments = $_REQUEST['comments'];
// Build the email (replace the address in the $to section with your own)
if($name !== null && $email !== null && $topic !== null && $comments !== null){
$to = 'hello#cipherbunny.com';
$subject = "New message: $topic";
$message = "$name said: $comments";
$headers = "From: $email";
// Data cleaning function
function clean_data($string) {
if (get_magic_quotes_gpc()) {
$string = stripslashes($string);
}
$string = strip_tags($string);
return mysql_real_escape_string($string);
}
// Mail header removal
function remove_headers($string) {
$headers = array(
"/to\:/i",
"/from\:/i",
"/bcc\:/i",
"/cc\:/i",
"/Content\-Transfer\-Encoding\:/i",
"/Content\-Type\:/i",
"/Mime\-Version\:/i"
);
$string = preg_replace($headers, '', $string);
return strip_tags($string);
}
// Pick up the cleaned form data
$name = remove_headers($_POST['name']);
$email = remove_headers($_POST['email']);
$topic = remove_headers($_POST['topic']);
$comments = remove_headers($_POST['comments']);
// Send the mail using PHPs mail() function
mail($to, $subject, $message, $headers);
// Redirect
header("Location: http://foobar/success.html");
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis" />
<title>Send</title>
</head>
<body>
<form action="#" method="POST">
Name : <input type="text" name="name" /><br />
Email : <input type="text" name="email" /><br />
Topic : <input type="text" name="topic" /><br />
Comments : <textarea name="comments"></textarea><br />
<input type="submit" value="Send" />
</form>
</body>
</html>
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I run a small website and my users requested that I set up a mailing list. I found a simple free script that adds e-mail addresses to a protected text file, email.txt, in CSV format:
email1#yahoo.com,email2#yahoo.com,blah,blah,blah
The script works flawlessly. However, it is a nuisance to go through the file to manually remove e-mail addresses when users cancel their list subscriptions. I need to create a simple script that removes e-mail addresses.
All I want is a simple PHP script that displays a text box so users can enter their e-mail addresses and click a "Cancel Newsletter" button. The script should search the text file, find the given e-mail address and remove it and its trailing comma.
For example, say the contents of email.txt are
john#yahoo.com,peter#yahoo.com,steve#yahoo.com
If I type "peter#yahoo.com" into the text box displayed by my desired script, I want the file to look like this:
john#yahoo.com,steve#yahoo.com
UPDATE: I tried this code:
<?php
function showForm() {
echo '
<form method="post" action="">
Email Address: <input type="text" name="email"> <br />
<input type="submit" value="Cancel Newsletter" name="submit">
</form>
';
}
$_POST['email']
$to_delete = 'email';
$file = array_flip(explode(",",file_get_contents("email.txt")));
unset($file[$to_delete]);
file_put_contents("email.txt",implode(",",array_flip($file));
if(!$file_put_contents) {
die('Error occured');
} else {
echo 'Your subscription has been cancelled. You will not receive any further emails from us.';
}
}
} else {
showForm();
}
?>
This code doesn't even show the form.
UPDATE 2:
Another attempt at writing this script:
<?php
$email = $_POST["email"];
$text = file_get_contents("email.txt");
$oldWord = "$email";
$newWord = "";
$text = str_replace($oldWord , $newWord , $text);
$fp = fopen('email.txt', 'w');
fwrite($fp, $text);
fclose($file);
?>
This works as far as removing the e-mail address goes, but there is no announcement (echo). I would like for it to say either "that e-mail isn't subscribed" or "you have been removed," based on whether the script sucessfully finds the $email in the list and deletes it.
UPDATE 3 Dec. 31, 2011:
I tried the advanced code and just got a blank page, so I went back to my version. Here is the code I have now:
<html>
<body>
<form method="post" action="">
<p>Email Address: <input type="text" name="email"></p>
<input type="submit" value="Cancel Newsletter" name="submit">
</form>
<?php
$email = $_POST["email"];
$basetext = file_get_contents("email.txt");
$oldWord = "$email";
$newWord = "";
$text = str_replace($oldWord , $newWord , $basetext);
$str1 = $basetext;
// echo strlen($str1);
$str2 = $text;
// echo strlen($str2);
$fp = fopen('email.txt', 'w');
fwrite($fp, $text);
if ($str1 > $str2) { // This part handles the success/fail message
echo ("Success!");
} else {
echo ("Fail!");
}
fclose($file);
?>
</body>
</html>
This works perfectly. However, it displays the "fail" message when the page is loaded, not when triggered to load, after the submit button is pressed.
I would like to keep the original code if possible, just rearranged so that it only shows "Success!" or "Fail!" once it has executed the code.
I would like the echo messages to be the last script executed on the page.
Is there any reason why you don't use a database?
CREATE TABLE `emails` (`address` VARCHAR(255) NOT NULL, PRIMARY KEY (`address`)) ENGINE=InnoDB
INSERT INTO `emails` VALUES ('user1#example.com')
SELECT * FROM `emails`
DELETE FROM `emails` WHERE `address`='user1#example.com'
These are just infinitely easier and more efficient than a text file...
But if you want to use a text file...
$to_delete = 'user1#example.com';
$file = array_flip(explode(",",file_get_contents("email.txt")));
unset($file[$to_delete]);
file_put_contents("email.txt",implode(",",array_flip($file));
Basically what it does it explodes by the comma, then flips the array so that the emails are keys (and their numeric positions are values, but that doesn't matter), then it removes the email you want to delete and finally reassembles the file. The bonus of this is that it will also strip out any duplicates you may have.
You can use a similar method to add email addresses, just changing the unset line to $file['user1#example.com'] = -1; (to ensure the number doesn't conflict with anything, as that would interfere with the array flipping).
This answer was originally appended to the question body by the OP.
First I moved the form to /cancel.html and used <form action="/cancel_submit.html">.
(Where I have written .html, it is just to demonstrate, as my server is configured to use no page extentions and also so that PHP is parsed on .html pages.)
Then I put the PHP code into the page /cancel_submit.html and moved
if ($str1 > $str2) {
echo ("You Have Successfully Unsubscribed From Our Newsletter....<br>You Will Not Receive Any More Emails From Us.");
} else {
echo ("The Email Address You Specified Is Not In Our Mailing List.");
}
to another set of PHP brackets.
This meant that the e-mail adddress was sent via POST to the other page, which then performed the actual removal of the e-mail address from the list and then checked to see if an address been removed to provide the comfirmation message.
I also added two commas to $oldword = "$email"; to make it $oldword = ",$email,"; so that it only finds the text entered into the e-mail box if it has a comma on either side. This addresses the case where someone submits half of an e-mail address.
I also changed $newWord = ""; to $newWord = ","; so that if the script removes an e-mail address with commas at each side, the two e-mail addresses that were next to it will not be separated by a comma.
Here is the code I have for both pages now:
cancel.html
<p>To cancel our Newsletter please enter your email address below....</p>
<p>
<form method="post" action="/cancel_submit.html">
<p>Email Address: <input type="text" name="email"></p>
<input type="submit" value="Cancel Newsletter" name="submit">
</form>
cancel_submit.html
<?php
$email = $_POST["email"];
$basetext = file_get_contents("email.txt");
$oldWord = ",$email,";
$newWord = ",";
$text = str_replace($oldWord , $newWord , $basetext);
$str1 = $basetext;
// echo strlen($str1);
$str2 = $text;
// echo strlen($str2);
$fp = fopen('email.txt', 'w');
fwrite($fp, $text);
fclose($file);
?>
<?php
if ($str1 > $str2) {
echo ("You Have Successfully Unsubscribed From Our Newsletter....<br>You Will Not Receive Any More Emails From Us.");
} else {
echo ("The Email Address You Specified Is Not In Our Mailing List.");
}
?>
<p>
<p>Please wait to be re-directed or <u>CLICK HERE.</u>
</p>
EDIT:
I made a few improvements. I added:
$email = strtolower($email);
to both the e-mail add script and the e-mail remove script. This converted all characters entered into either form to lowercase; previously, it wouldnt remove e-mails typed in a different case than the big list had.
This messed up the confirmation message command, so I changed it to
if (str_replace($oldWord , $newWord , $basetext)) {
echo ("You Have Successfully Unsubscribed From Our Newsletter....<br>You Will Not Receive Any More Emails From Us.");
} else {
echo ("The Email Address You Specified Is Not In Our Mailing List.");
}
Suggested research:
http://us.php.net/manual/en/function.explode.php
http://us3.php.net/manual/en/function.file-put-contents.php
edited to add:
http://us3.php.net/manual/en/function.file-get-contents.php
If you end up with a 3rd party service, don't pay Aweber. Go for MailChimp. They've got a free plan if your mailing list isn't that big.
In your sample you reference a variable $_POST['email'] without assignment or testing the value. Additionally you may want to sanitize this variable.
Another issue I saw was that $to_delete = 'email';, you are only looking for entries of 'email'.
Your $file_put_contents is not being assigned.
} else { showForm(); } wasn't paired up with an if statement.
<?php
function showForm() {
echo '<form method="post" action="">' . PHP_EOL
. 'Email Address: <input type="text" name="email"> <br />' . PHP_EOL
. '<input type="submit" value="Cancel Newsletter" name="submit">' . PHP_EOL
. '</form>';
}
if($_POST['email']) {
$to_delete = $_POST['email'];
$file = array_flip(explode(",",file_get_contents("email.txt")));
unset($file[$to_delete]);
$file_put_contents = file_put_contents("email.txt",implode(",",array_flip($file));
if(!$file_put_contents) {
die('Error occured');
} else {
echo 'Your subscription has been cancelled. You will not receive any further emails from us.';
}
} else {
showForm();
}
If I understand your question correctly, this is what you are attempting to achieve.
Check to see if the user has posted from a form.
Get the email. (You should ensure that it is a sane value in this step)
Retrieve the member data.
Check to see if the user is on the list.
Remove the user and save the data if applicable.
Output the result of the function.
Display a message with form to submit to self.
I know this can be done as a very simple task, but I don't trust that approach. Additionally, I think anything interacting with permanent storage of data should have some mild to moderate form of abstraction.
I would approach that task this way.
class MailingList {
const EMAIL_OK = 1;
const ERR_EMAIL_EXISTS = -1;
const ERR_EMAIL_INVALID = -2;
const ERR_EMAIL_NOTFOUND = -3;
protected $_db_src;
protected $_db_opt;
protected $members = array(); // An array intended to hold members.
public function email_exists($email) {
return array_key_exists($this->members, $email);
}
public function remove_email($email) {
$this->_sanitize_email($email);
if ($email) {
if (array_key_exists($this->members, $email)) {
unset($this->members[$email]);
$this->_update_members();
return self::EMAIL_OK;
} else {
return self::ERR_EMAIL_NOTFOUND;
}
} else {
return self::ERR_EMAIL_INVALID;
}
}
public function add_email($email) {
$this->_sanitize_email($email);
if ($email) {
if (array_key_exists($this->members) {
return self::ERR_EMAIL_EXISTS;
} else {
$this->members[$email] = -1;
$this->_save_members();
$this->_load_members();
return self::EMAIL_OK;
}
} else {
return self::ERR_EMAIL_INVALID;
}
}
// We expect a data source and options for the
// data source upon instantiation.
// This is to prepare this class for abstraction and allow it to be
// extended to databases.
public function __construct($data_source = "flatfile", $data_options = "email.txt") {
$this->_db_src = $data_source;
$this->_db_opt = $data_options;
$this->_load_members();
}
protected function _load_members() {
// Create the function name to ensure it exists.
$data_function = "handle_" . $this->_db_src;
if (!method_exists(&$this, $this->_db_src)) {
throw new Exception('Invalid data source');
}
// Build our array of parameters to be sent to our handler function.
$parameters = array_merge(array('load'), (array) $this->_db_opt);
// This calls our data function with a load action parameter.
// This is written to expect the data function to populate $this->members.
return call_user_func_array(array(&$this, $data_function), $parameters);
}
// Most of this is similar to the constructor as far as data handling goes.
protected function _save_members() {
// Create the function name to ensure it exists.
$data_function = "handle_" . $this->_db_src;
if (!method_exists(&$this, $this->_db_src)) {
throw new Exception('Invalid data source');
}
// Set up our data options with a save action.
$parameters = array_merge(array('save'), (array) $this->_db_opt);
return call_user_func_array(array(&$this, $data_function), $parameters);
}
// The heart of the storage engine, designed for CSV data.
protected function handle_flatfile($action, $filename) {
switch ($action) {
case "load":
// Make sure we can load members.
if (!is_readable($filename)) {
throw new Exception("File: $filename, is not readable");
}
// Open our data file and load the information.
// Populate $this->members as an array just the way we expect it.
$this->members = array_flip(explode(',', file_get_contents($filename)));
break;
case "save":
// Make sure we can write to the file before we move forward.
if (!is_writeable($filename)) {
throw new Exception("File $filename, is now writable");
}
// Convert our array back to a CSV string and write it to the file.
$status = file_put_contents($filename, implode(',', array_flip($this->members)));
// If we failed to write to the file make sure something is done before we continue.
if (!$status) {
throw new Exception("Writing to file failed!");
}
break;
default:
throw new Exception("Unknown action called on data handler.");
}
}
// converts email addresses to lowercase to avoid duplication.
// should add a regex filter here to ensure that we have a valid address
protected function _sanitize_email(&$email) {
$email = strtolower($email);
}
}
function show_form() {
echo '<form method="post" action="">' . PHP_EOL
. 'Email Address: <input type="text" name="email"> <br />' . PHP_EOL
. '<input type="submit" value="Cancel Newsletter" name="submit">' . PHP_EOL
. '</form>';
}
if (isset($_POST) && isset($_POST['email'])) {
$list = new MailingList();
$status = $list->remove_email($_POST['email']);
switch ($status) {
case MalingList::EMAIL_OK:
echo "<p class='success'>Your email was successfully removed.<p>";
break;
case MailingList::ERR_EMAIL_INVALID:
echo "<p class='error'>The email address provided was invalid.</p>";
case MailingList::ERR_EMAIL_NOTFOUND:
echo "<p class='error'>The email address provided was not registered.</p>";
default:
show_form();
}
} else {
show_form();
}