2

I got a cronjob that executes a PHP script every 5 minutes in order to send a welcome letter to new members.
My goal is to fetch the data from MySQL, pull it into an array, loop through the results and mail each result to a recipient using PHPs mail() function.
The mail() part is not working for some reason and I am 100% sure that mail()is configured and working because I can use mail() outside the foreach loop.

Example code below:

Fetch data from MySQL and store it in an array:

while ($row = $result->fetch_assoc()) {
  $tickets[] = array($row['id'], $row['namn'], $row['epost'], 
  $row['meddelande'], $row['datum']);
}

$tickets is an array.

Loop through the results and mail it:

foreach ($tickets as $ticket) {
    if (mail("mymail@example.org", "Msg from $ticket[1]", "$ticket[3]", "From: $ticket[2]")) { // Always called, but doesn't send the mail
        $query = 'UPDATE ticket SET skickat = 1 WHERE id = ?';
        if ($stmt = $db->prepare($query)) {
            $stmt->bind_param('s',$ticket[0]);
            $stmt->execute();
        } else {
            sleep(5);
            $query = 'UPDATE ticket SET skickat = 1 WHERE id = ?';
            $stmt = $db->prepare($query);
            $stmt->bind_param('s',$ticket[0]);
            $stmt->execute();
        }
    } else {
        die('The email could not be sent');
    }
}

The code works, and it updates the MySQL record to skickat = 1 so I know that the code got executed how ever, it doesn't send the mail.
I don't have access to the error.log that Apache creates and I get no errors with PHP errors turned on.

What am I missing?
I'm using Apache 2 with PHP 7

  • Why are you changing the associative arrays to numeric arrays? It makes the later code harder to read. – Barmar Nov 02 '17 at 20:09
  • Sending a mail and receiving a mail are completely different things, so the fact that you're not receiving a message doesn't mean it wasn't sent. You can only determine the difference if you have access to the logs for both the sending mail server and the receiving mail server. I'd recommend doing away with `mail()` entirely and using a mail API service like Mailgun -- it's a little more work to set up, but the benefits are definitely worth the effort. – Alex Howansky Nov 02 '17 at 20:09
  • @Barmar, I have no good answer for that. I guess it's a bad habit.
    @AlexHowansky Yeah I know and you're right. I did test `mail()` outside the foreach loop, with the same params and then it worked, on both ends. The reason why I want to use mail() for now is because i'm just testing it out.
    – Jonas Johansson Nov 02 '17 at 20:15
  • If it only fails inside the loop, it could be because of exceeding a rate limit, which makes you look like a spammer. – Barmar Nov 02 '17 at 20:19
  • Checking the mail logs would probably shed light on this. – Barmar Nov 02 '17 at 20:19
  • @Barmar Yeah it only fails inside the loop. I also tested with just one result from MySQL, (only one record had "skickat = 0") and it didn't send it either. I don't think I got access to the mail logs, I'm on a shared host. Is there another way I can find out whats going on? – Jonas Johansson Nov 02 '17 at 20:21
  • You must be giving different arguments to `mail()`, because there's no way that it can behave differently just because it's in a loop. If you can't access the mail logs directly, you need to contact tech support for the hosting service. – Barmar Nov 02 '17 at 20:23
  • Yeah I thought so aswell, so I decided to copy the `mail()` code from outside the foreach loop and pasted it in inside the foreach loop. No results. I think you are right, I do need to contact them and see whats going on – Jonas Johansson Nov 02 '17 at 20:42

1 Answers1

0

The problem you're encountering likely has to do with your hosting setup. To prevent spam, many hosting providers do not allow many emails to be sent quickly. You can likely resolve this by adding:

sleep( 5 ); // causes the script to wait for 5 seconds

after your if statement.

Ben Shoval
  • 1,732
  • 1
  • 15
  • 20
  • Yeah I thought so aswell. I tried to add `sleep(5)` after the if statement, after the MySQL query and the code gets executed, it updates all records to skickat = 1, but still doesnt send the mails. I'm so confused right now – Jonas Johansson Nov 02 '17 at 20:46
  • @JonasJohansson Are you running the script on localhost or a hosting provider? If a provider, who is it? – Ben Shoval Nov 02 '17 at 20:47