通过python发邮件的步骤:
- 邮箱开通了SMTP服务,并设置了授权码(可以登陆第三方客户端)
- 构建收发件人,主题,内容
- 创建一个smtp对象,连接到smtp服务器,登陆邮件,发送邮件,关闭stmp对象
163邮箱测试一直报554错误代码。以下代码基于QQ邮箱
[root@web sendemial]# cat test.py #!/usr/bin/env python #coding:utf8 import codecs import sys import os import smtplib from email.mime.text import MIMEText from email.header import Header class SendEmail(object): def __init__(self, sender, sendto, subject, subtype, filename): self.sender = sender self.sendto = sendto self.subject = subject self.filename = filename self.subtype = subtype self.smtpserver = 'smtp.qq.com' self.username = self.sender self.password = 'xxxxx' self._init() def _init(self): if not os.path.exists(self.filename): print ('{0} is not exist, program exiting.....') sys.exit() def readContent(self): with codecs.open(self.filename, 'rb', encoding='utf-8') as fd: return fd.read() def buildHeader(self): self.msg = MIMEText(self.readContent(), self.subtype, 'utf-8') //创建消息对象 self.msg['Subject'] = Header(self.subject, 'utf-8') //构建请求头信息,第一个参数必须为字符串 self.msg['From'] = Header(self.sender, 'utf-8') self.msg['To'] = Header(','.join(self.sendto), 'utf-8') def send(self): self.buildHeader() try: sm = smtplib.SMTP_SSL() //创建smtp对象,qq邮箱强制走ssl sm.connect(self.smtpserver, 465) //smtp服务器走465端口 sm.login(self.username, self.password) sm.sendmail(self.sender, self.sendto, self.msg.as_string()) //调用对象的发送邮件方法 except Exception as e: print (e) finally: sm.quit() if __name__ == '__main__': sender = 'xxxx@qq.com' sendto = ['xxx@qq.com', 'xxxx'] subject = 'web聊天室' subtype = 'plain' filename = 'content.txt' sendEmail = SendEmail(sender, sendto, subject, subtype, filename) sendEmail.send()
需要注意的地方:
- 创建消息对象
In [27]: help(email.mime.Text.MIMEText) Help on class MIMEText in module email.mime.text: class MIMEText(email.mime.nonmultipart.MIMENonMultipart) | Class for generating text/* type MIME documents. | | Method resolution order: | MIMEText | email.mime.nonmultipart.MIMENonMultipart | email.mime.base.MIMEBase | email.message.Message | | Methods defined here: | | __init__(self, _text, _subtype='plain', _charset='us-ascii') | Create a text/* type MIME document. | | _text is the string for this message object. //第一个参数为消息对象(文本内容) | | _subtype is the MIME sub content type, defaulting to "plain". //发送文本:_subtype='plain'(默认);如果邮件内容含html代码:_subtype='html' | | _charset is the character set parameter added to the Content-Type //字符集默认为ascii | header. This defaults to "us-ascii". Note that as a side-effect, the | Content-Transfer-Encoding header will also be set.
2. 构建头部信息
In [28]: help(email.Header.Header) Help on class Header in module email.header: class Header | Methods defined here: | | __eq__(self, other) | # Rich comparison operators for equality only. BAW: does it make sense to | # have or explicitly disable <, <=, >, >= operators? | | __init__(self, s=None, charset=None, maxlinelen=None, header_name=None, continuation_ws=' ', errors='strict') | Create a MIME-compliant header that can contain many character sets. s may be a byte string or a Unicode string //第一个参数必须是字符串或者unicode编码
- 选择邮箱和smtp服务器的问题
qq邮箱默认走ssl,所以创建的smtp对象必须要支持加密传输,且需要指定port=465
- 发送邮件
In [30]: help(smtplib.SMTP_SSL) Help on class SMTP_SSL in module smtplib: class SMTP_SSL(SMTP) | This is a subclass derived from SMTP that connects over an SSL encrypted | socket (to use this class you need a socket module that was compiled with SSL | support). If host is not specified, '' (the local host) is used. If port is | omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile | are also optional - they can contain a PEM formatted private key and | certificate chain file for the SSL connection. | | Methods defined here: | | __init__(self, host='', port=0, local_hostname=None, keyfile=None, certfile=None, timeout=<object object>) ....... | sendmail(self, from_addr, to_addrs, msg, mail_options=[], rcpt_options=[]) | This command performs an entire mail transaction. | | The arguments are: | - from_addr : The address sending this mail. //邮件发送地址 | - to_addrs : A list of addresses to send this mail to. A bare //邮件接收地址,必须为一个列表,列表的元素是收件邮件邮箱,如果只有一个收件人,可以不用列表,直接使用字符串 e.g. '736821063@qq.com' | string will be treated as a list with 1 address. | - msg : The message to send. //需要发送的消息,这里指的是通过Header类创建的携带头部信息的消息对象 | - mail_options : List of ESMTP options (such as 8bitmime) for the | mail command. | - rcpt_options : List of ESMTP options (such as DSN commands) for | all the rcpt commands.
5. 如果上面的代码发送失败,试试下面的代码,主要是创建消息对象的方式不同
[root@web sendemial]# cat test1.py #!/usr/bin/env python #coding:utf8 import codecs import sys import os import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart class SendEmail(object): def __init__(self, sender, sendto, subject, subtype, filename): self.sender = sender self.sendto = sendto self.subject = subject self.filename = filename self.subtype = subtype self.smtpserver = 'smtp.qq.com' self.username = self.sender self.password = 'xxxxx' self._init() def _init(self): if not os.path.exists(self.filename): print ('{0} is not exist, program exiting.....') sys.exit() def readContent(self): with codecs.open(self.filename, 'rb', encoding='utf-8') as fd: return fd.read() def buildHeader(self): self.msg = MIMEMultipart() self.msg['from'] = self.sender self.msg['to'] = ','.join(self.sendto) //构建头部信息,跟上面一样,值必须为字符串 self.msg['subject'] = self.subject txt = MIMEText(self.readContent(), self.subtype, 'utf-8') self.msg.attach(txt) def send(self): self.buildHeader() try: sm = smtplib.SMTP_SSL() sm.connect(self.smtpserver, 465) sm.login(self.username, self.password) sm.sendmail(self.sender, self.sendto, self.msg.as_string()) except Exception as e: raise e print (e) finally: sm.quit() if __name__ == '__main__': sender = 'xxxx' sendto = ['xxxx', 'xxxx'] subject = 'debugging' subtype = 'plain' filename = 'content.txt' sendEmail = SendEmail(sender, sendto, subject, subtype, filename) sendEmail.send()