I have a question about the wp_mail() function. Right now I’m having the following button to send e-mail with:
echo '<input type="submit" name="send_button" value="verzenden" id="'.$post_id.'" class="send_post">';
which triggers a jQuery request:
jQuery(document).ready(function() {
jQuery(".send_post").click(function() {
var post_id = $(this).attr('id');
jQuery.ajax({
async: false,
type: 'get',
url: nieuwsbrief.sendmail_url,
data: 'postid=' + post_id,
success: function(data) {
alert(data);
return false;
}
});
});
});
jQuery sends the request to sendmail.php
. Which includes the following:
<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/www/wordpress/wp-config.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/www/wordpress/wp-load.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/www/wordpress/wp-includes/wp-db.php';
global $wpdb;
$subscribers = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM
wp_nwsbrf_subscribers
INNER JOIN
wp_nwsbrf_couple
INNER JOIN
wp_nwsbrf_categories
INNER JOIN
wp_posts
WHERE
wp_nwsbrf_subscribers.category_id = wp_nwsbrf_categories.category_id
AND
wp_nwsbrf_couple.category_id = wp_nwsbrf_categories.category_id
AND
wp_nwsbrf_subscribers.category_id = wp_nwsbrf_couple.category_id
AND
wp_posts.ID = wp_nwsbrf_couple.ID
AND
wp_nwsbrf_couple.ID = %d", $_GET['postid']) );
foreach ($subscribers as $subscriber) {
$to = $subscriber->subscriber_mail.",";
$title = $subscriber->post_title;
$message = $subscriber->post_content;
wp_mail($to, $title, $message);
}
?>
As you can see, the mail has to be sent in sendmail.php
(url: nieuwsbrief.sendmail_url
). But when I click on the send_button it takes minutes (3 or 4) to send the e-mail!? What am I doing wrong here?
Thanks for helping me out!
Many, many things, not all performance related. Lets begin with the critical parts, then conclude on your performance issues and what can be done to mitigate and help
AJAX API
Firstly, you’re not using the AJAX API, and reinventing the wheel. It’s quite simple:
JS:
PHP:
Closing PHP Tag and Trailing Space
PHP can be used as a scripting language, but you’ve veered into app development, so I’d recommend not having a closing PHP tag at the end of the document. Your code snippet above does this and it has a new line break space afterwards, which can cause issues.
Security
It would appear that although you’re running a prepare statement, not once are you checking if the user is actually allowed to do this.
E.g. I can flood all your subscribers, and bring down your server with the following javascript snippet:
You don’t check that:
Performance
Your performance woes are a result of what you’re doing. Namely:
Both are inherently expensive, and the last one you’re doing a lot of. Emails themselves are costly to send server-wise, as it has to contact the SMTP server, and negotiate, and any remote requests are going to take time.
There is little you can do to avoid this expense, as the core parts that make this up are inherently expensive.
But that’s okay. You aren’t the first person to have to do something expensive, so your goal should be mitigation and redesign. You cant reduce the cost of the process, but you can modify the process so that it appears fast for the UI, and still gets done. Banks solved this in the early days by doing their hard number crunching overnight while the branch was closed in batch runs.
Here are some ways of mitigating it:
Data Note
That you need an SQL statement like that makes me wonder if your categories table and query cant be replaced with a custom taxonomy and a call to
WP_Query
. This way you could take advantage of the built in object and query cachingIn my case wp_mail() took over 90 seconds per email on form submits, bringing my site to a crawl. Totally forgot to correct the /etc/hosts config for my site, per the instructions below, now sendmail is < 3 seconds.
https://www.digitalocean.com/community/questions/sendmail-is-slow-to-send-mail
If you check your /var/log/mail.log you will probably find something like this: My unqualified host name (localhost) unknown; sleeping for retry. This is because sendmail requires “hostname” to be a fully qualified domain name. update your “/etc/hosts” file: nano /etc/hosts to look like this: 127.0.0.1 localhost.localdomain localhost yourhostname boom, fast sendmail.