I am trying to use the php mail function to send an email. However, I am not sure how to structure the message part. I am processing an HTML form and I want that to be the message of the html. How could I wrap all of the output in a variable that I can pass as the message argument to the mail() function?
MY PHP:
//Contact Information
$array = $_POST['contact'];
echo '<hr>CONTACT INFORMATION<hr>';
foreach ($array as $key=>$value) {
if ($value != NULL) {
echo '<strong>' . $contact[$key] . '</strong><br/>';
echo $value . '<br/><br/>';
}
}
//Services Information
$array = $_POST['services'];
echo '<hr>SERVICES INFORMATION<hr>';
foreach ($array as $key=>$value) {
if ($value != NULL) {
echo '<strong>' . $services[$key] . '</strong><br/>';
echo $value . '<br/><br/>';
}
}
//Background Information
$array = $_POST['background'];
echo '<hr>BACKGROUND INFORMATION<hr>';
foreach ($array as $key=>$value) {
if ($value != NULL) {
echo '<strong>' . $background[$key] . '</strong><br/>';
echo $value . '<br/><br/>';
}
}
//Services Needed
$value = $_POST['servicesneeded'];
$value = rtrim($value, ", ");
echo '<hr>WHICH SERVICES ARE YOU INTERESTED IN?<hr>';
echo $value;
//Goals
$value = $_POST['goals'];
$value = rtrim($value, ", ");
echo '<hr>WHAT IS THE CORE PURPOSE OF YOUR PROJECT?<hr>';
echo $value;
if (!empty($_POST['goalsOther'])) {
echo '<br/>OTHER: ' . $_POST['goalsOther'];
}
........ I have about a dozen or so of these codeblocks
This isn't really a question about php mail, but more about concatenation. To solve your problem, create a variable, let's call it $message. Then, instead of echoing things out, append them to $message. So, instead of echo '<strong>' . $background[$key] . '</strong><br/>';, you'd have $message .= '<strong>' . $background[$key] . '</strong><br/>';.
I think it will be much easier for you to use SwiftMailer or PHPMailer
They both have a really easy to use API for sending emails using SMTP or php mail() function.
best of luck.
As mentioned by Brian Ray you should create a variable containing the message text that is later being sent using the mail() function. Depending on your server setup you may retrieve the content of the output buffer (things you have echo'd out before) and instead of sending it to the browser load it into a variable. Here's a sample how this could be achieved:
ob_start(); // enable output buffering
ob_clean(); // if content has been buffered before, discard it
// this would contain your echo() statements
echo(...);
...
// load the data from the output buffer into a variable
$message= ob_get_contents();
ob_clean(); // remove the buffered contents from the output buffer
// send the mail:
// PLEASE add security measures to avoid being used as spambot; I would strongly
// recommend to not allow any user input for the $recipient variable or
// additional header variable (if applicable)
mail($recipient, $subject, $message);
Things to keep in mind: output buffering is not always available and the output buffer differs from server to server. If the buffer limit is reached, the server will automatically flush the data (=send it to the browser), in that case you will find no or truncated data inside the output buffer. The method is OK in cases you are in full control of your server, do not allow direct access to the mail routine and can make sure that the buffer is sufficiently sized to contain the generated output.
Some additional reading on output control and ob_get_contents.
In several Delphi XE2 projects, I have set up Eurekalog to send bug reports via "HTTP upload" which works well, as I use a PHP script to catch the bug report, save it in a directory and send it to me via email:
<?php
require 'PHPMailerAutoload.php';
foreach ($_FILES as $key => $value)
{
$uploaded_file = $_FILES[$key]['tmp_name'];
$server_dir = 'upload/';
$server_file = $server_dir . date("Y-m-d H-i-s ") . basename($_FILES[$key]['name']);
$ext = strtoupper(pathinfo($server_file, PATHINFO_EXTENSION));
if ($ext != 'EL')
{
continue;
}
if (move_uploaded_file($uploaded_file, $server_file))
{
echo '<html>';
echo '<head>';
echo '<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="TEXT/HTML; CHARSET=UTF-8">';
echo '<title>Bug submission</title>';
echo '</head>';
echo '<body>';
echo 'Thank you!<br />';
echo "<!--\n";
echo "<EurekaLogReply>Thank you for your feedback!</EurekaLogReply>\n";
echo "-->";
echo '</body>';
echo '</html>';
SendBugReportMessage('auserofmyprogram#usersofmyprogram.com',
'A User of my program',
'Eurekalog Bug Report',
'This is a bug report from Eurekalog.',
'eurekalog.bugreport#mysite.com',
$server_file,
basename($server_file)
);
}
}
function SendBugReportMessage($AFrom, $AFromName, $ASubject, $ABodyText, $ARecipient, $AFileToAttach, $ANameOfFile)
{
$email = new PHPMailer();
$email->From = $AFrom;
$email->FromName = $AFromName;
$email->Subject = $ASubject;
$email->Body = $ABodyText;
$email->AddAddress($ARecipient);
$file_to_attach = $AFileToAttach;
$email->AddAttachment($file_to_attach, $ANameOfFile);
return $email->Send();
}
?>
Now I have several programs using this very same PHP script to upload their bug reports. However, the bug report sent to this PHP script has always the name "BugReport". So, in the PHP script how can I get the name of the program which sent the bug report, so I can save it by attaching the program name and include the program name in the mail subject? Or could there be a solution by implementing something on the side of the Delphi code? Or in Eurekalog?
Eurekalog version is 7.1.0.0
You can use web-fields for that. EurekaLog has OnCustomWebFieldsRequest event handler, which allow you to alter web-fields for any web-based send method (such as HTTP upload, bug trackers with HTTP API, etc.).
Assign such event hanlder:
uses
EEvents;
procedure AddApplicationName(const ACustom: Pointer; ASender: TObject { TELWebSender }; AWebFields: TStrings; var ACallNextHandler: Boolean);
begin
AWebFields.Values['Application'] := AnsiLowerCase(ExtractFileName(ParamStr(0)));
end;
initialization
RegisterEventCustomWebFieldsRequest(nil, AddApplicationName);
end.
Then, you can access your new "Application" field from your script. For PHP it will be $_REQUEST["Application"] or $_POST["Application"]
For this particular task you can also use OnCustomFileName event handler to alter file name used for sending. You are interested in AFileType = ftZIP (if you are going to send packed .elp report) or AFileType = ftBugReport (if you are going to send unpacked .el report).
I'm trying to parse emails sent to "parsethis#mysite.com" with PHP (I will use a cronjob, but for now I am just hitting mysite.com/cronJobs/parseMail in my browser).
This is my first time trying to parse emails .. so I'm just not sure how to go about troubleshooting this at all.
Here is the code I'm using, found it on a site and it seemed to be something I can work from. (Yes I have replaced all the placeholders)
$mailbox = imap_open("{mysite.com:143/notls}INBOX", "parsethis#mysite.com", "123password"); //connects to mailbox on your server
if ($mailbox == false) {
echo "<p>Error: Can't open mailbox!</p>";
echo imap_last_error();
}else{
//Check number of messages
$num = imap_num_msg($mailbox);
//if there is a message in your inbox
if( $num > 0 ) { //this just reads the most recent email. In order to go through all the emails, you'll have to loop through the number of messages
$email = imap_fetchheader($mailbox, $num); //get email header
$lines = explode("\n", $email);
// data we are looking for
$from = "";
$subject = "";
$to = "";
$headers = "";
$splittingheaders = true;
for ($i=0; $i < count($lines); $i++) {
if ($splittingheaders) {
// this is a header
$headers .= $lines[$i]."\n";
// look out for special headers
if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) {
$subject = $matches[1];
}
if (preg_match("/^From: (.*)/", $lines[$i], $matches)) {
$from = $matches[1];
}
if (preg_match("/^To: (.*)/", $lines[$i], $matches)) {
$to = $matches[1];
}
}
}
//We can just display the relevant information in our browser, like below or write some method, that will put that information in a database
echo "FROM: ".$from."<br>";
echo "TO: ".$to."<br>";
echo "SUBJECT: ".$subject."<br>";
echo "BODY: ".imap_qprint(imap_body($mailbox, $num));
//delete message
// imap_delete($mailbox,$num); // not while testing
// imap_expunge($mailbox); // not while testing
}else{
// echo "No more messages";
}
imap_close($mailbox);
}
Problem is : I get this when I hit it
FROM: "K.K.Smith"
TO: parsethis#mysite.com
SUBJECT: test subject
BODY: --50f9f846_140e0f76_3df1 Content-Type: // etc .. with the body of the email unformatted in a continuous string
// INTERESTING > I get the body twice .. doubled.. once as a long unformatted string, and then again with formatting
--50f9f846_140e0f76_3df1 Content-Type: text/html; // etc.. the rest of the body with formatting .. ie my signature is correctly formatted with spacing and line breaks unlike the first body output
/// ***and then this weird error at the end***
--50f9f846_140e0f76_3df1--
Fatal error: Exception thrown without a stack frame in Unknown on line 0
So I don't know what that means. I have googled and all results seem to indicate it is a "mysterious error". It looks like it is about to output the body for a third time (I don't really know what that weird string is.. an email id maybe?) .. but then it chokes where it didn't choke the two previous times.
.. can anyone give any ideas how I should move forward?
EDIT
so I reduced the parseMail function to just the minimum..
public function parseMail(){
$mailbox = imap_open("{mysite.com:143/notls}INBOX", "parsethis#mysite.com", "123password"); //connects to mailbox on your server
imap_close($mailbox);
}
and I still get the error when I hit it. Ideas?
SOLVED
It looks like it has something to do with Codeigniter interpreting errors/warnings thrown by the IMAP functions as exceptions.
My solution was to put this after my imap_close() function
imap_errors();
This got rid of the error notice for me.
Here is where i found my solution on the Kohana discussion board
I am writing a PHP script that will send via a cron an email every night. In this script, I have multiple functions which output particular text. I am then trying to send the contents of those functions in the email. For some reason the email is going through fine, but the body of the content is showing up empty. If there's a better way to do this, by all means I'm open to it.
function function1() {
global $new;
echo "<p>";
while ($row = mysql_fetch_array($query)) $content = $row["COUNT(column1)"];
if ($content != 0) echo "output1";
else echo "output2";
echo "</p>";
}
$emailMessage = function1().function2().function3();
if ($_GET['version'] == "email") {
mail ($emailTo, $emailSubject, stripslashes($emailMessage));
}
else echo $emailMessage;
Obviously the code is obfuscated a bit, but the general outline is there.
echo sends the output to the standard out, it doesn't return it from the function. Try this.
ob_start()
// run function contents, including echo
var message = ob_get_clean();
return message;
This will capture what you echo into the buffer, prevent the buffer from being sent, and then reading the buffer into a variable. It will then empty the buffer ready for next time.
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();
}