1. 程式人生 > >利用python寫郵件管理

利用python寫郵件管理

Email

郵件歷史。。。

  • 起源

    • 就是通訊的一個發展,懶得打字了省略了,以後再查吧

  • 管理程式

    • 一些讓郵件普及的郵件公司

郵件的工作流程

  • MUA(MailUserAgent)郵件使用者代理

  • MTA(MailTransferAgent)郵件傳輸代理

  • MDA(MailDeliveryAgent)郵件投遞代理

  • 流程

    • MUT->MTA

    • qq MTA->...........................->sina MTA

    • sina MTA->.........................->sina MDA

    • sina MDA->MUA(FoxMail/outlook)郵件下載到本地電腦

  • 編寫程式

    • 傳送 MUA->MTA 協議

    • 接收 MTA->MDA 協議

  • 準備工作

    • 註冊郵箱

    • 第三方郵箱進行設定

      • 進入設定中心

      • 取得授權碼

      • 案例07傳送純文字郵件‘

      • import smtplib 
        from email.mime.text import MIMEText
        
        #MIMEText的主要引數有3個
        #1。郵件內容
        #2。MIME子型別,在這裡用plain代表text格式的檔案
        #3.郵件的編碼格式
        msg = MIMEText('這是一封文字格式的郵件','plain','utf-8')
        
        #傳送email的地址,需要更改為對應的郵件地址
        from_addr = '
        [email protected]
        ' #授權密碼,大多數的郵箱在使用第三方軟體時,都需要驗證金鑰,這裡不是指郵箱的密碼 from_pwd = 'XXXXXXXXXXX' #收件人 to_addr = '[email protected]' #輸入smtplib伺服器地址 #此處根據不同的郵件服務商有不同的值 #現在基本任何一家郵件服務商在開啟第三方郵件的時候都需要開啟服務 #TX QQ郵箱的smtplib地址時smtplib.qq.com smtp_srv = 'smtplib.qq.com' try: srv = smtplib.SNTP_SSL(smtp_srv.encode(),465) #這裡的465時QQ郵箱的埠 #登陸郵箱,任何的郵箱在使用之前都必須的登陸 srv.login(from_addr,from_pwd) #傳送郵件 #三引數,傳送地址,接受的地址(必須時list格式),傳送內容時字串格式 srv.sendmail(from_addr,[to_addr],msg.as_String()) srv.quit() except Exception as e: print(e)

         

  • Python for mail

    • SMTP協議負責傳送郵件

      • 使用Email模組構建郵件-純文字案例V07

      • HTML格式郵件傳送

        • 準備HTML程式碼作為內容

        • 把郵件的subtype設為html

        • 傳送

        • 案列V08

        • import  smtplib
          from email.mime.text import MIMEText
          #MIMEText的主要的三個引數
          #1。郵件內容
          #2。MIME子型別的格式 這裡時HTML所以是html
          #3.郵件的編碼格式
          msg_content = """
                                  <!DOCTYPE html>
                          <html lang="en">
                              <head>
                                  <meta charset="UTF-8">
                                  <title>Title</title>    
                              </head>
                              <body>
                              <h1>這是一封HTML格式的郵件</h1>
                              </body>
                          </html>
          """
          #傳送郵件的地址
          from_addr = '[email protected]'
          #傳送郵件的密碼
          from_pwd = 'XXXXXXXXXXx'
          #收件人
          to_addr = '[email protected]'
          
          #輸入SMTP伺服器地址
          smtp_srv = 'smtp.qq.com'
          try:
              srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
              #登陸郵箱
              srv.login(from_addr,from_pwd)
              #傳送郵件
              srv.sendemail = (from_addr,[to_addr],msg_content.as_toString())
              srv.quit()
          except Exception as e:
              print(e)
          

           

      • 傳送帶附件的郵件

        • 可以看作有一個文字郵件和一個附件的合體

        • 需要使用MIMEltaipart格式構建

        • 新增一個MIMEBase或者MEME text作為附件

        • 案列V09

        • import smtplib
          from email.mime.text import MIMEText
          from email.mime.text import MIMEBase,MIMMultipart #構建基礎郵件時使用
          
          mail_mul = MIMEMulipart()
          #構建郵件正文
          main_text = MIMEText("這是郵件的正文",'plain','utf-8')
          #把構建的正文附加到郵件中
          mail_mul.attach(mail_text)
          
          #構建附件,需要從本地讀入
          #開啟一個本地檔案
          with open('a.txt','rb') as f:
              s = f.read()
              #設定附件的MIME檔名
              m = MIMEText(s,'base64','utf-8')
              m['Content-Type'] = 'application.octet-stream'
              #需要注意的
              #1.attachment後的分號時英文狀態
              #2.filename 後面需要英文包裹,注意外面的引號錯開
              m['Content-Dispostion'] = 'attachment;filename="a.txt"'
              #新增MIMEMultipation
              mail_mul.attach(m)
          
              #傳送郵件
              from_addr = '[email protected]'
              from_pwd = 'XXXXXXXXx'
              to_addr = '[email protected],com'
              smtp_srv = 'sntp.qq.com'
          try:
              srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
              #登陸郵箱
              srv.load(from_addr,from_pwd)
              srv.sendmail(from_addr,[to_addr],mail_mul.as_string())
              srv.quit()
          except Exception as e:
              print(e)

           

      • 新增郵件頭,抄送等資訊

        • mail['From'] 表示傳送者的資訊,包括姓名和郵件

        • mail['To'] 表示接收者資訊,包括姓名和郵件地址

        • mail['Subject']表示摘要或者主題資訊

        • 案例V10

      • 同時支援html和text格式

        • 構建一個MIMEMultipart格式的郵件

        • MIMEMultipart的subtype設定成alterbalive

        • 新增html 檔案和text檔案

        • import smtplib
          from email.mime.text import MIMEText
          from email,mime.multipart import MIMEMUltipart
          #構建一個MIMEMultipart郵件
          msg = MIMEMultapart('alternative')
          #構建一個HTML格式的郵件內容
          html_content = """
              <!DOCTYPE html>
                          <html lang="en">
                              <head>
                                  <meta charset="UTF-8">
                                  <title>Title</title>    
                              </head>
                              <body>
                              <h1>這是一封HTML格式的郵件</h1>
                              </body>
                          </html>
          """
          msg_html = MIMEText(html_content,'html','utf-8')
          msg.attach(msg_html)
          
          #構建一個文字格式的郵件
          msg_text = MIMEText("這是文字格式的郵件",'plain','utf-8')
          msg.attach(msg_text)
          
          from_addr = '[email protected]'
          from_pwd = 'XXXXX'
          to_addr = "[email protected]"
          smtp_srv = 'smtp.qq.com'
          try:
              srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
              srv.login(from_addr,from_pwd)
              srv_sendmail(from_addr,[to_addr],msg.as_tostring())
              srv.quit()
          except Exception as e:
              print(e)

           

      • 使用smtplib模組傳送郵件

    • POP3協議接受郵件

      • 本質上講是從MDA到MTA的一個過程

      • 從MDA下載下來的是一個完整的郵件結構體,需要解析才能的帶每個具有

      • 步驟:

        • 1.用poplib下載郵件結構體原始內容

          • 1.準備相應的內容(郵件的內容,密碼。pop3例項)

          • 2.身份驗證

          • 3.一般會先得到郵箱內郵件的整體列表

          • 4.根據相應的序號,得到某一封信的資料流

          • 5.利用解析函式進行解析出相應的郵件結構體

        • 2.emai解析郵件的具體內容

          • 案例V12

          • #匯入相關的包
            #poplib負責相關的MDA到MUA的下載
            import poplib
            from email.parser import Parser
            from email.header import decode_header
            from email.utils import parseaddr
            
            #得到郵件的原始內容
            #這個過程主要看負責從MDA帶MUA的下載並且使用Parse粗略的解析
            def getMsg():
                #準備相應的資訊
                email = '[email protected]'
                #郵箱的授權碼
                pwd = 'azyktnytwqlmbdeb'
                #pop3的伺服器地址 預設埠995
                pop3_srv = 'pop.qq.com'
                #SSL代表安全通道
                srv = poplib.POP3_SSL(pop3_srv)
                #user代表Email地址
                srv.user(email)
                #pass_代表密碼
                srv.pass_(pwd)
                #一下操作根據業務內容具體使用
                #stat返回郵件的數量和佔用的空間
                #注意stat返回一個tuple格式
                msgs,counts = srv.stat()
                print("messages:{0},Size{1}".format(msgs,counts))
                #list返回所有的郵件編號列表
                #malis返回所有郵件編號列表
                rsp,mails,octets = srv.list()
                #可以檢視返回mails列表類似
                print(mails)
                #獲取最新一封郵件,注意,郵件的索引號從1開始,最新的郵件索引號最高
                index = len(mails)
                #retr 負責返回一個具體索引號的一封信的內容,此內容不具有可讀性
                #lines 儲存郵件的最高原始文字的每一行
                rsp,lines,octets = srv.retr(index)
                #獲取整個郵件的原始文字
                msg_count = b'\r\n'.join(lines).decode('utf8')
                #解析出郵件的整個結構體
                #引數時解碼後的郵件整體
                msg = Parser().parsestr(msg_count)
                #關閉連結
                srv.quit()
                return msg
            #
            #詳細解釋得到的郵件內容
            #msg表示郵件的原始內容
            #idnent代表的是郵件的巢狀層級
            
            def parseMsg(msg,indent=0):
                '''
                1.郵件可能是完全巢狀
                2.郵件只有一個From,To,Subject之類的資訊
                :param msg:
                :param indent: 描述郵件裡面的幾個郵件的MIMEXXX型別的內容,展示的時候進行縮排
                :return:
                '''
                #想辦法提取頭部資訊
                #只有在第一層的郵件中才會有相關資訊內容
                #此內容只有一個
                if indent == 0:
                    for header in ['From','To','Subject']:
                        #使用get可以避免如果沒有相關關鍵字報錯的可能性
                        #如果沒有關鍵字“From"在使用msg["From"]時會報錯
                        value = msg.get(header,'')
                        if value:
                            #Subject中的內容直接解碼就可以,他是字串型別
                            if header == 'Subject':
                                value = decodeStr(value)
                            #如果是From和To欄位,則內容的大概是‘我的郵箱<[email protected]>’這種格式
                            else:
                                hdr,addr = parseaddr(value)
                                name = decodeStr(hdr)
                                #最終的返回型別如“我的郵箱是<[email protected]>”
                                value = "{0}<{1}>.".format(name,addr)
                        print("{0},{1}:{2}".format(indent,header,value))
                #接下來關注郵件內容本身
                #郵件內容中,有可能是multipart型別,也有可能是普通郵件型別
                #下面的解析使用遞迴的方法
                if (msg.is_multipart()):
                    #如果是multipart型別則呼叫遞迴解釋
                    #得到多部分郵件的一個基礎郵件部分
                    parts = msg.get_payload()
                    #enumerate函式是內建函式
                    #作用是將一個列表,此處是parts,生成一個有索引和parts原內容生成的列表
                    #例如:enumerate(['a','b','c'])結果是:[(1,'a'),(2,'b'),(3,'c')]
                    for n,part in enumerate(parts):
                        #一個字串乘以一個數字的意思就是對這個字串進行n倍擴充套件
                        #例如("aa"*2) = 'aaaa'
                        print("{0}spart:{1}".format(' '*indent,n))
                        parseMsg(part,indent+1)
                else:#基礎型別
                    #get_content_type是系統函式,得到內容的型別
                    content_type = msg.get_content_type()
                    #text/plain,或者是text/html是固定值
                    if content_type == 'text/plain' or content_type == 'text/html':
                        content = msg.get_payload(decode=True)
                        charset = gussCharset(msg)
                        if charset:
                            content = content.decode(charset)
                        print("{0}text:{1}".format(indent,content))
                    else:#不是文字內容,因該是附件
                        print('{0}Attachment:{1}'.format(indent,content_type))
            def decodeStr(s):
                '''
                s代表一封郵件中的from,to,Subject中的任意一項
                對s進行解碼,解碼是通過編碼的逆過程
                :param s:
                :return:
                '''
                value,charset = decode_header(s)[0]
                #charset完全可能為空
                if charset:
                    #如果指定編碼,則用指定的編碼格式進行解碼
                    value = value.decode(charset)
                return value
            def gussCharset(msg):
                '''
                猜測郵件的編碼格式
            
                :param msg:
                :return:
                '''
                #呼叫現成的函式
                charset = msg.get_charset()
                if charset is None:
                    #找到相應的內容型別轉換成小寫
                    content_type = msg.get("Content-Type","").lower()
                    pos = content_type.find('charset=')
                    if pos > 0:
                        #如果包含charset,則內容為charset=XXX
                        charset = content_type[pos+8:].strip()
                return charset
            if __name__ == '__main__':
                #得到郵件的原始內容
                msg = getMsg()
                print(msg)
                #精確解析郵件的內容
                parseMsg(msg,0)