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 = ‘[email protected]‘
receivers = [‘[email protected]‘, ‘[email protected]‘]

# 三个参数
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: {‘[email protected]‘: (553, b‘5.1.8 <[email protected]>... Domain of sender address [email protected] does not exist‘), ‘[email protected]‘: (553, b‘5.1.8 <[email protected]>... Domain of sender address [email protected] does not exist‘)}

发送者sender的域名[email protected]不存在!

更改sender为sender = ‘[email protected]‘,测试程序,仍然失败!

更改sender为[email protected],receivers为[‘[email protected]‘],想实现从[email protected]发送邮件到[email protected],当然,失败了!的确也应该失败,都不登录就想法邮件?不可能的!

日志分析

在sendmail的日志文件中找到一些记录:

My unqualified host name (myhostname) unknown; sleeping for retry

unable to qualify my own domain name (myhostname) -- using short name

--

w7F2vjwT000424: to=<[email protected]>, 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=<[email protected]myhostname>, size=327, class="0", nrcpts=2, msgid=<[email protected]myhostname>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]

sm-mta[1118]: w7F3nI5V001118: from=<[email protected]localhost>, size=327, class="0", nrcpts=2, msgid=<[email protected]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=<[email protected]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 <[email protected]>
                                         <[email protected]>
w7F6N0hd002648*       4 Wed Aug 15 14:23 <[email protected]>
                 (Deferred: Connection timed out with mx1.qq.com.)
                                         <[email protected]>
w7F1Z5w4032186*     102 Wed Aug 15 09:35 <[email protected]>
                 (Deferred: Connection timed out with 163mx00.mxmail.netease.c)
                                         <[email protected]>
w7F1VIFh032131      102 Wed Aug 15 09:31 <[email protected]>
                 (Deferred: Connection timed out with 163mx00.mxmail.netease.c)
                                         <[email protected]>

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

把握重点,用到多少,就学多少,就酱!别担心没学到的会怎样怎样!没学到,可是,自己还是把系统搭建起来了啊!

哈哈哈哈~孤的系统,快快上线吧!~

参考资料:

Python SMTP发送邮件

The Python 3.5 Standard Library

smtplib — SMTP protocol client

阿里云ECS: TCP 25端口解封申请

Sendmail Open Source

sendmail安装使用

linux之发送邮件--sendmail服务配置

TCP协议端口状态说明 by jessezeng

sendmail 报错:unable to qualify my own domain name

原文地址:https://www.cnblogs.com/luo630/p/9484620.html

时间: 2024-08-30 11:55:45

Python发送邮件:smtplib、sendmail的相关文章

Python发送邮件smtplib.SMTP各报错问题的解决方法

经测试可用的发送邮件代码: import smtplib from email.mime.text import MIMEText # 第三方 SMTP 服务 mail_host = "smtp.163.com" # SMTP服务器 mail_user = "username" # 用户名 mail_pass = "passwd" # 密码(这里的密码不是登录邮箱密码,而是授权码) sender = '[email protected]' # 发

python之smtplib模块 发送邮件

# -*- coding: utf-8 -*- #python 27 #xiaodeng #smtplib模块 发送邮件 import smtplib from email.mime.text import MIMEText ''' http://www.cnblogs.com/xiaowuyi/archive/2012/03/17/2404015.html #基本思路: 1.构造发送邮件的主程序,创建发邮件的对象,链接服务器.登录服务器.发送邮件命令行.关闭服务器 2.在主程序中为了便于错误分

python - 发送邮件(smtplib、email)

发送邮件(smtplib.email) 通常在API和UI自动化测试后,都需要将运行的测试报告发送给指定邮件组接收,这个邮件发送功能可以利用python自带的两个模块完成: smtplib模块主要负责发送邮件如:连接邮箱服务器,登录邮箱,发送邮件 email模块主要负责构造邮件如:发件人,收件人,主题,正文,附件.图片.HTML等 一.smtplib 1.smtplib示例: import smtplib # 实例化SMTP连接(IP,端口) smtp = smtplib.SMTP_SSL(se

python爬虫-smtplib模块发送邮件

1.代码如下: import smtplib from email.message from EmailMessage # smtplib模块负责发送邮件服务 # email.message模块负责构建邮件,然后交给smtplib发送 # 定义SMTP服务器地址 smtp_server = 'smtp.163.com' # 定义发件人地址 from_addr = "***********@163.com" # 定义登录密码 password = '**********' # 定义收件人

python 发送邮件及smtplib.SMTPAuthenticationError 503 错误处理

发送失败错误1:smtplib.SMTPAuthenticationError:    我们使用python发送邮件时相当于自定义客户端根据用户名和密码登录,然后使用SMTP服务发送邮件,邮箱是默认不开启客户端授权的,因此登录总是被拒绝,解决办法(以qq邮箱为例):进入qq邮箱-设置-客户端授权密码-开启(授权码是用于登录第三方邮件客户端的专用密码),非第三方登录密码不变. 原文地址:https://www.cnblogs.com/sixing/p/8665286.html

【转载】python发送邮件实例

本文转自:http://www.cnblogs.com/lonelycatcher/archive/2012/02/09/2343463.html 这几天要用python发送邮件,上网找到这篇文章感觉蛮全面的,故转载收藏之. 1. 文件形式的邮件 #!/usr/bin/env python3 #coding: utf-8 import smtplib from email.mime.text import MIMEText from email.header import Header send

python发送邮件(一)

最近设计了一个小的应用程序,主要是根据文件中邮件地址发送一份excel中内容,并且在接受方收到邮件都是以网页的格式呈现的. 下面主要是对python发送邮件涉及到的部分知识点做个总结 一.先介绍一下Smtp协议和POP3协议 SMTP (Simple Mail Transfer Protocol) http://www.rfc-editor.org/info/rfc821    RFC821文档详细描述了这个协议信息: 邮件传送代理 (Mail Transfer Agent,MTA) 程序使用S

python发送邮件(转)

SMTP发送邮件 阅读: 90274 SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件.HTML邮件以及带附件的邮件. Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件. 首先,我们来构造一个最简单的纯文本邮件: from email.mime.text import MIMEText msg = MIMEText('hello, send by Python...', 'plain', 'utf-8

解读Python发送邮件

解读Python发送邮件 Python发送邮件需要smtplib和email两个模块.也正是由于我们在实际工作中可以导入这些模块,才使得处理工作中的任务变得更加的简单.今天,就来好好学习一下使用Python发送邮件吧. SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件.HTML邮件以及带附件的邮件. Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件. 1.邮件正文是文本的格式 1 # -*- codi

python发送邮件的脚本

python发送邮件的脚本,带有邮件内容与附件,邮件内容为串格式,附件为文件.如果想把某个目录下的所有文件当作附件发送,那请去掉注释. 代码如下: #!/usr/bin/python #coding utf-8 from email.MIMEText import MIMEText from email.MIMEMultipart import MIMEMultipart from email.MIMEBase import MIMEBase from email import Utils, E