首先装上sendmail, mail套件:
sudo apt-get install sendmail mailutils -y
然后使用命令行发送邮件:
echo “邮件正文” | mail -s 邮件主题 xxxxxxx@qq.com
在 bwh 主机一切正常, 但是我的电脑死活发不出去, 这是为什么呢?
难道一定要有外网IP? 或者我的IP被 qq mail server 封杀?
离线
查看发送日志 /var/log/mail.log
$ cat /var/log/mail.log
Apr 21 09:07:34 ubuntu sendmail[62831]: 03L17YMG062831: from=yyyy@yyyy.cn, size=100, class=0, nrcpts=1, msgid=<202004210107.03L17YMG062831@yyyy.cn>, relay=yyyy@localhost
Apr 21 09:07:34 ubuntu sm-mta[62832]: 03L17YDB062832: from=<yyyy@yyyy.cn>, size=345, class=0, nrcpts=1, msgid=<202004210107.03L17YMG062831@yyyy.cn>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
Apr 21 09:07:34 ubuntu sendmail[62831]: 03L17YMG062831: to=<xxxx@qq.com>, ctladdr=yyyy@yyyy.cn (1000/1000), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30100, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (03L17YDB062832 Message accepted for delivery)
Apr 21 09:07:39 ubuntu sm-mta[62834]: STARTTLS=client, relay=mx3.qq.com., version=TLSv1.2, verify=FAIL, cipher=ECDHE-RSA-AES128-GCM-SHA256, bits=128/128
Apr 21 09:07:39 ubuntu sm-mta[62834]: 03L17YDB062832: to=<xxxx@qq.com>, ctladdr=<yyyy@yyyy.cn> (1000/1000), delay=00:00:05, xdelay=00:00:05, mailer=esmtp, pri=120345, relay=mx3.qq.com. [183.232.93.177], dsn=5.0.0, stat=Service unavailable###4秒后出现这个 DSN: Service unavailable ###
Apr 21 09:07:39 ubuntu sm-mta[62834]: 03L17YDB062832: 03L17dDB062834: DSN: Service unavailable
Apr 21 09:07:39 ubuntu sm-mta[62834]: 03L17dDB062834: to=<yyyy@yyyy.cn>, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=30000, dsn=2.0.0, stat=Sent
###4秒后出现这个 DSN: Service unavailable ###
离线
根据DSN: Service unavailable关键字,搜到这个:
https://www.centos.bz/2012/06/dsn-service-unavailable/
自从换了vps,博客的评论邮件提醒功能一直有问题,今天有空,我们来解决它。
无法发送邮件的日志如下:Jun 26 07:24:23 MyVPS1976 sendmail[31760]: q5PNOMeP031760: from=<www@MyVPS1976>, size=1393, class=0, nrcpts=1, msgid=<101f67a320c3f53ec88cb43d5c74631f@www.centos.bz>, proto=SMTP, daemon=MTA, relay=MyVPS [127.0.0.1]
Jun 26 07:24:25 MyVPS1976 sendmail[31762]: q5PNOMeP031760: to=<admin@centos.bz>, ctladdr=<www@MyVPS1976> (501/501), delay=00:00:02, xdelay=00:00:02, mailer=esmtp, pri=121393, relay=mxdomain.qq.com. [64.71.138.90], dsn=5.0.0,stat=Service unavailable
Jun 26 07:24:25 MyVPS1976 sendmail[31762]: q5PNOMeP031760: q5PNOPeP031762: DSN: Service unavailable
Jun 26 07:24:25 MyVPS1976 sendmail[31762]: q5PNOPeP031762: to=root, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=32578, dsn=2.0.0, stat=Sent
根据relay=mxdomain.qq.com. [64.71.138.90], dsn=5.0.0,stat=Service unavailable这一段,我们知道邮件已经发送出去,但由于某种原因邮件被拒绝,于是更换hostname,重启sendmail,解决问题。
更换hostname方法:
1、编辑/etc/sysconfig/network,更换文件中的hostnmae。
2、把hostname写入/etc/hosts
3、执行hostname www.centos.bz立即生效
1 在我的ubuntu18.04没找到, 2,3都做了,然而还是没x用。
离线
bwh的日志:
# cat /var/log/mail.log
Apr 21 09:19:13 LLLLLL sendmail[25209]: 03L1JD4o025209: from=root, size=247, class=0, nrcpts=1, msgid=<202004210119.03L1JD4o025209@LLLLLL.com>, relay=root@localhost
Apr 21 09:19:13 LLLLLL sm-mta[25210]: 03L1JD34025210: from=<root@LLLLLL.com>, size=481, class=0, nrcpts=1, msgid=<202004210119.03L1JD4o025209@LLLLLL.com>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
Apr 21 09:19:13 LLLLLL sendmail[25209]: 03L1JD4o025209: to=xxxx@qq.com, ctladdr=root (0/0), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30247, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (03L1JD34025210 Message accepted for delivery)
Apr 21 09:19:14 LLLLLL sm-mta[25212]: STARTTLS=client, relay=mx3.qq.com., version=TLSv1/SSLv3, verify=FAIL, cipher=ECDHE-RSA-AES128-GCM-SHA256, bits=128/128
Apr 21 09:19:16 LLLLLL sm-mta[25212]: 03L1JD34025210: to=<xxxx@qq.com>, ctladdr=<root@LLLLLL.com> (0/0), delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=120481, relay=mx3.qq.com. [203.205.219.57], dsn=2.0.0, stat=Sent (Ok: queued as )
这个日志是正常的: dsn=2.0.0, stat=Sent
相当于 http 的 200 OK 状态, 已妥投的意思吧。
离线
实在折腾不出来,感觉很可能IP被 smtp服务器封杀,
实在不行只能用 php 脚本编程 调用 fsockopen 搞定邮件发送了:
https://schoudhury.com/blog/articles/send-email-using-gmail-from-php-with-fsockopen/
离线
实在折腾不出来,感觉很可能IP被 smtp服务器封杀,
实在不行只能用 php 脚本编程 调用 fsockopen 搞定邮件发送了:
https://schoudhury.com/blog/articles/send-email-using-gmail-from-php-with-fsockopen/
终于用上面的搞定, php fsockopen 连接 smtp.qq.com 或者 smtp.163.com 的 465 端口,
然后用交互式命令登录并发送邮件即可,
发完之后会出现在你qq/163邮箱的发件箱里面。
离线
前面那个 demo 不支持发送附件, 又找到了一个支持发送附件的代码:
http://www.nomadcf.com/scripting/phpsocketssendauthemailgmail
function SendMail($ServerName, $Port, $Username, $Password, $ToEmail, $FromEmail, $Subject, $Body, $Attachments='' ) {
/* Attachments work like this array('Attachment Name'=>'ATTACHMENT AS A STRING','Next Attachment Name'=>'ATTACHMENT 2 AS A STRING') */
$smtp = fsockopen($ServerName, $Port);
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 220;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed Connect";
fputs($smtp, "HELO $ServerName\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 250;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed Helo";
fputs($smtp, "AUTH LOGIN\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 334;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed AUTH";
fputs($smtp, base64_encode($Username)."\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 334;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed Username";
fputs($smtp, base64_encode($Password)."\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 235;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed Password";
fputs($smtp, "MAIL From:<$FromEmail>\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 250;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed MAIL";
fputs($smtp, "RCPT To:<$ToEmail>\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 250;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed RCPT";
fputs($smtp, "DATA\r\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 354;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed DATA";
fputs($smtp, "From: $FromEmail\r\n");
fputs($smtp, "To: $ToEmail\r\n");
if ($Attachments != '') {
$ContentBoundry = '----=_NextPart_'.md5(date('U').uniqid('NCF',TRUE));
fputs($smtp, "MIME-Version: 1.0\r\n");
fputs($smtp, 'Content-Type: multipart/mixed; boundary="'.$ContentBoundry.'"'."\r\n");
}
fputs($smtp, "Subject: $Subject\r\n\r\n");
if ($Attachments == '') {
fputs($smtp, "$Body\r\n.\r\n");
} else {
$NewBody = "\r\n";
$NewBody .= '--'.$ContentBoundry."\r\n";
$NewBody .= 'Content-Type: text/plain; charset="UTF-8"'."\r\n";
$NewBody .= 'Content-Transfer-Encoding: 8bit'."\r\n\r\n";
$NewBody .= $Body."\r\n";
foreach ($Attachments as $Filename => $Attachment) {
$NewBody .= '--'.$ContentBoundry."\r\n";
$NewBody .= 'Content-Type: application/octet-stream; name="'.$Filename.'"'."\r\n";
$NewBody .= 'Content-Transfer-Encoding: base64'."\r\n";
$NewBody .= 'Content-Disposition: attachment; filename="'.$Filename.'"'."\r\n\r\n";
$NewBody .= chunk_split(base64_encode($Attachment));
$NewBody .= "\r\n";
}
$NewBody .= $ContentBoundry."--\r\n\r\n";
fputs($smtp, $NewBody."\r\n.\r\n");
}
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 250;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed BODY";
fputs($smtp, "QUIT\n");
$InputBuffer = fgets($smtp, 1024);
$ErrorCode = 221;
if(substr($InputBuffer,0,3) != "$ErrorCode") return "Failed QUIT";
fclose($smtp);
return TRUE;
}
$TheAttachments = array('CurriculumReviewCycle.pdf'=>file_get_contents('/var/www/html/CurriculumReviewCycle.pdf'));
// SendMail($ServerName, $Port, $Username, $Password, $ToEmail, $FromEmail, $Subject, $Body, $Attachments='' )
SendMail('smtp.gmail.com', 25, 'franklinc@fromdomain', 'Password', 'cfranklin@todomain', 'franklinc@fromdomain', 'Attach - Test - subject', 'What up dog! - the body', $TheAttachments);
我试一试看效果如何.
离线
生命的意义在于折腾, 今天继续折腾 php 发送 email, 居然搜到一个牛逼的开源库:
https://github.com/PHPMailer/PHPMailer
首先用composer安装PHPMailer: composer require phpmailer/phpmailer
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// Load Composer's autoloader
require 'vendor/autoload.php';
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'user@example.com'; // SMTP username
$mail->Password = 'secret'; // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
//Recipients
$mail->setFrom('from@example.com', 'Mailer');
$mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient
$mail->addAddress('ellen@example.com'); // Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');
// Attachments
$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
这是测试代码, 如果用 163/qq 邮箱 465 加密端口发送,
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
这里得改成:
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
离线
https://stackoverflow.com/questions/2491475/phpmailer-character-encoding-issues
如果邮件有中文, 一定记得加下面这行代码:
$mail->CharSet = 'UTF-8';
离线
再配合 crontab 终于搞定了定时发送带附件(公司项目源码)的email 到老板邮箱:
离线