SMTP(Simple Mail Transfer Protocol) 简单邮件传输协议。
smtplib模块
创建SMTP对象
- smtplib.SMTP( [host [, port [, local_hostname]]] )
- 参数:
- host : SMTP 服务器主机。可以指定主机的ip地址或域名,可选参数。
- port : host参数需指定SMTP使用端口(25)
- local_hostname : SMTP在本机时,指定localhost
SMTP对象方法
方法
描述SMTP.set_debuglevel(level) 设置输出debug调试信息,默认不输出
SMTP.docmd(cmd[, argstring]) 发送一个命令到SMTP服务器
SMTP.connect([host[, port]]) 连接到指定的SMTP服务器
SMTP.helo([hostname]) 使用helo指令向SMTP服务器确认你的身份
SMTP.ehlo(hostname) 使用ehlo指令像ESMTP(SMTP扩展)确认你的身份
SMTP.ehlo_or_helo_if_needed() 如果在以前的会话连接中没有提供ehlo或者helo指令,这个方法会调用ehlo()或helo()
SMTP.has_extn(name) 判断指定名称是否在SMTP服务器上
SMTP.verify(address) 判断邮件地址是否在SMTP服务器上
SMTP.starttls([keyfile[, certfile]]) 使SMTP连接运行在TLS模式,所有的SMTP指令都会被加密
SMTP.login(user, password) 登录SMTP服务器
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])
发送邮件from_addr:邮件发件人
to_addrs:邮件收件人
msg:发送消息
SMTP.quit() 关闭SMTP会话
SMTP.close() 关闭SMTP服务器连接
1.文件形式邮件
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
- mail_server = 'smtp.163.com'
mail_server_port = 465
- mail_user = 'msun1996@163.com'
mail_pass = '*******'
from_addr = 'msun1996@163.com'
to_addr = ['msun1996@163.com'] #to_addr可放入多个邮箱,以逗号隔开
#发送邮件形式和内容
msg = MIMEText('Python mail test...','plain','utf-8')
msg['From'] = Header('msun','utf-8')
msg['To'] = Header('Test','utf-8')
- #发送主题
subject = 'Python SMTP mail test'
msg['Subject'] = Header(subject,'utf-8')
try:
smtp = smtplib.SMTP_SSL(mail_server,mail_server_port)
smtp.login(mail_user,mail_pass)
smtp.sendmail(from_addr,to_addr,msg.as_string())
smtp.quit()
print('邮件发送成功')
except smtplib.SMTPException:
print('Error:邮件发送失败!!!')
注意:此处用的是465端口 ssl
问题1:阿里云默认是关闭25端口,醉了!怪不得windose 25端口可以,linux就不行了。
问题2:windose smtp对象定义格式如下可以
smtp = smtplib.SMTP_SSL()
smtp.connect(mail_server,mail_server_port)
linux下必须用以下格式,否则会有ssl报错
smtp = smtplib.SMTP_SSL(mail_server,mail_server_port)
(163邮箱默认没开代理的,要进行设置)
2.HTML形式邮件
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
mail_server = 'smtp.163.com'
mail_server_port = 465
mail_user = 'msun1996@163.com'
mail_pass = '******'
from_addr = 'msun1996@163.com'
to_addr = ['msun1996@163.com']
mail_msg='''
<p>Python 邮件发送测试...</p>
<p><a href="http://139.199.82.84/kexiewojia/">这是一个链接</a></p>
'''
msg = MIMEText(mail_msg,'html','utf-8')
msg['From'] = Header('msun','utf-8')
msg['To'] = Header('Test','utf-8')
subject = 'Python SMTP mail test'
msg['Subject'] = Header(subject,'utf-8')
try:
smtp = smtplib.SMTP_SSL(mail_server,mail_server_port)
smtp.login(mail_user,mail_pass)
smtp.sendmail(from_addr,to_addr,msg.as_string())
smtp.quit()
print('邮件发送成功')
except smtplib.SMTPException:
print('Error:邮件发送失败!!!')
3.邮件附件
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
mail_server = 'smtp.163.com'
mail_server_port = 465
mail_user = 'msun1996@163.com'
mail_pass = '******'
from_addr = 'msun1996@163.com'
to_addr = ['msun1996@163.com']
#创建一个带附件实例
msg = MIMEMultipart()
msg['From'] = Header('msun','utf-8')
msg['To'] = Header('Test','utf-8')
subject = 'Python SMTP mail test'
msg['Subject'] = Header(subject,'utf-8')
#邮件正文
msg.attach(MIMEText('Ptthon SMTP mail test...','plain','utf-8'))
#构造附件
att = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8')
att["Content-Type"] = 'application/octet-stream'
att["Content-Disposition"] = 'attachment; filename="test.txt"'
msg.attach(att)
- try:
smtp = smtplib.SMTP_SSL(mail_server,mail_server_port)
smtp.login(mail_user,mail_pass)
smtp.sendmail(from_addr,to_addr,msg.as_string())
smtp.quit()
print('邮件发送成功')
except smtplib.SMTPException:
print('Error:邮件发送失败!!!')
4.邮件图片(图片存放于附件中)
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
mail_server = 'smtp.163.com'
mail_server_port = 465
mail_user = 'msun1996@163.com'
mail_pass = '******'
from_addr = 'msun1996@163.com'
to_addr = ['msun1996@163.com']
msg = MIMEMultipart()
msg['From'] = Header('msun','utf-8')
msg['To'] = Header('Test','utf-8')
subject = 'Python SMTP mail test'
msg['Subject'] = Header(subject,'utf-8')
msgAlternative = MIMEMultipart('alternative')
msg.attach(msgAlternative)
mail_msg = '''
<p>Python SMTP mail test...</p>
<p>图片</p>
<img src='cid:image' width='30' height='30'>
'''
#邮件正文
msg.attach(MIMEText(mail_msg,'html','utf-8'))
#指定图片为当前目录
fp = open('logo.png','rb')
msgImage = MIMEImage(fp.read())
fp.close()
#定义图片ID,在HTML引用
msgImage.add_header('Content-ID','<image>')
msg.attach(msgImage)
try:
smtp = smtplib.SMTP_SSL(mail_server,mail_server_port)
smtp.login(mail_user,mail_pass)
smtp.sendmail(from_addr,to_addr,msg.as_string())
smtp.quit()
print('邮件发送成功')
except smtplib.SMTPException:
print('Error:邮件发送失败!!!')
POP3收取邮件
pop3收取步骤:
1.用poplib模块把源始文件下载到本地
2.用email模块解析原始文本,还原邮件对象
poplib模块
poplib建立对象
poplib.POP3(server)
server : pop服务器对象
poplib对象方法
user(username) 发送用户名到服务器,等待服务器返回信息
pass_(password) 密码
stat() 返回邮箱的状态,返回2元祖(消息的数量,消息的总字节)
list([msgnum]) stat()的扩展,返回一个3元祖(返回信息, 消息列表, 消息的大小),如果指定msgnum,就只返回指定消息的数据
retr(msgnum) 获取详细msgnum,设置为已读,返回3元组(返回信息, 消息msgnum的所以内容, 消息的字节数),如果指定msgnum,就只返回指定消息的数据
dele(msgnum) 将指定消息标记为删除
quit() 登出,保存修改,解锁邮箱,结束连接,退出
pop接收实例
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
from datetime import datetime
email = 'msun1996@163.com'
passwd = 'h19960304'
pop_server = 'pop.163.com'
def get_email():
server = poplib.POP3_SSL(pop_server,'995')
# 可以打开或关闭调试信息:
# server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字:
print(server.getwelcome().decode('utf-8'))
server.user(email)
server.pass_(passwd)
#邮件数量和占有空间
print('Messages: %s. Size: %s' % server.stat())
#list()返回所有邮件编号
resp_one,mails,octets_one = server.list()
#查看返回列表
#print(mails)
#获取最新的一封邮件,索引号为1开始
index = len(mails)
resp_two, lines, octets_two = server.retr(index)
#lines存储邮件原始文本每行并进行解析
msg_content = b'\r\n'.join(lines).decode('utf-8')
msg = Parser().parsestr(msg_content)
#可以根据邮件索引从服务器删除邮件
#server.dele(index)
#关闭邮件
server.quit()
print_info(msg)
#编码设置
def guess_charset(my_msg):
charset = my_msg.get_charset()
if charset is None:
content_type = my_msg.get('Content-Type', '').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
return charset
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
# indent用于缩进显示,递归打印
def print_info(my_msg, indent=0):
if indent == 0:
for header in ['From', 'To','Subject']:
value = my_msg.get(header, '')
if value:
if header == 'Subject':
value = decode_str(value)
else:
hdr, addr = parseaddr(value)
name = decode_str(hdr)
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
if my_msg.is_multipart():
parts = my_msg.get_payload()
for n, part in enumerate(parts):
print('%spart %s' % (' ' * indent, n))
print('%s-----------------------------------' % ' ' * indent)
print_info(part, indent + 1)
else:
content_type = my_msg.get_content_type()
if content_type == 'text/plain' or content_type == 'text/html':
content = my_msg.get_payload(decode=True)
charset = guess_charset(my_msg)
if charset:
content = content.decode(charset)
print('%sText: %s' % (' ' * indent, content + '...'))
else:
print('%sAttachment: %s' % (' ' * indent, content_type))
if __name__ == '__main__':
get_email()