-
Bug
-
Resolution: Fixed
-
Minor
-
2.7.2, 2.7.3, 2.7.4
-
MOODLE_27_STABLE
-
MOODLE_27_STABLE
-
Since upgrading to Moodle 2.7.2 in November, our students are reporting that Forum Digests, when sent to email addresses on certain mail providers (GMail being the most notable), are being silently rejected as spam.
Steps to reproduce:
(1) using a Moodle 2.7.x account with its email set to a gmail address (or other provider with strict spam filtering), subscribe to a sufficiently busy forum.
(2) Set Forum Digest on for that forum or set Forum Digest on globally in your profile settings.
(3) Wait for Moodle to send out its scheduled Forum Digests.
(4) Check for a Forum Digest email in gmail. If the Forum Digest email is in your spam folder, check its headers - you should find that the Message-ID header contains localhost.localdomain.
Analyzing the outgoing emails, we discovered that Moodle inserts a Message-ID: header that looks like this:
<reallylonghexadecimalnumber>@localhost.localdomain
The use of localhost.localdomain in this header is a major spam red flag.
Tracing the send process, I discovered that this header is built using the phpmailer class's serverHostname() method. This attempts to determine the server's host name in this order:
(1) The object's Hostname property
(2) $_SERVER['SERVER_NAME']
(3) localhost.localdomain
When sending forum digests, this method always returns localhost.localdomain.
This is because:
- $this->Hostname is not set (and I could find nothing in Moodle that sets it!),
- Forum Digest being cron-powered, $_SERVER[] is also unset because the httpd (Apache in my case) is not in the picture. PHP is running standalone from cron.
On our Moodle instances, I have worked around this temporarily by modifying phpmailer::serverHostname() to always return the domain of our mail server (e.g. mail.royalroads.ca). This lets the forum digests through Gmail and other mail services we tested.
In lib/phpmailer/class.phpmailer.php:
// My cheesy workaround.
|
protected function serverHostname()
|
{
|
if (!empty($this->Hostname)) {
|
$result = $this->Hostname;
|
} elseif (isset($_SERVER['SERVER_NAME'])) {
|
$result = $_SERVER['SERVER_NAME'];
|
} else {
|
$result = 'localhost.localdomain';
|
}
|
// Ignore above logic and always return mail.royalroads.ca
|
$result = 'mail.royalroads.ca';
|
|
return $result;
|
}
|
I think this could be fixed by adding another Hostname source to phpmailer::serverHostname: $CFG->wwwroot.
(1) $this->Hostname
(2) $_SERVER['SERVER_NAME']
(3) parse_url($CFG->wwwroot)['host']
(4) localhost.localdomain
Proposed fix:
protected function serverHostname()
|
{
|
if (!empty($this->Hostname)) {
|
$result = $this->Hostname;
|
} elseif (isset($_SERVER['SERVER_NAME'])) {
|
$result = $_SERVER['SERVER_NAME'];
|
} elseif (isset($CFG->wwwroot)) {
|
$urlinfo = parse_url($CFG->wwwroot);
|
$result = $urlinfo['host'];
|
} else {
|
$result = 'localhost.localdomain';
|
}
|
return $result;
|
}
|