转载请注明文章出处:https://tlanyan.me/php-review...PHP评测系列目录PH??P基础web请求cookieweb响应session数据库操作加密解密Composer创建自己的Composer包发送电子邮件是网站的常见功能。用户激活、找回密码等场景,往往需要向用户邮箱发送邮件。本文首先回顾了发送邮件的相关概念,然后给出了使用PHP发送邮件的示例代码。从功能上看,短信类似于电子邮件,其目的通常是通知和安全验证。发送SMS(本质上)需要向提供商付款,因此SMS提供商有动力提供清晰的文档和易于使用的界面以便于访问。一般来说发短信的有:找供应商,比如阿里大鱼、聚合数据等;注册账号,获取appid和appkey;申请模板;查看接口文档,集成到应用程序中;调用API发送短信。过程简单易懂,接入和使用也非常方便。基本上一两个小时就可以对接测试。用户在通信过程中无需考虑消息的编码、寻址、传递等细节。缺点是他们必须付费。邮件一般是免费服务,相关支持不是很到位,这点也需要理解。各种编程语言发送邮件的类库很多,从来源上看基本上可以分为两大类:本机发送和第三方邮件服务商发送。为了理解发送邮件的过程,先介绍一些相关的概念。相关概念大多数接触互联网的人都有使用电子邮件的经历,但基本仅限于电子邮件客户端、网页和提供商的概念。作为开发人员,了解本节中的以下概念将有助于您更好地掌握电子邮件通信的细节。MUA:MailUserAgent,邮件用户代理。用户代理是开发中经常遇到的一个术语,主要是指理解人的意图并代表用户请求资源的工具。例如,浏览器是最常用的用户代理,它以HTTP/HTTPS协议格式向Web服务器发送请求,解析响应,渲染后呈现给用户。邮件用户代理是Foxmail和Outlook等常用工具。人们写完邮件后,将邮件内容封装成一种格式,与邮件服务器进行通信。MTA:MailTransferAgent,邮件传输代理,帮助用户收发邮件的程序。常说的邮件服务器指的就是MTA。开源程序有sendmail、postfix、QMail等。MRA:MailRetrievalAgent,邮件收集代理,将用户的邮件从邮件服务器上取回本地。邮件客户端是常见的MRA。SMTP:SimpleMailTransferProtocol,简单邮件传输协议。该协议用于用户、邮件服务器、邮件服务器之间相互传输邮件(默认明文,可以使用SSLTLS加密)。POP3/IMAP:PostOfficeProtocolversion3/InternetMessageAccessProtocol,邮局协议版本3或网络信息访问协议,客户端用来从服务器获取邮件的协议。用户A(163邮箱)给用户B(Gmail邮箱)发了一封信,用户B获取信件的过程涉及以上概念。流程和概念关系可以用下图表示:用户A--发送邮件-->用户BM|SM|IU|MR|MA|TA|A|P|PvvmTA(163)--转发(SMTP)->MTA(gmail)注:上图为发送邮件的大致流程。其他MSA、MDA、ESMTP、SMTPS等可能会在整个过程中出现,但不影响收发邮件的理解。下面会提到的缩写和概念都会注明,其他请自行查询。postfixLinux下发送邮件的软件主要是sendmail和postfix,在系统中充当上述概念中的MTA/MDA(MailDeliveryAgent)角色。它帮助用户发送电子邮件、接收电子邮件并将它们投递到用户邮箱(默认位置/var/spool/mail/username)。sendmail是一款老牌的邮件软件,知名度非常高。但是维茨(WietseZweitzeVenema)对此并不满意,于是就有了postfix。postfix命令(几乎)与sendmail兼容,但它更高效、更安全(后缀fix的由来)。目前是大多数Linux发行版默认的邮件收发软件。推荐使用postfix而不是sendmail(本博客多年前写过一篇文章howtoConfiguresendmail,当时年少无知,打算抽空把那篇文章改过来)。postfix的主要配置文件是/etc/postfix/main.cf。配置文件的注释非常齐全,选项基本都是自解释的。最重要的配置是:myhostname、myorigin、inet_interfaces、inet_protocols和mydestination(如果你打算从外部网络接收信件)。需要注意的是,当inet_interfaces配置为localhost时,inet_protocols的值应该是ipv4,否则可能会出现类似于postfix:fatal:parameterinet_interfaces:nolocalinterfacefoundfor::1的错误信息。与邮件相关的几个常用的postfix命令有:postquque,查看邮件发送队列。postqueue-p可以代替sendmail中的mailq命令,postqueue-f刷新队列(强制尝试发送队列中的邮件)。postcat,查看未发送邮件的信息。例如postcat-qxxxx(xxxx是postqueue或mailq显示的未发送队列ID)可以查看邮件的详细信息,postcat-b-qxxxxx只能查看邮件的正文。postsuper,一个只能由超级用户使用的邮件管理程序。postsuper-dxxxx,删除队列ID为xxxxx的邮件;postsuper-hxxxxx,暂停发送队列ID为xxxx的邮件等。上面的描述对于发送邮件来说基本够用了。注意mail命令发送的邮件只有在postfix运行的情况下才能投递(psaux|greppostfix|grep-vgrep输出不为空)。有了postfix,配置后可以对外发送邮件,也可以接收外网的邮件,但仅限于命令行操作。如果要用foxmail等客户端收发邮件,需要让服务器支持POP3/IMAP协议。开源的dovecot可以实现这个功能。Dovecot服务于接收邮件而不是发送邮件,因此了解它对开发帮助不大。如果想搭建一个完整的邮件系统(包括网页支持、垃圾邮件过滤、病毒扫描、传输加密等),建议参考或使用国内开源的EwoMail。理解postfix在开发过程中发送电子邮件有多大帮助?老实说,这几乎没有帮助。原因是为了防止垃圾邮件泛滥,各大云服务器厂商都封锁了25端口(谷歌云连465都干掉了)。亚马逊云还是有应用发布的可能(但是有速度和每日配额限制),其他厂商几乎不会让你用自己的域名直接从机器上发邮件。封锁25端口,必须使用第三方邮件服务,这几乎是业界的标准做法。聪明人可能会想,使用加密的465端口(基于SMTPS,SMTPoverSSL协议)或者587端口(SMTPoverSTARTTLS协议)发送邮件可以绕过限制?阿里云/腾讯云等厂商不屏蔽465端口,无需申请即可使用该端口发送邮件。但是注意465和587端口是用于客户端和邮件服务器之间的通信,25端口是用于邮件服务器之间的通信。可以通过465端口连接到Gmail邮箱发送邮件,但是不能让postfix使用465端口向hotmail邮件服务器投递邮件。综上所述,sendmail/postfix作为垃圾邮件和欺诈邮件泛滥之前的邮件服务器软件,为业界做出了巨大的贡献。随着云服务器的普及,域名指向本机的邮件几乎不可能发送。sendmail/postfix除了在本机发送提醒邮件外,用处不大。对外发送邮件,要么自建机房,要么使用第三方邮件系统。由于PHP的邮件功能是用PHP开发的,所以了解sendmail/postfix还是很有用的。mail函数默认使用sendmail/postfix发送邮件。如果了解相关配置,就可以知道为什么有效/为什么无效。简单来说,要使PHP自带的邮件功能正常工作,需要做如下操作:申请域名,在DNS解析中设置MX记录,发送邮件指向本机(非合法主机(FQDN,FullyQualifiedDomainName)将作为垃圾邮件直接丢弃);安装sendmail/postfix,配置软件并运行;配置防火墙、安全组和允许端口。发送效率低、调用方式不面向对象、配置麻烦、被云服务器厂商封杀是邮件功能使用的最大障碍。所以自从开始使用PHP,我就没有直接使用过邮件功能。PHP发送邮件发送邮件需要知道的东西太多了,会让人觉得很累。说好的PHP是最好的语言?使用PHP发送电子邮件也可以非常简单。推荐的方法是使用SwiftMailer或PHPMailer等库。引入这些类库后,注册一个第三方邮箱(如Gmail、QQ等),填写用户名和密码,配置好STMP地址和端口,就可以像发短信一样轻松发邮件了。当然这些库也支持使用sendmail/postfix发送邮件,但我认为你不会再这样做了。以SwiftMailer为例,直接上传代码可见用PHP发送邮件也是一件很简单的事情!首先在项目中引入SwiftMailer:composerrequire"swiftmailer/swiftmailer:^6.0"然后准备邮件内容(以文本文件为例,不带附件):$message=(newSwift_Message('TestMessage'))->setFrom(['tlanyan@tlanyan.me'=>'tlanyan'])->setTo(['tlanyan1@tlanyan.me'])->setBody('你好,这是来自Swift的测试邮件Mailer!');接下来,设置邮件传输方式(使用Gmail):$transport=(newSwift_SmtpTransport('smtp.gmail.com',465,'ssl'))->setUsername('username')->setPassword('密码');或者使用sendmail/postfix(不推荐):$transport=(newSwift_SendmailTransport());最后,使用transport构造一个mailer实例并发送邮件:$mailer=newSwift_Mailer($transport);$result=$mailer->send($message);老板再也不用担心收不到发送的邮件了,Soeasy!总结本文首先回顾了发送邮件的相关概念,解释了为什么不推荐使用内置的邮件功能,最后给出了使用第一个第三方类库发送邮件的代码示例。感谢阅读,欢迎评论指正!参考http://cn.linux.vbird.org/lin...http://doc.ewomail.com/ewomai...http://php.net/manual/en/func...https://swiftmailer.symfony.com
