解决Hashover无法发送邮件提醒问题

前因

  前几天刚刚完成VPS的搬家,虽然大部分功能都恢复了,但是唯独评论系统无法发送邮件提醒的问题还是没能解决。经过各种各样的尝试终于最终解决了,中间虽然做了很多不成功的尝试,比较曲折,但还是挺攒经验的。所以记录下来给以后提供依据。

配置Postfix进行Sendmail测试

  在之前的VPS中,直接安装配置完Postfix之后,基本上就能够正常发送相关邮件了,但是这次安装配置完Postfix,还是不正常。

  安装配置过程不表,主要是留意一下域名配置,要增加127.0.0.1的本地回环域名解析到hosts文件内就行。完成配置后用邮件发送命令测试:

1
2
3
4
5
6
sendmail -t <<EOF
From: noreply@candura.us
To: candura@foxmail.com
Subject: Sendmail Test
Hello! This is a sendmail Test
EOF

  然后成功收到邮件,排除sendmail配置问题。

PHP调用mail()函数测试

  系统的sendmail正常之后,就开始测试PHP下面相关函数了。

  首先修改一下php.ini配置文件,找到

1
;sendmail_path = "sendmail -t -i"

  把这个配置的注释删掉,并且写上sendmail的完整路径。

1
sendmail_path = "/usr/sbin/sendmail -t -i"

  然后写了一个简单的PHP页面来测试一下。

1
2
3
4
5
6
7
<?php
$to = "candura@foxmail.com";
$subject = "PHP mail Test";
$message = "Hello! This is a php email test";
$headers .= "From: noreply@candura.us";
mail($to,$subject,$message,$headers);
?>

  也能成功收到邮件,排除PHP的配置及相关权限设置问题。

回滚Hashover版本

  由于此前搬家时好不容易才让评论系统正常显示,不想退回去使用hashover的1.0版本,于是在疆飞的建议下试试他使用的老版本。

  他使用的版本是hashover-next中较早的版本,根据文件时间判断他使用的是2018年8月份的的版本。在查询hashover-nextcommits记录中发现,那个时间段开始新增SMTP支持,猜想是不是这个SMTP支持导致原来的sendmail失效。

  于是采用git reset --hard cb4de3d002f52730cd30aa05c7bfe771e5f70500命令回滚到支持SMTP之前的版本。

  结果还是失败了。后续由往后测试了几个版本,都以失败告终。

偷懒带来的柳暗花明

  后面随着不断的翻滚版本,渐渐想偷懒了,于是也懒得调整主题、语言、登录设置这些东西了,直接默认装上去在secret.php文件里改好必须的配置就直接测试,没想到反而成功收到了邮件提醒。

  伴随着这一小阵成功的曙光,开始逐个排查是哪个选项造成无法发送,排查到最后发现,当把语言设置成中文的时候就无法发送邮件通知,改回英文就正常。

  于是开始重点检查语言设置,发现采用中、日、韩这些双字节文字的语言就无法触发邮件通知,采用英、法、西这些语言就能够正常接收邮件通知。

  这下基本上就可以判断是跟语言有关了,接下来就得排查到底是PHP的相关支持的原因还是系统语言包支持的原因了。

重新进行PHP测试

  经此想起之前测试因为懒得切换输入法,都是直接用英文测试,这回改成用中文测试。

1
2
3
4
5
6
7
<?php
$to = "candura@foxmail.com";
$subject = "中文邮件";
$message = "中文邮件测试";
$headers .= "From: noreply@candura.us";
mail($to,$subject,$message,$headers);
?>

  果然就无法触发邮件了,再分别测试了下面两个PHP。

1
2
3
4
5
6
7
<?php
$to = "candura@foxmail.com";
$subject = "中文邮件";
$message = "Hello! This is a php email test";
$headers .= "From: noreply@candura.us";
mail($to,$subject,$message,$headers);
?>
1
2
3
4
5
6
7
<?php
$to = "candura@foxmail.com";
$subject = "PHP mail Test";
$message = "中文邮件测试";
$headers .= "From: noreply@candura.us";
mail($to,$subject,$message,$headers);
?>

  对比发现邮件内容是中文并不影响邮件发送,而一旦邮件标题是中文的时候就没办法发送了。

重新进行Sendmail测试

  随后继续在命令行下采用Sendmail命令测试。

1
2
3
4
5
6
sendmail -t <<EOF
From: noreply@candura.us
To: candura@foxmail.com
Subject: 中文标题测试
Hello! This is a sendmail Test
EOF

  果然不行,于是基本上可以把问题原因锁定在中文邮件标题上了。

临时方案测试成功

  随着在网上一阵 Google,发现大部分人都遇到了Subject参数是中文导致的邮件乱码问题,但是都没有说发送不了。我猜测可能邮件也发出了,但是由于标题是乱码被发送出口或者邮箱接受口那里直接屏蔽掉了。所以相应的解决方案应该是通用的。

  解决方案是把Subject里面的中文标题用Base64加密成字符串,并在文件头中写上解码信息。

  把PHP的测试文件改成下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$to = "candura@foxmail.com";
$subject = "中文标题测试";
$message = "内容是中文就可以正常发送邮件";

$headers = "MIME-Version: 1.0";
$headers .= "From: noreply@candura.us";
$headers .= "Content-Type: text/plain; charset=\"UTF-8\"";

$subject = "=?UTF-8?B?".base64_encode($subject)."?=";
mail($to,$subject,$message,$headers);
?>

  然后访问这个PHP文件执行,成功收到了中文标题的邮件,看来这个方法果然可行。

修改Hashover源码解决问题

  通过分析hashover的源代码,邮件提醒的内容部分主要是在writecomments.php文件中,最终通过调用sendmail.php里面的send()函数发出。那么主需要把关键的$subject = "=?UTF-8?B?".base64_encode($subject)."?=";语句增加进去就行了。

  最终需要修改的是sendmail.php里面的倒数第三行,在调用mail()函数之前,把标题内容改进进去。

1
2
3
4
5
// Send mail
// 改变标题格式
$this->subject = "=?UTF-8?B?".base64_encode($this->subject)."?=";
// 发出邮件
mail ($this->to, $this->subject, $message, $headers);

  经过这样修改完再进行几次测试,分别切换了不同语言,把邮件内容分别设置成HTMLTEXT模式,均能正常发出邮件提醒,算是解决了问题!

后记

  虽然这个问题最终通过修改hashover的源码来解决了,但是感觉并没有触碰到问题的实质。我之前的VPS是Ubuntu系统,现在这个是Debian,后来在其他的CentOS、Ubuntu系统的主机上搭建测试,发现不用修改也不存在这样的问题。所以到底后面是因为什么原因造成的这个情况,我也不得而知了。

文章目录
  1. 1. 前因
  2. 2. 配置Postfix进行Sendmail测试
  3. 3. PHP调用mail()函数测试
  4. 4. 回滚Hashover版本
  5. 5. 偷懒带来的柳暗花明
  6. 6. 重新进行PHP测试
  7. 7. 重新进行Sendmail测试
  8. 8. 临时方案测试成功
  9. 9. 修改Hashover源码解决问题
  10. 10. 后记
|