Python发送邮件:smtplib、sendmail
本地Ubuntu 18.04,本地Python 3.6.5,
阿里云Ubuntu 16.04,阿里云Python 3.5.2,
smtplib,sendmail 8.15.2,
今天,打算实现通过电子邮件发送 注册用户激活功能,原以为一天是够够的了,谁知,踩到 坑了:一个软件坑,一个ECS坑。
早上一来,便按照教程Python SMTP发送邮件做测试,很简单,使用smtplib模块 在 安装了sendmail的电脑上就可以执行邮件发送功能了。
只是,sendmail是什么?先用起来再说!
拷贝了教程中第一段代码,并更改了其中的sender和receivers,如下:
# -*- coding: UTF-8 -*-
'''
Created on 2018年8月15日 @author: log
''' import smtplib
from email.mime.text import MIMEText
from email.header import Header import traceback sender = 'test@mydomain.com'
receivers = ['my163mail@163.com', 'myqqmail@qq.com'] # 三个参数
message = MIMEText('来自Python smtplib模块发送的测试邮件...请勿回复(Ubuntu)', 'plain', 'utf-8')
message['From'] = Header('测试邮件', 'utf-8')
message['To'] = Header('自己', 'utf-8') subject = 'Python smtplib邮件发送测试'
message['Subject'] = Header(subject, 'utf-8') try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message.as_string())
print('没有异常发生,邮件发送成功...')
except:
traceback.print_exc()
print('Error: 邮件发送失败')
sendmail安装
本地和阿里云Ubuntu中都没有安装sendmail,使用下面的命令安装:
sudo apt install sendmail
sendmail安装完毕,开始测试程序。
sendmail安装位置查询:
$ whereis sendmail
sendmail: /usr/sbin/sendmail /usr/lib/sendmail /usr/share/sendmail /usr/share/man/man8/sendmail.8.gz
配置文件位于/etc/mail/目录中,文件很多,挺复杂的。开始遇到问题时,修改过其中的sendmail.mc、sendmail.cf,后来才知道,其实不需要更改的。
日志文件位于/var/log/目录中,mail.log、mail.err,后者为错误记录文件,查看两个信息、定位问题,很关键。



常用命令mail、mailq,mail查看 接收到的邮件,mailq查看 待发送邮件。
更多说明:
mail命令可以查看收到的邮件,今天在本地测试时,有收到一些邮件,具体操作,还需看起文档、资料(当然,自己发送的邮件是被当作垃圾邮件的spam)。

mailq的待发送邮件存在于/var/spool/mqueue-client、/var/spool/mqueue两个目录中,直接删除其中的文件,即可删除所有待发送邮件,但要注意,里面存储的可不一定是自己这个用户的待发送邮件,更好的方法是使用一个叫做postsuper(需要安装postfix)命令按用户删除——孤没有安装它,直接去目录中删除的。
测试程序
因为有本地Ubuntu,所以,将上面的代码拷贝到本地Ubuntu中运行——virtualenv中,Python 3.6.5。
结果,遇到了第一个问题:
smtplib.SMTPRecipientsRefused: {'my163mail@163.com': (553, b'5.1.8 <my163mail@163.com>... Domain of sender address test@mydomain.com does not exist'), 'myqqmail@qq.com': (553, b'5.1.8 <myqqmail@qq.com>... Domain of sender address test@mydomain.com does not exist')}
发送者sender的域名test@mydomain.com不存在!
更改sender为sender = 'test@qq.com',测试程序,仍然失败!
更改sender为myqqmail@qq.com,receivers为['my163mail@163.com'],想实现从myqqmail@qq.com发送邮件到my163mail@163.com,当然,失败了!的确也应该失败,都不登录就想法邮件?不可能的!
日志分析
在sendmail的日志文件中找到一些记录:
My unqualified host name (myhostname) unknown; sleeping for retry
unable to qualify my own domain name (myhostname) -- using short name
--
w7F2vjwT000424: to=<myqqmail@qq.com>, delay=00:08:00, xdelay=00:08:00, mailer=esmtp, pri=120327, relay=mx1.qq.com. [183.57.48.35], dsn=4.0.0, stat=Deferred: Connection timed out with mx1.qq.com.
下面是阿里云上测试的日志记录:
sm-mta[1076]: w7F3lErF001076: from=<from@myhostname>, size=327, class="0", nrcpts=2, msgid=<201808150347.w7F3lErF001076@myhostname>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
sm-mta[1118]: w7F3nI5V001118: from=<from@localhost>, size=327, class="0", nrcpts=2, msgid=<201808150349.w7F3nI5V001118@myhostname>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
sm-mta[1134]: w7F3p4ua001134: from=<myqqmail@qq.com>, size=327, class="0", nrcpts=1, msgid=<201808150351.w7F3p4ua001134@myhostname>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
--
My unqualified host name (myhostname) unknown; sleeping for retry
unable to qualify my own domain name (myhostname) -- using short name
P.S.一个上午就这么过去了,哎呀,
想了一下,本地和阿里云都有下面的日志记录:
My unqualified host name (myhostname) unknown; sleeping for retry
unable to qualify my own domain name (myhostname) -- using short name
那么,先解决这个问题先。
解决方案:更改/etc/hosts文件
怎么修改?
阿里云ECS 更改前 hosts文件中存在下面的语句:
ipv4_addr myhostname myhostname
更改后:
ipv4_addr myhostname domain.name.com
将第二个更改为域名即可,当然,这个域名应该不能使qq.com、163.com等吧?这里孤不清楚,还需dig。
注意:在修改之后,ECS重启后会在更改后的配置下面添加原来的ipv4_addr myhostname myhostname,即出现两行。为何如此呢?
本地安装在虚拟机中的Ubuntu的hosts中部分配置:
127.0.0.1 localhost
127.0.1.1 localhost
更改后:
127.0.0.1 localhost
127.0.1.1 localhost some_name.me
为何添加一个somename.me呢?这个some_name.me是一个域名,还尝试了配置为自己购买的域名,以及其它域名,在本地测试时都成功发送了邮件。
对了,怎么不配置在第一行127.0.0.1后面呢?或许可以,未尝试,需dig,
P.S.都是Ubuntu,版本不同,但hosts文件的差别挺大的呢!
说明:更改hosts文件后,sendmail的软件坑就算解决了,没有上面的“unknown; sleeping for retry...unable to qualify my own domain name”错误提示了,下面ECS的坑紧接着就来了,而这个ECS的坑的名字叫做阿里云默认封禁TCP 25端口出方向的访问流量。
P.S.下面的测试都是在修改了hosts文件后进行的测试。
大错特错的是:自己首先用阿里云进行了测试,结果,邮件一直发送失败。结果就是,mailq里面有越来越多的 待发送邮件,进程里面有很多目的主机端口为25的状态为SYN_SENT的连接存在。
$ mailq
MSP Queue status...
/var/spool/mqueue-client is empty
Total requests: 0
MTA Queue status...
/var/spool/mqueue (18 requests)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
w7F6USWQ002743* 4 Wed Aug 15 14:30 <ben@myhostname.com>
<my163mail@163.com>
w7F6N0hd002648* 4 Wed Aug 15 14:23 <ben@myhostname.com>
(Deferred: Connection timed out with mx1.qq.com.)
<myqqmail@qq.com>
w7F1Z5w4032186* 102 Wed Aug 15 09:35 <myqqmail@qq.com>
(Deferred: Connection timed out with 163mx00.mxmail.netease.c)
<my163mail@163.com>
w7F1VIFh032131 102 Wed Aug 15 09:31 <myqqmail@qq.com>
(Deferred: Connection timed out with 163mx00.mxmail.netease.c)
<my163mail@163.com>
netstat -ano | grep :25:邮件发送成后,只会存在一个的,即状态为LISTEN那个进程,这些SYN_SENT表示在重发mailq中的 待发送邮件。
$ netstat -ano | grep :25
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN off (0.00/0/0)
tcp 0 1 172.18.232.21:45698 220.181.14.145:25 SYN_SENT on (12.06/4/0)
tcp 0 1 172.18.232.21:57766 220.181.14.144:25 SYN_SENT on (59.02/6/0)
tcp 0 1 172.18.232.21:39008 123.125.50.139:25 SYN_SENT on (57.35/6/0)
tcp 0 1 172.18.232.21:36952 14.17.41.170:25 SYN_SENT on (3.37/4/0)
tcp6 0 1 172.18.232.21:40978 220.181.14.135:25 SYN_SENT on (5.96/5/0)
tcp6 0 1 172.18.232.21:52616 220.181.14.149:25 SYN_SENT on (21.32/6/0)
就不多说了,此问题由ECS坑造成的,还好,至少本地邮件发送成功了,否则,今天一定要郁闷到吐血啊!
不过自己定位问题、解决问题的效率挺低的,不够专注,多次被其它东西干扰!
展示下成果——全来自本地Ubuntu:
-163.com收到的邮件

发件人域名为log-u18.me:

发件人域名为自己购买的域名:

-qq.com收到的邮件
QQ邮箱会屏蔽这些本地Ubuntu发来的邮件,需要 首页--我的信息--自助查询 中将它们 取回才可以。

上图紫色方框中的邮件很有意思,内容入下图——发件人就是简单的log,后面居然没有跟着域名!
颠覆了自己的认知啊!
不过,在网易邮箱中没有发现这封邮件!




总结
阿里云ECS的这个坑可以申请使用25端口来提供邮件服务,据说只要1天审核时间;
但自己不准备这么做了,现在有网易邮箱、QQ邮箱,而且都可以开启SMTP服务,那么就是使用它们的服务器来发送邮件嘛,个人网站,发送的邮件又不多;
所以,还需要用注册手机开发网易邮箱、QQ邮箱的SMTP服务才可以。
至今,自己对sendmail所知甚少,怎么配置、怎么开发的、源码分析,估计是不会做更多研究了,安装了,就可以了。
至于Python标准库中的其它一些邮件操作库,暂时也是没有精时去了解研究了:
The Python Standard Library
https://docs.python.org/3.5/library/index.html
21. Internet Protocols and Support
21.14. poplib — POP3 protocol client
21.15. imaplib — IMAP4 protocol client
21.17. smtplib — SMTP protocol client
21.18. smtpd — SMTP Server 19. Internet Data Handling
19.1. email — An email and MIME handling package
19.3. mailcap — Mailcap file handling
19.4. mailbox — Manipulate mailboxes in various formats
把握重点,用到多少,就学多少,就酱!别担心没学到的会怎样怎样!没学到,可是,自己还是把系统搭建起来了啊!
哈哈哈哈~孤的系统,快快上线吧!~
参考资料:
The Python 3.5 Standard Library
smtplib — SMTP protocol client
sendmail 报错:unable to qualify my own domain name
Python发送邮件:smtplib、sendmail的更多相关文章
- python email ==> send 发送邮件 :) [smtplib, email 模块]
关于Email的预备知识: 原贴地址:http://www.cnblogs.com/lonelycatcher/archive/2012/02/09/2343480.html ############ ...
- python使用smtplib发送邮件
python要实现发送邮件的功能,需要使用smtplib库. 1. 过程大致如下: 1. 建立和SMTP邮件服务器的连接 # 默认端口25 smtp = smtplib.SMTP(host, port ...
- python之smtplib模块 发送邮件
# -*- coding: utf-8 -*- #python 27 #xiaodeng #smtplib模块 发送邮件 import smtplib from email.mime.text imp ...
- python发送邮件(smtplib)
我们在测试完成后,都会发一份邮件也就是我们的测试报告,那么既然要自动化,是不是也可以通过python帮助我们发送邮件?当然这么强大的python可以帮助你完成这个需求 SMTP SMTP(Simple ...
- python爬虫-smtplib模块发送邮件
1.代码如下: import smtplib from email.message from EmailMessage # smtplib模块负责发送邮件服务 # email.message模块负责构 ...
- python发送邮件
python发送邮件(无附件) ======================================================= #!/usr/bin/env python#coding ...
- python发送邮件及附件
今天给大伙说说python发送邮件,官方的多余的话自己去百度好了,还有一大堆文档说实话不到万不得已的时候一般人都不会去看,回归主题: 本人是mac如果没有按照依赖模块的请按照下面的截图安装 导入模块如 ...
- 解读Python发送邮件
解读Python发送邮件 Python发送邮件需要smtplib和email两个模块.也正是由于我们在实际工作中可以导入这些模块,才使得处理工作中的任务变得更加的简单.今天,就来好好学习一下使用Pyt ...
- python 发送邮件例子
想到用python发送邮件 主要是服务器 有时候会产生coredump文件 ,然后因为脚本重启原因,服务器coredump产生后会重启 但是没有主动通知开发人员 想了下可以写个脚本一旦产生cored ...
- 利用python发送邮件
找了很多使用python发送邮件的文章, 发现写的并不是太全, 导致坑特别多, 刚把这个坑跨过去, 在此记录下来 本代码使用163作为发送客户端, 接收邮箱随意 首先登录163邮箱, 开启POP3/S ...
随机推荐
- Software-Defined Networking:A Comprehensive Survey--Day3
(接Day2的内容 +2s) E. Layer V: Northbound Interfaces 南行接口已经得到广泛接受(OpenFlow),但现在就定义北向接口还为时尚早,开发不同的控制器经验一定 ...
- 对于beta发布的评论
第一组:新蜂小组 题目:俄罗斯方块 评论:主体功能已经完成,可以流畅的进行游戏,看项目的完成度是最高的.他们不但把核心功能做出来了,界面也已基本完成. 第二组:Nice团队 题目:约跑APP(约吧) ...
- WP-PostViews使用
1.在后台安装次插件 2.获取多少天之内的访问排名最高的记录 2.1 添加相应方法代码到wp-postviews.php文件中,据体代码可以网上找(本人自己可以在自己本机的例子查看到),这里只是记录大 ...
- P2824 [HEOI2016/TJOI2016]排序
题面 这是一道非常巧妙的线段树的题 我们会发现维护\(1 \sim n\)的序列非常困难,但如果我们维护\(01\)序列的的顺序,就非常容易了 但是我们怎么能把这道题变成维护\(01\)序列的顺序呢? ...
- VirtualBox 文件共享及网络配置技巧
文件共享 1. 安装增强功能 2. 分配数据空间 这样就可以在virtualbox里访问本地的数据了: 网络配置
- 【洛谷P2661】信息传递
题目大意:给定一个有 N 个点,N 条边且每个点的出度均为 1 的有向图,求该有向图的一个最小环. 题解:由于每个点的出度均为 1,可知可能的情况只有以下几种:一个环或多个环,一个环+一条链.因此,可 ...
- Eclipse启动项目正常,放到tomcat下单独启动就报错的 一例
一个老的ssh的项目,进行二次开发(增加一些新功能)后, 首先用Eclipse中集成的Tomcat启动没有任何问题,但是把启动后的webapps下得目录放到 windows的普通tomcat下单独启动 ...
- spring in action 学习笔记八:用@Primary 或者@Qualifier消除@Autowired引起的歧义现象
首先解释一下@Primary和@Qualifier这两个注解的意思:@Primary的意思是在众多相同的bean中,优先使用用@Primary注解的bean.而@Qualifier这个注解则指定某个b ...
- Centos7.4+openvpn-2.4.4+easy-rsa-3.0物理机安装教程
完整CentOS搭建OpenVPN服务环境图文教程 大福技术 关注 2016.02.17 09:28* 字数 3017 阅读 34000评论 18喜欢 21赞赏 3 对于OpenVPN环境有什么用途老 ...
- Excel:函数中的万金油:INDEX+SMALL+IF+ROW
很多人在Excel中用函数公式做查询的时候,都必然会遇到的一个大问题,那就是一对多的查找/查询公式应该怎么写?大多数人都是从VLOOKUP.INDEX+MATCH中入门的,纵然你把全部的多条件查找 ...