README
https://github.com/guoruibiao/worktools/edit/master/mailer/README.md
最終效果
sendmail.py -h
usage: sendmail.py [-h] [-s SENDER] [-p PASSWORD] [-H HOST] [-P PORT]
[-r RECEIVERS [RECEIVERS ...]] [-a ATTACHMENT] [-t TEXT]
[-S SUBJECT]
命令列郵件傳送工具
optional arguments:
-h, --help show this help message and exit
-s SENDER, --sender SENDER
郵件傳送人郵件地址
-p PASSWORD, --password PASSWORD
郵件傳送人對應的密碼
-H HOST, --host HOST 郵件伺服器主機
-P PORT, --port PORT 郵件伺服器埠,預設25
-r RECEIVERS [RECEIVERS ...], --receivers RECEIVERS [RECEIVERS ...]
收件人列表,注意不能少於一個,而且多個收件人要用空格隔開
-a ATTACHMENT, --attachment ATTACHMENT
附件的全路徑,注意windows和linux上會稍有不同~, 多個附件的時候需要重複指定此引數~
-t TEXT, --text TEXT 郵件正文部分,相當於純文字模式
-S SUBJECT, --subject SUBJECT
郵件主題
複製程式碼
因為畢設的緣故,不能待在公司了。但是偶爾公司的活還是要做,基本上來說,給運營跑的資料都很小,幾十上百行就能搞定了。然後自己複製貼上即可。但是有時候跑的資料結果集賊大,動輒上萬行,這個時候就不能使用複製貼上了。由於外網限制,好多埠都是用不了的,所以通過HTTP服務的方式就放棄了。轉而採用曲線救國的方式來實現,那就是使用**“郵件”**。
由於我是後臺開發,一般工作的時候需要先登入公司的一臺跳板機,然後再從跳板機登入到對應的伺服器。所以這樣是沒法使用GUI介面的郵件工具的。因此轉而使用命令列版。詳見下面的程式碼,不依賴標準庫之外的其他庫,所以可以很方便的進行移植。
# coding:utf8
import re
import os
import smtplib
import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
class Mailer(object):
"""
郵件工具箱, 用於傳送通用文字郵件以及各種附件形式的郵件。
"""
def __init__(self, username="spidersmall@163.com", password="", host="smtp.163.com", port=25):
if self._checkMailAddress(mailaddress=username) == False:
raise Exception("發件人郵件地址有誤,當前值:{}".format(username))
self.username = str(username)
# 初始化收件人列表
self.receivers = []
self._login(str(username), str(password), str(host), int(port))
self.message = MIMEMultipart()
def _login(self, username, password, host, port):
self.client = smtplib.SMTP()
self.client.connect(host, port)
self.client.login(username, password)
def _checkMailAddress(self, mailaddress=""):
if mailaddress == "" or mailaddress is None:
raise Exception("郵箱地址為空,當前值:{}".format(mailaddress))
if len(mailaddress) < 6:
raise Exception("郵箱[{}]長度太少了吧,確定沒有輸入錯誤嗎?".format(mailaddress))
regpattern = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$"
if re.match(re.compile(regpattern), mailaddress) is not None:
return True
else:
return False
def addReceiver(self, receiver=""):
if not self._checkMailAddress(mailaddress=receiver):
raise Exception("收件人郵箱格式有誤,當前值:{}".format(receiver))
self.receivers.append(receiver)
def _getContent(self, filename="", mode="r"):
"""
這裡mode最重要,需要自己指定讀檔案的模式,像xlsx,mp3這種二進位制的,一定要用rb;普通檔案用r模式即可。
"""
content = ""
mode = str(mode).lower()
if os.path.exists(filename) == False:
raise Exception("附件路徑不存在,請確認後再傳送吧~ \n當前值: {}".format(filename))
if mode == "r":
with open(filename, mode, encoding='utf8') as f:
content = f.read()
f.close()
elif mode == "rb":
with open(filename, mode) as f:
content = f.read()
f.close()
else:
raise Exception("暫不支援的讀檔案模式,當前值:{}".format(mode))
return content
def addAttchment(self, filename=""):
content = self._getContent(filename=filename, mode='rb')
attachment = MIMEApplication(content)
attachment.add_header("Content-Disposition", "attachment", filename=filename)
self.message.attach(attachment)
def addMailBody(self, filename=""):
content = self._getContent(filename=filename, mode='r')
mailbody = MIMEText(content)
self.message.attach(mailbody)
def addMailContent(self, content=""):
if content is None or content == "":
raise Exception("一句話郵件正文不能為空哈~")
mailcontent = MIMEText(content)
self.message.attach(mailcontent)
def send(self, subject="忘了寫標題~"):
self.message['Subject'] = subject
self.message["From"] = self.username
self.message['To'] = ",".join(self.receivers)
try:
self.client.sendmail(self.username, self.receivers, self.message.as_string())
self.client.quit()
print("主題為:[{}]的郵件傳送成功~\n".format(subject))
except Exception as e:
print("出了點問題,具體資訊為:{}".format(e))
def main():
"""
使用命令列引數,免得密碼洩露什麼的。
"""
parser = argparse.ArgumentParser(description="命令列郵件傳送工具")
parser.add_argument("-s", "--sender", help="郵件傳送人郵件地址")
parser.add_argument("-p", "--password", help="郵件傳送人對應的密碼")
parser.add_argument("-H", "--host", help="郵件伺服器主機")
parser.add_argument("-P", "--port", help="郵件伺服器埠,預設25")
parser.add_argument("-r", "--receivers", nargs="+", help="收件人列表,注意不能少於一個,而且多個收件人要用空格隔開")
parser.add_argument("-a", "--attachment", action="append", help="附件的全路徑,注意windows和linux上會稍有不同~, 多個附件的時候需要重複指定此引數~")
parser.add_argument("-t", "--text", help="郵件正文部分,相當於純文字模式")
parser.add_argument("-S", "--subject", help="郵件主題")
args = parser.parse_args()
if args is None:
raise Exception("命令列引數有誤~")
sender = args.sender
password = args.password
host = args.host
port = int(args.port)
mailer = Mailer(username=sender, password=password, host=host, port=port)
if args.text is not None:
mailer.addMailContent(content=str(args.text))
for receiver in args.receivers:
mailer.addReceiver(receiver=receiver)
for attach in args.attachment:
mailer.addAttchment(filename=attach)
if args.subject is not None:
mailer.send(subject=str(args.subject))
if __name__ == "__main__":
main()
複製程式碼
使用方法
python sendmail.py -s sender@xxx.com -p your-password -H mailhost(如: smtp.163.com) -P 25(如果是QQ郵箱可能要更改下) - r receiver1 receiver2 ... -a attachment-file-path1 -a attachment-file-path2(-a 選項每次只是新增一個附件的完整路徑,多個附件的時候需要多次指定-a引數) -t 郵件正文顯示的內容 -S 郵件主題
複製程式碼
待改進之處
我自己大致測試了下,感覺還算可以。但是不得不說,這個工具還有其他不夠好的地方。大致可以羅列下:
-
通過命令列輸入密碼,算是一個比較敏感的問題,可以使用getpass庫動態輸入密碼。
-
每次都要指定這麼一大串引數,有點冗餘。這點可以模仿**
.vimrc
**這種,通過執行時環境變數來載入,省去每次都要輸入一遍。(但是要記得安全儲存這些比較敏感的資訊)
好了,差不多就這樣了。如果以後在用的過程中覺得有不太合適或者可以優化使用者體驗的,再過來完善吧。(2018年4月12日14:05:44)。
參考連結: [1]: argparse庫學習 [2]: Python smtplib庫傳送帶有附件的郵件