1.SMTP发送邮件:
# Python 3.6
# Author:宿命小哥哥
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
import smtplib
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), addr))
def send_mail(to_list, sub):
msg = MIMEMultipart()
msg['From'] = _format_addr('发送者 <%s>' % from_addr)
msg['To'] = _format_addr('接受者 <%s>' % to_addr).join(to_list)
msg['Subject'] = Header(sub, 'utf-8').encode()
txt = MIMEText('发送测试!!!', _subtype='plain', _charset='utf8')
msg.attach(txt)
h = MIMEText('Hello,这是一个Python的SMTP程序发送来的邮件
' +
'send by 宿命小哥哥...
' +
'', _subtype='html', _charset='utf8')
msg.attach(h)
# 添加附件
img = MIMEText(open('F:\\1.png', 'rb').read(), 'base64', 'utf-8')
img["Content-Type"] = 'application/octet-stream'
img["Content-Disposition"] = 'attachment; filename="Picture.png"'
# filename是自定义附件名字
msg.attach(img)
att1 = MIMEText(open('F:\\1.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
att1["Content-Disposition"] = 'attachment; filename="text.txt"'
msg.attach(att1)
try:
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
# 加密SMTP会话
# server.starttls()
# 打印出和SMTP服务器交互的所有信息
server.set_debuglevel(1)
# 登录SMTP服务器
server.login(from_addr, password)
# 发邮件
server.sendmail(from_addr, to_addr, msg.as_string())
server.quit()
return True
except:
print("出现错误!")
return False
if __name__ == '__main__':
# 邮件发送方的邮箱账号
from_addr = input('From: ')
# 邮件发送方的邮箱密码
password = input('Password: ')
# 邮件接收方的邮件地址
to_addr = input('To: ')
# 邮件传送协议服务器
smtp_server = input('server: ')
# 使用SSL,端口号465或587
smtp_port = input('port: ')
Sub = input('Subject: ')
if send_mail(from_addr, Sub):
print("发送成功")
else:
print("发送失败")
2.POP3接收邮件:
# Python 3.6
# Author:宿命小哥哥
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
import poplib
# indent用于缩进显示:
def print_info(msg, indent=0):
# 初始分析
if indent == 0:
# 遍历获取:发件人,收件人,主题
for header in ['From', 'To', 'Subject']:
# 获得对应的内容
value = msg.get(header, '')
# 有内容
if value:
# 如果是主题
if header == 'Subject':
# 解码主题
value = decode_str(value)
else:
# parseaddr:解析字符串中的email地址
hdr, addr = parseaddr(value)
# 解码主题
name = decode_str(hdr)
# 合成内容
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
# 如果消息由多个部分组成,则返回True。
if (msg.is_multipart()):
# 返回list,包含所有的子对象
parts = msg.get_payload()
# enumerate将其组成一个索引序列,利用它可以同时获得索引和值
for n, part in enumerate(parts):
# 打印消息模块编号
print('%spart %s' % (' ' * indent, n))
# 打印分割符号
print('%s---------------------------------------' % (' ' * indent))
# 递归打印
print_info(part, indent + 1)
else:
# 递归结束条件,打印最基本模块;返回消息的内容类型。
content_type = msg.get_content_type()
# 如果是text类型或者是html类型
if content_type == 'text/plain' or content_type == 'text/html':
# 返回list,包含所有的子对象,开启解码
content = msg.get_payload(decode=True)
# 猜测字符集
charset = guess_charset(msg)
# 字符集不为空
if charset:
# 解密
content = content.decode(charset)
# 打印内容
print('%sText: %s' % (' ' * indent, content + '...'))
else:
print('%sAttachment: %s' % (' ' * indent, content_type))
# 邮件的Subject或者Email中包含的名字都是经过编码后的str,要正常显示就必须decode
def decode_str(s):
# 在不转换字符集的情况下解码消息头值,返回一个list
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
# 文本邮件的内容也是str,还需要检测编码,否则,非UTF-8编码的邮件都无法正常显示:
def guess_charset(msg):
# 得到字符集
charset = msg.get_charset()
if charset is None:
# lower:所有大写字符为小写
content_type = msg.get('Content-Type', '').lower()
# find:检测字符串中是否包含子字符串,返回charset=头字符的位置
pos = content_type.find('charset=')
if pos >= 0:
# strip:移除字符串头尾指定的字符(默认为空格)
charset = content_type[pos + 8:].strip()
return charset
if __name__ == '__main__':
# 输入邮件地址, 口令和POP3服务器地址:
email = input('Email: ')
password = input('Password: ')
pop3_server = input('POP3 server: ')
# 连接到POP3服务器:
server = poplib.POP3_SSL(pop3_server)
# 可以打开或关闭调试信息:
server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字:
print(server.getwelcome().decode('utf-8'))
# 身份认证:
server.user(email)
server.pass_(password)
# stat()返回邮件数量和占用空间:
print('Messages: %s. Size: %s' % server.stat())
# list()返回所有邮件的编号:
resp, mails, octets = server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
print(mails)
# 获取最新一封邮件, 注意索引号从1开始:
index = len(mails)
resp, lines, octets = server.retr(index)
# lines存储了邮件的原始文本的每一行,
# 可以获得整个邮件的原始文本:
msg_content = b'\r\n'.join(lines).decode('utf-8')
# 解析出邮件:
Msg = Parser().parsestr(msg_content)
print_info(Msg)
# 可以根据邮件索引号直接从服务器删除邮件:
# server.dele(index)
# 关闭连接:
server.quit()
3.IMAP接收邮件:
# Python 3.6
# Author:宿命小哥哥
import imaplib
import email
# 解析邮件方法(区分出正文与附件)
def parseEmail(e):
# 解析邮件/信体
# 循环信件中的每一个mime的数据块
for part in e.walk():
# 这里要判断是否是multipart,是的话,里面的数据是一个message 列表
if not part.is_multipart():
charset = part.get_charset()
print('charset: ', charset)
contenttype = part.get_content_type()
print('content-type', contenttype)
# 如果是附件,这里就会取出附件的文件名
if contenttype in ['image/jpeg', 'image/png']:
image_file = part.get_payload(decode=True)
image_file_name = part.get_filename()
print('content-type', image_file_name)
name = part.get_param("name")
if name:
# 有附件
# 下面的三行代码只是为了解码象=?gbk?Q?=CF=E0=C6=AC.rar?=这样的文件名
fh = email.Header.Header(name)
fdh = email.Header.decode_header(fh)
fname = fdh[0][0]
print('附件名:', fname)
# 解码出附件数据,然后存储到文件中
attach_data = part.get_payload(decode=True)
try:
# 注意一定要用wb来打开文件,因为附件一般都是二进制文件
f = open(fname, 'wb')
except:
print('附件名有非法字符,自动换一个')
f = open('aaaa', 'wb')
f.write(attach_data)
f.close()
else:
# 不是附件,是文本内容,解码出文本内容,直接输出
print(part.get_payload(decode=True).decode('utf-8'))
def geimail(host, port, mail, password):
M = imaplib.IMAP4_SSL(host, port)
print(M)
try:
try:
M.login(mail, password)
print('成功登陆邮箱')
except Exception as e:
print('登陆错误: %s' % e)
M.close()
# 选取收件箱
M.select('INBOX')
# 获取未读邮件信息
unseen = M.search(None, 'Unseen')
unseen_list = unseen[1][0].split()
print('未读邮件数:', len(unseen_list))
# 想获取最新一封的做法是:
typ, data = M.search(None, 'ALL')
msglist = data[0].split()
print('已读邮件数:', len(msglist))
new = msglist[len(msglist) - 1]
try:
typ, data = M.fetch(new, '(RFC822)')
msg = email.message_from_string(data[0][1].decode('utf-8'))
sub = email.header.decode_header(msg.get('subject'))[0]
print("From:", email.utils.parseaddr(msg.get("from"))[1])
print("To:", email.utils.parseaddr(msg.get("to"))[1])
if not email.utils.parseaddr(msg .get_all('cc'))[1]:
print('Cc: 无抄送者')
else:
print('Cc:', email.utils.parseaddr(msg .get_all('cc'))[1])
print("Subject:", sub[0].decode(sub[1]))
print("Date:", msg["Date"])
print("_______________________________")
return msg
except Exception as e:
print('got msg error: %s' % e)
M.close()
except Exception as e:
print('imap error: %s' % e)
M.close()
M.logout()
if __name__ == "__main__":
# 输入邮件地址, 口令和服务器地址:
Email = input('Email: ')
Password = input('Password: ')
IMAP_server = input('IMAP server: ')
IMAP_port = input('IMAP port: ')
print('【1】开始获取最新一封邮件...')
Msg = geimail(IMAP_server, IMAP_port, Email, Password)
print('【2】开始解析邮件内容...')
parseEmail(Msg)