博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
配置mail使用SMTP发送邮件
阅读量:7005 次
发布时间:2019-06-27

本文共 4245 字,大约阅读时间需要 14 分钟。

转载请注明文章出处:

前文“”介绍了邮件中的一些基本概念,今天分享在Linux上使用mail命令通过SMTP对外发送邮件。

mail、mailx和sendmail

先看一下三者的关系:mailmailx的别名,最初叫nail(与arch linux目前用的S nail基因相同);mail是Heirloom的一个子项目,sendmail是Eric Allman的作品,都是开源项目;mail是用户代理(客户端),sendmail是邮件传输代理(服务器);mail默认使用sendmail对外发送邮件。

总结:mail和mailx是同一个东西,大约类似于发信用的foxmail、outlook等工具,sendmail大约相当于163/qq邮箱的服务器软件。

SSL、TLS和STARTTLS

由前文我们知道云服务器基本上不允许25端口对外通信,要对外发邮件只能考虑465和587端口。那么465和587端口有什么区别?这要先从SSL、TLS和STARTTLS的区别开始说。

SSL(Secure Socket Layer)是加密传输层,TLS(Transport Layer Security)是SSL的继承者和升级版,提供更好的安全性和性能。SSL有SSL v2、SSL v3两个版本,目前都不建议使用。TLS有TSL v1.0-v1.3,建议至少使用TLS v1.2。

TLS和STARTTLS两者关系不大,但更让人容易产生误解,原因是名字中都带有TLS。STARTTLS是升级非安全连接为安全连接的协议,并没有强制使用加密。当服务端支持时,客户端和服务端才协商将已经建立的连接升级到SSL或者TLS加密。

接着看465端口和587端口。我们知道25端口刚被设计出来时是用于转发邮件的,没有考虑认证、加密等问题。随着垃圾邮件泛滥、网络安全问题严重,MSA、ESMTP/SMTPS等概念和协议被设计出来。1997年465端口被注册用于加密方式(SMTPS)提交邮件,那时STARTTLS还没有捣腾出来。1998年STARTLS标准出炉,规定用587端口以STARTTLS方式提交邮件,465端口被吊销。然而许多客户端不支持STARTTLS,加上非常多邮件服务提供商都在使用465端口作为加密提交端口,于是465就一直这么被用到今天。

简单来说,465端口只支持加密传输,不符合互联网号码分配结构(The Internet Assigned Numbers Authority,IANA)的标准,但一直被使用和支持;587端口专门被设计用来提交邮件,传输可以加密也可以不加密。

配置mail

明白了基本概念,接下来配置mail使用SMTP对外发送邮件。mail命令的系统级配置文件是/etc/mail.rc,用户级别的默认配置文件是~/.mailrc,也可以通过MAILRC环境变量设置配置文件路径。作为普通用户,我们在本地的~/.mailrc文件进行配置,SMTP的主要配置如下:

set smtp=smtps://smtp.xxx.com:465   # 这里填入smtp地址set smtp-auth=login                 # 认证方式set smtp-auth-user=user@xxx.com     # 这里输入邮箱账号set smtp-auth-password=password     # 这里填入密码set ssl-verify=ignore               # 忽略证书警告set nss-config-dir=/etc/pki/nssdb   # 证书所在目录set from=user@xxx.com               # 设置发信人邮箱和昵称#set smtp-use-starttls=yes          # STARTTLS时使用

几个注意点:

  1. 如果是465端口,需要加上smtps://协议;如果是587端口,不需要加smtps://或者写smtp://
  2. 如果使用587端口通讯,应当显示设置smtp-use-starttls
  3. 邮件的来源应当与邮箱相同,或者将发信人姓名写在邮箱后的括号中。例如:set from=user@xxxx.comset from=user@xxx.com(nickname);如果邮箱与认证的不一致,将出现“smtp-server: 553 Mail from must equal authorized user”的错误;
  4. 有些邮件服务器的587端口不是使用STARTTLS而是SMTPS,此时仍需加上smtps://协议,例如126邮箱。

配置好后,使用mail命令发送邮件:

echo '邮件内容' | mail -s '邮件标题' 收件人邮箱#或者:cat 邮件内容.txt | mail -s '邮件标题' 收件人邮箱#或者mail -s '邮件标题' 收件人邮箱 < 邮件内容.txt

mail命令的选项非常丰富,具体可查看其文档或。

多账户

如果想切换发送邮箱怎么办?答案是利用配置文件的account指令或在命令行中指定配置。先看配置文件中指定,在~/.mailrc中将配置改成如下:

# 126不支持STARTTLS,使用465端口account 126 {    set smtp=smtps://smtp.126.com:465    set smtp-auth=login    set smtp-auth-user=user@126.com    set smtp-auth-password=password    set ssl-verify=ignore    set nss-config-dir=/etc/pki/nssdb    set from=password@126.com}# QQ邮箱支持STARTTLS,使用587端口account qq {    set smtp=smtp://smtp.qq.com:587    set smtp-auth=login    set smtp-auth-user=user@qq.com    set smtp-auth-password=password    set ssl-verify=ignore    set nss-config-dir=/etc/pki/nssdb    set from="user@qq.com(nickname)"    set smtp-use-starttls=yes}

配置文件中定义了两个账户,发送邮件时可用-A参数指定发信账户:

echo 'mail test for 126' | mail -A 126 -s 'mail test' user@xxx.comecho 'mail test for qq' | mail -A qq -s 'mail test' user@xxx.com

除了配置文件,也可以在命令行中用-S参数进行设置。例如:

echo 'mail test for command line option' | mail -s 'mail test' -S smtp=smtp://smtp.qq.com:587 -S smtp-auth=login -S smtp-auth-user=user@qq.com -S smtp-auth-password=password -S ssl-verify=ignore -S nss-config-dir=/etc/pki/nssdb -S from="user@qq.com(nickname)" -S smtp-use-starttls=yes user@xxx.com

这种方法比较繁琐,就是将配置文件的每一行都作为选项写在命令中。在程序中调用mail命令发送邮件时可以采取这种方法。

解决警告

虽然邮件能顺利发送,但每次运行都会出现一行警告:“Error in certificate: Peer's certificate issuer is not recognized.”。这是由于使用加密通信,但客户端不能确认证书是否真实。如果我们将配置中的set ssl-verify=ignore改成set ssl-verify=strict,连接将直接中断而不会继续发邮件。

要解决这个警告,需要将邮件服务器的证书加入到信任列表。操作步骤如下:

  1. 获取邮件服务器证书:
# 465端口echo -n "" | openssl s_client -connect smtp.xxx.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > xxx.crt# 587端口echo -n | openssl s_client -starttls smtp -connect smtp.xxx.com:587 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > xxx.crt# 也可以直接在浏览器上打开网页版,保存证书为PEM(base64格式)格式然后上传到服务器
  1. 将证书添加到受信任列表:
certutil -A -n 'xxxx' -t "P,P,P" -d . -i ./xxx.crt

上述命令中-A表示添加,-n是nickname,可以随意取,例如126或qq;-t表示受信任的标签,可取值是t/c/p三种或者其组合;-d表示证书所在目录,-i指示证书文件的位置。

  1. 在配置文件中更改证书目录:
# 指向证书文件目录set nss-config-dir=/path/to/cert-dir

网上许多教程的-t标签都是"C,,",实践中发现使用该标签仍会报错(gmail的证书是google自己签发的,用C标签没问题,许多博主估计没试就直接抄来)。通过查阅certutil的用法,使用P标签顺利解决问题。

配置完成后,再使用mail命令发送邮件,烦人的警告消失不见。

其他

"Unexpected EOF on SMTP connection",基本上是由于端口只支持SMTPS导致,将协议改成smtps://即可。

参考

你可能感兴趣的文章
ListView_split 分割
查看>>
在32位windows 7下安装PyLucene
查看>>
新闻站点程序
查看>>
自己工资自己算,策略设计模式(Strategy)
查看>>
[转载]WebConfig配置文件详解
查看>>
159. Longest Substring with At Most Two Distinct Characters
查看>>
Android 架构组件 - Lifecycle, LiveData, ViewModel
查看>>
Ubuntu的web服务器搭建系列之Nginx(JDK+Tomcat+MySQL+Nginx+Redis+NodeJS)
查看>>
java集合相关的小知识
查看>>
非root用户免sudo使用docker命令
查看>>
DOM事件
查看>>
检测AudioRecord是否被第三方管理应用禁用(附demo)
查看>>
阿里P8架构师谈:如何搭建亿级并发系统的性能指标体系
查看>>
关于webpack优化,你需要知道的事(上篇)
查看>>
深入浅出Java并发核心
查看>>
springmvc+mybatis +Jeesz 分布式架构
查看>>
深入剖析 Java7 中的 HashMap 和 ConcurrentHashMap
查看>>
打造腾讯营销数据闭环,MTA联手腾讯广告平台
查看>>
Tomcat中用JNDI方式加载JDBC DataSource以连接数据库
查看>>
android解析HashMap格式的json
查看>>