自動化打包續(xù)(Python發(fā)送郵件)

起因

機器運行的越來慢型将,每天啟動模擬器需要十幾分鐘够挂,打個發(fā)布包也需要十分鐘左右钞速,實在受不了這個速度贷掖,一咬牙一跺腳就把機器格式化了(其實是作死行為,為后來半個月工作帶來了不小的麻煩)渴语。重裝部分軟件后發(fā)現(xiàn)我的打包腳本郵件有時候發(fā)送郵件到個別郵箱時苹威,郵件無法準時到達。當時是怎么配置發(fā)送環(huán)境的資料也隨電腦格式化煙消云散了驾凶。更不想再去重走回頭路牙甫,按照原來的方法一步步去配置。最近也是在學習Python狭郑,有這樣的一個機會學以致用使用Python發(fā)送郵件貌似不能夠錯過腹暖。

需求

  • 1.發(fā)送郵件。能夠正常翰萨、準時脏答、穩(wěn)定發(fā)送有標題、正文并且?guī)в懈郊泥]件。
  • 2.能夠在Mac終端使用命令行操作操作殖告。能與Shell打包腳本之間參數(shù)傳遞
  • 3.發(fā)送郵件時候能夠直觀看到發(fā)送的進度阿蝶,上傳的網絡速率(目前尚未實現(xiàn))等等

實現(xiàn)過程

發(fā)送帶附件的郵件

python使用smtp發(fā)送郵件。關于這個我覺得沒有什么好說的黄绩,詳情見菜鳥教程Python 2.7教程

獲取郵件發(fā)送進度和網速

有時候我希望看到郵件的發(fā)送進度羡洁,但smtp自身并不能直接顯示郵件發(fā)送的進度。我們可以通過每秒讀取文件數(shù)據(jù)占總量百分比來實現(xiàn)需求爽丹。閱讀其源碼找到如下代碼對其做一定拓展貌似能滿足我們的需求筑煮。

def data(self,msg):
        """SMTP 'DATA' command -- sends message data to server.

        Automatically quotes lines beginning with a period per rfc821.
        Raises SMTPDataError if there is an unexpected reply to the
        DATA command; the return value from this method is the final
        response code received when the all data is sent.
        """
        self.putcmd("data")
        (code,repl)=self.getreply()
        if self.debugle vel >0 : print "data:", (code,repl)
        if code != 354:
            raise SMTPDataError(code,repl)
        else:
            q = quotedata(msg)
            if q[-2:] != CRLF:
                q = q + CRLF
            q = q + "." + CRLF
            self.send(q)
            (code,msg)=self.getreply()
            if self.debuglevel >0 : print "data:", (code,msg)
            return (code,msg)

我們可以在其發(fā)送過程中獲取每秒鐘監(jiān)測到發(fā)送的字節(jié)數(shù),并將其輸出出來粤蝎,這樣就能獲取其發(fā)送進度和網速了.

          global starttime,sendByteBySec
          endtime = datetime.datetime.now()
          percent = 100. * progress / total
          stdout.write('\r')
          starttime = endtime;
          speedNum = (progress - sendByteBySec)/1024
          if (endtime - starttime).seconds >=1:
             # starttime = endtime;
             # speedNum = (progress - sendByteBySec)/1024
             stdout.write("%s bytes sent of %s [%2.0f%%]|Speed: [%2.0f%%]" % (progress, total, percent,speedNum))
             # sendByteBySec = progress
          else:
              # starttime = endtime;
              # speedNum = (progress - sendByteBySec)/1024
              stdout.write("%s bytes sent of %s [%2.0f%%]|Speed: [%2.0f%%]" % (progress, total, percent,speedNum))

          sendByteBySec = progress
          stdout.flush()
          # print (endtime - starttime).seconds
          if percent >= 100: stdout.write('\n')

完整代碼如下

# !/usr/bin/python
# -*- coding: utf-8 -*-

# import smtplib
from smtplib import SMTP, quotedata, CRLF, SMTPDataError
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
from email.MIMEMultipart import MIMEMultipart
from email.mime.base import MIMEBase
from sys import stderr, stdout
import os,sys, time

class ExtendedSMTP(SMTP):
  def data(self, msg):
    self.putcmd("data")
    (code,repl)=self.getreply()
    if self.debuglevel > 0 : print >> stderr, "data:", (code, repl)
    if code != 354:
      raise SMTPDataError(code,repl)
    else:
      q = quotedata(msg)
      if q[-2:] != CRLF:
        q = q + CRLF
      q = q + "." + CRLF

      # begin modified send code
      chunk_size = 2048
      bytes_sent = 0

      while bytes_sent != len(q):
        chunk = q[bytes_sent:bytes_sent+chunk_size]
        self.send(chunk)
        bytes_sent += len(chunk)
        if hasattr(self, "callback"):
          self.callback(bytes_sent, len(q))
      # end modified send code

      (code,msg)=self.getreply()
      if self.debuglevel >0 : print>>stderr, "data:", (code,msg)
      return (code,msg)


def sendMail(filePath,fileName,appName):
    def _format_addr(s):
        name, addr = parseaddr(s)
        return formataddr(( \
            Header(name, 'utf-8').encode(), \
            addr.encode('utf-8') if isinstance(addr, unicode) else addr))

    def callback(progress, total):
          percent = 100. * progress / total
          stdout.write('\r')
          stdout.write("%s bytes sent of %s [%2.0f%%]" % (progress, total, percent))
          stdout.flush()
          if percent >= 100: stdout.write('\n')

    #參數(shù)配置
    from_addr = "xyhuangjia@yeah.net"
    password = "HJ19930112"
    to_addr = ["dengq@ywsoftware.com","huangj@ywsoftware.com"]
    smtp_server = "smtp.yeah.net"

    #郵件信息配置
    #正文
    content = u'%s新版本(版本號)的安裝包已發(fā)送真仲,請將本版本的需要變更之處用文本記錄下來發(fā)送給本人,謝謝??'% sys.argv[3]
    #標題(使用傳輸過來的數(shù)據(jù))
    subject = u'%s的安裝包' % sys.argv[3]
    emailFrom = "鶸開發(fā)黃小佳"
    msg = MIMEMultipart()
    msg['From'] = _format_addr('%s<%s>' % (emailFrom,from_addr))
    msg['To'] = _format_addr(u'接受者 <%s>' % to_addr)
    msg['Subject'] = Header('%s' % subject, 'utf-8').encode()
    msg.attach(MIMEText('%s'%content, 'plain', 'utf-8'))

    mime = MIMEBase('application', 'octet-stream', filename=fileName)
    with open(filePath, 'rb') as f:
        # 加上必要的頭信息:
        mime.add_header('Content-Disposition', 'attachment', filename=fileName)
        mime.add_header('Content-ID', '<0>')
        mime.add_header('X-Attachment-Id', '0')
        mime.set_payload(f.read())
        # 用Base64編碼:
        encoders.encode_base64(mime)
        # 添加到MIMEMultipart:
        msg.attach(mime)

    try:
        server = ExtendedSMTP()
        server.callback = callback
        server.connect(smtp_server, 25)
        # server.set_debuglevel(1)#坑爹的調試模式初澎,打開輸出一萬行坑了我四天
        server.login(from_addr, password)
        server.sendmail(from_addr, to_addr, msg.as_string())
        server.quit()
        return True
    except Exception as e:
        raise e
        return False


if __name__ == '__main__':

    # print sys.argv
    if sendMail(sys.argv[1], sys.argv[2], sys.argv[3]):
        print "\033[32;1m 郵件已發(fā)送!\033[0m"
    else:
        print "郵件發(fā)送失敗!"

注意:

沒事不要開什么調試模式server.set_debuglevel(1)打開后會輸出代碼執(zhí)行過程秸应,在含有大附件的郵件在發(fā)送時會嚴重的拖慢進度,要注意這個

參考文章鏈接

Python發(fā)送以整個文件夾的內容為附件的郵件的教程

smtplib

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末碑宴,一起剝皮案震驚了整個濱河市软啼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌延柠,老刑警劉巖祸挪,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捕仔,居然都是意外死亡匕积,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門榜跌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闪唆,“玉大人,你說我怎么就攤上這事钓葫∏睦伲” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵础浮,是天一觀的道長帆调。 經常有香客問我,道長豆同,這世上最難降的妖魔是什么番刊? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮影锈,結果婚禮上芹务,老公的妹妹穿的比我還像新娘蝉绷。我一直安慰自己,他們只是感情好枣抱,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布熔吗。 她就那樣靜靜地躺著,像睡著了一般佳晶。 火紅的嫁衣襯著肌膚如雪桅狠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天轿秧,我揣著相機與錄音中跌,去河邊找鬼。 笑死淤刃,一個胖子當著我的面吹牛晒他,可吹牛的內容都是我干的。 我是一名探鬼主播逸贾,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼津滞!你這毒婦竟也來了铝侵?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤触徐,失蹤者是張志新(化名)和其女友劉穎咪鲜,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撞鹉,經...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡疟丙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年良狈,在試婚紗的時候發(fā)現(xiàn)自己被綠了宵蕉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡巡扇,死狀恐怖孝鹊,靈堂內的尸體忽然破棺而出炊琉,到底是詐尸還是另有隱情,我是刑警寧澤又活,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布苔咪,位于F島的核電站,受9級特大地震影響柳骄,放射性物質發(fā)生泄漏团赏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一耐薯、第九天 我趴在偏房一處隱蔽的房頂上張望舔清。 院中可真熱鬧隘世,春花似錦、人聲如沸鸠踪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽营密。三九已至械媒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間评汰,已是汗流浹背纷捞。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留被去,地道東北人主儡。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像惨缆,于是被迫代替她去往敵國和親糜值。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內容