程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python: 郵件收發-以QQ郵箱為例

編輯:Python

發郵件比較簡單。但收郵件卻要麻煩一些。這裡涉及到郵件的內容、標題、發件人等解析。
下面以QQ郵箱為例。需要注意的是,一些公司exchange郵箱往往需要公司在後台開啟授權。

import smtplib
from email.header import Header # 用來對Email標題進行編碼
from email.mime.text import MIMEText # 負責構造文本
from email.mime.image import MIMEImage # 負責構造圖片
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase # 添加附件的時候用到
from email.utils import parseaddr, formataddr
from email.mime.application import MIMEApplication
## 需要進行pop設置的郵箱有:ailiyun、qq,163等
#設置登錄及服務器信息
import poplib
#import settings
import imaplib
import email #導入兩個庫
import base64
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
class UserInfo:
def __init__(self,mail_address,mail_password):
self.mail_user_name = mail_address.split("@")[0] # 郵件用戶名
self.mail_password = mail_password
self.mail_address = mail_address
## 收發郵箱的配置
class MailSettings:
# port => 126,: 25 qq和163: 465 ,ssl: 443,ailiyun:993
def __init__(self,name,send_host,send_port,server_host,server_port,is_ssl_host ):
self.send_port = send_port
self.send_host = send_host
self.server_host = server_host
self.server_port = server_port
self.is_ssl_host= is_ssl_host
self.name = name
def get_attaches():
pass
## 指一次郵件內容,發送多個不同的收件人
## 如果一次郵件發送,只顯示一個收件人,如果有N個收件人,就需要定義N個郵件的message
def set_email_from_and_to_info(user,receivers,subject):# subject 是一個說明
#添加一個MIMEmultipart類,處理正文及附件
message = MIMEMultipart()
message['From'] = user.mail_address
message['To'] = ", ".join(receivers) ## 可以針對多個,這個會在這封郵件上顯示所有的發送的郵件
message['Subject'] = subject
return message
## 可以處理各類附件
def set_content_and_attaches(message,content_body,content_type,attache_paths):
#正文通常有html和普通文本(plain)格式; html格式比較方便排版和制表
content = MIMEText(content_body, content_type, 'utf-8') ## plain 和 html不同的方式
message.attach(content) ## 正文
## 下面處理相關的附件
attach_num =0
for attach_path in attache_paths:
attach_num += 1
attach_name = get_filename_from_path(attach_path) ## 把路徑拆成文件
file_name = "附件_:"+ str(attach_num) + ":" + attach_name
_part = MIMEApplication(open(attach_path,'rb').read()) ## 附件1
_part.add_header('Content-Disposition', 'attachment', filename=file_name)
message.attach(_part)
return message
def get_filename_from_path(path):
split_info = path.split("\\")
return split_info[-1]
def send_email(message,user,mail_info,receivers): ## to be continued
try:
if mail_info.is_ssl_host:
print("smtp_ssl connect -> ")
smtp = smtplib.SMTP_SSL(mail_info.send_host,mail_info.send_port) ##
#smtp.set_debuglevel(2) ## 如果需要打印出調試信息的話
else:
print("smtp connect ->")
smtp = smtplib.SMTP()
smtp.connect(mail_info.send_host,mail_info.send_port)
smtp.ehlo()
smtp.starttls()
#smtp.set_debuglevel(2) ## 如果需要打印出調試信息的話
print("login .....")
smtp.login(user.mail_user_name,user.mail_password)
## 單獨發送還是統一發送
print("login 成功! send_mail....")
#print(message)
smtp.sendmail(user.mail_address,receivers,message.as_string()) ##單獨發送;不是集合發送; 統一發送是另外模式
print('郵件發送成功!',receivers)
smtp.quit()
except smtplib.SMTPException as e:
print('郵件發送失敗,具體信息:',e)
# SMTP 協議用於發送郵件,POP3 和 IMAP 協議用於接收郵件
def pop_receive_email(user,mail_info):
try:
# 連接到POP3服務器:
server = poplib.POP3(mail_info.server_host) #settings.pop3_server)
# 身份認證:
server.user(user.mail_user_name) # mail_address ?
server.pass_(user.mail_password)
# stat()返回郵件數量和占用空間:
print('Messages: %s. Size: %s' % server.stat())
# list()返回所有郵件的編號:
resp, mails, octets = server.list()
# 可以查看返回的列表類似[b'1 82923', b'2 2184', ...]
# 獲取最新一封郵件, 注意索引號從1開始:
latest_mail_index = len(mails)
resp, lines, octets = server.retr(latest_mail_index)
# lines存儲了郵件的原始文本的每一行,
# 可以獲得整個郵件的原始文本:
msg_content = b'\r\n'.join(lines).decode('gbk') ## utf-8
# 稍後解析出郵件:
msg = Parser().parsestr(msg_content)
print(msg)
# 郵件索引號直接從服務器刪除郵件
# server.dele(index)
# 關閉連接:
server.quit()
except BaseException as e:
print(e)
def imap_receive_email(user,mail_info):
try:
M = imaplib.IMAP4_SSL(host = mail_info.server_host,port = mail_info.server_port)
print('已連接服務器')
M.login(user.mail_user_name,user.mail_password)
print('已登陸')
print(M.noop())
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
# print('Message %s\n%s\n' % (num, data[0][1]))
# print(data[0][1].decode('utf-8'))
msg = email.message_from_string(data[0][1].decode('gbk')) # bug
print(msg)
break
M.close()
M.logout()
except BaseException as e:
print(e)
# 主題解析
def parser_subject(msg):
subject = msg['Subject']
value, charset = decode_header(subject)[0]
if charset:
value = value.decode(charset)
print('郵件主題: {0}'.format(value))
return value
# 郵件信息解析
def parser_address(msg):
hdr, addr = parseaddr(msg['From'])
# name 發送人郵箱名稱, addr 發送人郵箱地址
name, charset = decode_header(hdr)[0]
if charset:
name = name.decode(charset)
print('發送人郵箱名稱: {0},發送人郵箱地址: {1}'.format(name, addr))
## 如何收特定日期的郵件?
## 郵件的接收是全量推送?
## 郵件的解析,如何落附件?
qq_send_host = 'smtp.qq.com'#
qq_server_host = "imap.qq.com"
qq_send_port = 465 #465
qq_server_port = 993 ## 收郵件
qq_is_ssl_host = True
mail_address = '*****@qq.com'
mail_pass ='n********' ## qq是授權碼,不是賬戶密碼
receivers = ['h*****@sina.com.cn',"s****@163.com"]
subject = "標題:這是測試郵件,請不要回復!"
content_body = "正文:這是測試郵件的正文"
content_type = "plain"
#content_html = r'D:\mail\content.html' # 正文html空模版
attach_01 = r"D:\mail\df_y.csv" # xlsx
attach_02 = r'D:\mail\簽名.jpg' #jpg
attach_03 = r'D:\mail\上海房地產市場最新報告.pdf' #pdf
attaches = [attach_01,attach_02,attach_03]
user = UserInfo(mail_address,mail_pass)
mail_settings = MailSettings("qq",qq_send_host,qq_send_port,qq_server_host,qq_server_port,qq_is_ssl_host)
mode = 1 # 0 :=>發郵件; 1: 收郵件
if mode ==0:
message = set_email_from_and_to_info(user,receivers,subject)
message = set_content_and_attaches(message,content_body,content_type,attaches)
#print("message :",message)
send_email(message,user,mail_settings,receivers)
else:
if 'imap' in mail_settings.server_host: # imap
imap_receive_email(user,mail_settings)
else: # pop3
pop_receive_email(user,mail_settings)

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved