I am using EFUMultiple Uploader to receive files on my site. Does anyone know of a tutorial that will teach me how I can be notified each time there is a new file or batch of files in my uploads folder?
It will become annoying, fast, I can promise you that.
But either way, in your upload script, you'll want to use either the mail() function or, for example the PHPMailer library if you don't have a SMTP server configured on your PHP installation.
Consider this (untested) script:
#!/usr/bin/env php
<?php
// Warning: this script and UPLOADED_FILES_DB, for security reasons, should not be in UPLOAD_PATH.
define('UPLOAD_PATH', '...');
define('UPLOADED_FILES_DB', 'uploaded_files');
define('MAIL_TO', 'you#example.com');
define('MAIL_FROM', 'cron#example.com');
define('MAIL_SUBJECT', 'Uploaded files');
// Get old files:
if (file_exists(UPLOADED_FILES_DB)) {
$old_files = unserialize(file_get_contents(UPLOADED_FILES_DB));
} else {
$old_files = array();
}
// Get current files:
$current_files = array();
foreach (new DirectoryIterator(UPLOAD_PATH) as $file_info) {
if (!$file_info->isDot()) {
$current_files[$file_info->getFilename()] = filemtime($file_info->getFilename());
}
}
// Update database:
file_put_contents(serialize($current_files), UPLOADED_FILES_DB);
// Compute differences:
$added_files = array_diff(array_keys($old_files), array_keys($current_files));
$removed_files = array_diff(array_keys($current_files), array_keys($old_files));
$changed_files = array_diff_assoc($old_files, $current_files);
// Send message:
$headers = 'From: ' . MAIL_FROM . "\r\n";
$message = 'Added files: ' . implode(', ', $added_files);
mail($to, $subject, $message, $headers);
Then you would put that script on a cron job to execute every day or so, or you can include it in wherever your upload code is — though, the latter approach would get annoying quickly.
Related
It is 1 AM and I am struggling for 3-4 hours to see what's wrong with my script...
My database has ~400 emails. I set $ChunkSize as counter for the loop and also to count which is the next chunk to be processed.
I've set some echo() to debug
echo "This is the " . $GLOBALS["ChunkSize"] . " chunk. <br>";
It should output what chunk is processed at that time.
If I disable mail() then I don't get 503 Service Unavailable but every echo() displays at the same time, not in the order of processing.
I also found out that some emails arrive, but not to everyone. Also, if some emails are sent, that means foreach() should have processed at least one chunk, that means it should display at least one echo().
I've set break 1; so every time it breaks out of foreach() it should display the echo() with the chunk number processed by foreach() but it doesn't.
What I am doing wrong?
$connection = mysql_connect($hostname, $username, $password);
mysql_select_db($dbname, $connection);
$result = mysql_query("SHOW COLUMNS FROM `Emails`");
while($row = mysql_fetch_array($result)){
$Addresses[] = $row['Field'];}
$Subject = "Test";
$Message = "
Test
";
$Headers = array( EMPTY FOR SECURITY REASONS );
$Headers = implode( "\r\n" , $Headers );
$ChunkAddresses = 50;
$EmailChunkArray = array_chunk($Addresses, $ChunkAddresses);
$ArraySize = count ($EmailChunkArray);
$ChunkSize = 0;
ChunkLoop: {
$EmailChunkArrayLoop = $GLOBALS["EmailChunkArray"];
foreach ($EmailChunkArrayLoop[$GLOBALS["ChunkSize"]] as $ToChunkLoop) {
if ($GLOBALS["ChunkSize"] <= $GLOBALS["ArraySize"]) {
mail($ToChunkLoop,$GLOBALS["Subject"],$GLOBALS["Message"],$GLOBALS["Headers"]);
echo "This is the " . $GLOBALS["ChunkSize"] . " chunk. <br>";
} else if ($GLOBALS["ChunkSize"] == $GLOBALS["ArraySize"]){
exit();}
$GLOBALS["ChunkSize"]++;
break 1;}
}
if ($GLOBALS["ChunkSize"] != $GLOBALS["ArraySize"]){
echo "Test. <br>";
goto ChunkLoop;
} else {
echo "Finished! <br>";}
Create script that will only do one thing - send mail.
sendMail.php
<?php
// Get recipient from the argv array
$recipient = $_SERVER['argv'][1];
// Mail args
$subject = 'HELLOOOOOOO';
$message = 'BLablabla';
$headers = [...]; // optional or not
// Send it
mail($recipient, $subject, $message, $headers);
And inside of Your code where You do:
mail($ToChunkLoop,$GLOBALS["Subject"],$GLOBALS["Message"],$GLOBALS["Headers"]);
Replace with:
$recipient = escapeshellarg($ToChunkLoop);
exec("php /path/to/sendMail.php ".$recipient." > /dev/null &"); // that will call mail script and will not wait when execution will end
Feel free to adapt my code examples as You wish
P.S. this solution is for cases when You don't want to pay for normal batch mail sending, mail subscription or dedicated, vps services and have just small web hosting. (:
P.S.. it's not a brilliant solution, but done for requirements provided by question author
I have the following cod which basically sends a message with some user data from MySQL. Now the thing is the email in question gets sent sometimes but not if I need to resend it. Here is the code:
<?php
//including the database connection file
include("config.php");
//getting id of the data from url
$id = $_GET['id'];
//fetching data in descending order (lastest entry first)
$result = mysql_query("SELECT * FROM my_table_name Where id='$id'");
if($res = mysql_fetch_array($result)) {
$name = $res['name'];
$email = $res['email'];
$date = $res['date'];
if(empty($id)) {
echo "<font color='red'>Error: Did not send.</font><br/>";
} else {
// The message
$message = "Hi $name,\r\n\r\nThis email is to inform you that your
\r\n\r\nRegards, \r\n Me.";
$headers = 'From: no-reply#mydomain.org' . "\r\n" .
'Reply-To: no-reply#mydomain.org' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$Subject = 'Hello';
// Send
mail($email, $Subject, $message, $headers);
//display success message
echo "<font color='green'>Email sent successfully to $name.</font><br/>";
echo "<br/><a href='index.php' class='button button1 link'>Go Back to Overview</a>";
}
}
?>
Any help is greatly appreciated.
If I understood your question correctly and it was about mail function call failing sometimes:
You can add retry logic to your mail call:
$triesLeft = 5;
while ($triesLeft > 0) {
$rc = mail(...);
if ($rc === true) {
break;
}
sleep(1); // Space to improve here - see exponential backoff, for instance
$triesLeft -= 1;
}
if ($triesLeft === 0) {
// Log critical error
}
But this might and will introduce delays in your response time, and in some cases client will even get a timeout.
So usually the solution to this problem is not to send the email right away, but to quickly put it in any kind of queue (even simple db table will suffice), and then make another worker script that will send all that is unsent.
You can move this retry logic to this worker script and sleep all you want, it won't block client.
The only "downsides" to this solution is that:
You will not be able to show result of mail call to your client (which is useless anyway since it means only that is was "accepted for delivery", not actually delivered), and
You'll have a bit more moving parts and you'll have to write a bit more code. But it's either that or accepting that some of your mail calls will fail.
An outline of a solution might be:
form.php (gets called when customer submits form):
get request parameters
form email subject, body from request parameters
save email to db with status = unsent
worker.php (should be always running in an infinite loop or something like that in background on server):
get unsent email from db
try to send it, retrying if needed
if sent successfully - mark email as sent
if failed to send - mark email an failed, log critical error, mitigate manually
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 have a page that determines the variable ISSET and then acts on instructions. For example if the isset contains 'print' it loads a file via Include Template Path and echos a code on the bottom that prints the window.
eg.
if (isset($_GET['quoteprint'])) {
include(TEMPLATEPATH . '/bookings/booking-quote.php');
echo'<script type="text/javascript">window.print()</script>';
}
Now I would like a similar function to exist but this time to email the contents of that page to the user. I tired this but it does not work. I think the content needs to be converted but I don't know where to start.
else if (isset($_GET['quoteemail'])) {
$emailer = include(TEMPLATEPATH . '/bookings/booking-quote.php');
$to = $current_user->user_email;
$subject = "Your Quote - Dive The Gap" ;
$message = $emailer;
$headers = "From: Dive The Gap Bookings <ask#divethegap.com>" . "\r\n" .
"Content-type: text/html" . "\r\n";
mail($to, $subject, $message, $headers);
}
Any ideas?
Marvellous
The include function does not return the output or content of the script you're including.
See http://php.net/manual/en/function.include.php for more info (example #4 might be interesting for you).
You need to get the entire content of the page, or the part(s) you'd like to e-mail, into a variable. One way of doing this is using PHP's output buffering. A good explanation of how output buffering works can be found here: http://www.codewalkers.com/c/a/Miscellaneous/PHP-Output-Buffering/
I've recently posted here accessing $_SESSION when using file_get_contents in PHP about a problem I was having and the general consensus is that I'm not doing it right... while I generally think "as long as it works..." I thought I'd get some feedback on how I could do it better...
I was to send the exact same email in the exact same format from multiple different areas.
When a job is entered (automatically as a part of the POST)
Manually when reviewing jobs to re-assign to another installer
The original script is a php page which is called using AJAX to send the work order request - this worked by simply calling a standard php page, returning the success or error message and then displaying within the calling page.
Now I have tried to use the same page within the automated job entry so it accepts the job via a form, logs it and mails it.
My problem is (as you can see from the original post) the function file_get_contents() is not good for this cause in the automated script...
My problem is that from an AJAX call I need to do things like include the database connection initialiser, start the session and do whatever else needs to be done in a standalone page... Some or all of these are not required if it is an include so it makes the file only good for one purpose...
How do I make the file good for both purposes? I guess I'm looking for recommendations for the best file layout and structure to cater for both scenarios...
The current file looks like:
<?php
session_start();
$order_id = $_GET['order_id'];
include('include/database.php');
function getLineItems($order_id) {
$query = mysql_query("SELECT ...lineItems...");
//Print rows with data
while($row = mysql_fetch_object($query)) {
$lineItems .= '...Build Line Item String...';
}
return $lineItems;
}
function send_email($order_id) {
//Get data for current job to display
$query = mysql_query("SELECT ...Job Details...");
$row = mysql_fetch_object($query);
$subject = 'Work Order Request';
$email_message = '...Build Email...
...Include Job Details...
'.getLineItems($order_id).'
...Finish Email...';
$headers = '...Create Email Headers...';
if (mail($row->primary_email, $subject, $email_message, $headers)) {
$query = mysql_query("...log successful send...");
if (mysql_error()!="") {
$message .= '...display mysqlerror()..';
}
$message .= '...create success message...';
} else {
$query = mysql_query("...log failed send...");
if (mysql_error()!="") {
$message .= '...display mysqlerror()..';
}
$message .= '...create failed message...';
}
return $message;
} // END send_email() function
//Check supplier info
$query = mysql_query("...get suppliers info attached to order_id...");
if (mysql_num_rows($query) > 0) {
while($row = mysql_fetch_object($query)) {
if ($row->primary_email=="") {
$message .= '...no email message...';
} else if ($row->notification_email=="") {
$message .= '...no notifications message...';
} else {
$message .= send_email($order_id);
}
}
} else {
$message .= '...no supplier matched message...';
}
print $message;
?>
make a function and include it
Do separate functions. Authentication (which requires sessions) from mail sending (which don't)
Then include mail sending function into both tasks.