使用Python發送和讀取Lotus Notes郵件
本人原創,轉載請註明出處
Blog:Why So Serious
Github: LeoLuo22
CSDN: 我的CSDN 0x00前言
公司限制內部訪問互連網,與外網的唯一通道只有Lotus Notes,所以與外界的一切互動只能通過Notes郵件來進行。之前為了提醒,實現了自動發送郵件的功能。但是我也想通過外網郵件傳遞指令給機器,比如關機,打卡,重啟等等。要實現這些就要能夠讀取Notes郵件的內容,當時Google了一遍,發現大部分都是基於VB和.NET的,我試著用把他們的代碼用Python實現,但是會出現各種異常,由此放下。這兩個月以來一直很忙,也沒精力在注意這些。直到昨晚,由於在公司值班,又有時間來研究一下。
先說一下環境:
OS: Windows 7 Enterprise 64Bit
Lotus Notes 8.5.3
Python 3.5.3 0x01準備
首先要清楚兩個概念: 郵件伺服器 資料庫檔案
這兩個東西很重要。Notes的郵件資料庫是以.nsf檔案的形式儲存在伺服器上的,所以要讀取郵件內容,必須需要伺服器名稱和.nsf檔案路徑。這兩個可以通過下列步驟找到。 選擇檔案->喜好設定 選擇場所->聯機(基於你的預設值)
點擊編輯 選擇 伺服器 選項,得到你的伺服器名稱
選擇 郵件 選項,得到你的檔案路徑
其次,Notes只提供了COM介面,所以首先需要產生庫。
from win32com.client import makepymakepy.GenerateFromTypeLibSpec('Lotus Domino Objects')makepy.GenerateFromTypeLibSpec('Lotus Notes Automation Classes')
0x02 讀取郵件
首先,我們建立一個NotesMail對象,然後在init方法初始化串連。
class NotesMail():""" 發送讀取郵件有關的操作"""def __init__(self, server, file): """初始化串連 @param server 伺服器名 @param file 資料檔案名 """ session = DispatchEx('Notes.NotesSession') server = session.GetEnvironmentString("MailServer", True) self.db = session.GetDatabase(server, file) self.db.OPENMAIL self.myviews = []
self.myviews儲存資料庫下所有的視圖。
我們可以擷取所有的視圖名稱:
def get_views(self): for view in self.db.Views: if view.IsFolder: self.myviews.append(view.name)
返回內容如下:
[‘(群組行事曆)’, ‘(規則)’, ‘( Alarms)′,′( Alarms)', '(MAPIUseContacts)’, ‘( Inbox−Categorized1)′,′( Inbox-Categorized1)', '(JunkMail)’, ‘( Trash)′,′(OAMail)′,′( Trash)', '(OA Mail)', '(Inbox)’, ‘Files’, ‘SVN’, ‘Work’, ‘Mine’]
包含你的收件匣以及你建立的檔案夾。
我們可以定義一個方法來擷取一個視圖下的所有document。
def make_document_generator(self, view_name): self.__get_folder() folder = self.db.GetView(view_name) if not folder: raise Exception('Folder {0} not found. '.format(view_name)) document = folder.GetFirstDocument while document: yield document document = folder.GetNextDocument(document)
在這裡踩了一個坑,一開始我寫的是
document = folder.GetFirstDocument()
給我報錯
<class 'win32com.client.CDispatch'>Traceback (most recent call last):File "notesmail.py", line 64, in <module>main()File "notesmail.py", line 60, in mainmail.read_mail()File "notesmail.py", line 49, in read_mail for document in self.make_document_generator('Mine'):File "notesmail.py", line 43, in make_document_generator document = folder.GetNextDocument()File "<COMObject <unknown>>", line 2, in GetNextDocumentpywintypes.com_error: (-2147352571, '類型不符。', None, 0)
又是這種錯,當初改寫.NET的代碼的時候也出現這種錯。出現這種錯的原因可能是沒有GetFirstDocument()方法。這幾天佛跳牆用不了,用了bing國際版去搜尋lotus notes api,結果沒找到什麼有用的資訊。我又搜尋getfirstdocument,轉機來了,找到了lotus的官網,上面有各種API。在此推薦一下:API
原來是不需要括弧的。
然後寫一個解析document的方法。
def extract_documet(self, document): """提取Document """ result = {} result['subject'] = document.GetItemValue('Subject')[0].strip() result['date'] = document.GetItemValue('PostedDate')[0] result['From'] = document.GetItemValue('From')[0].strip() result['To'] = document.GetItemValue('SendTo') result['body'] = document.GetItemValue('Body')[0].strip()
And,Voila.
'body': '糾結\r\n發自我的iPhone', 'date': pywintypes.datetime(2017, 10, 26, 20, 17, 9, tzinfo=TimeZoneInfo('GMT Standard Time', True)), 'subject': '',
0x03 發送郵件
發送郵件的操作比較簡單,直接上代碼吧。
def send_mail(self, receiver, subject, body=None): """發送郵件 @param receiver: 收件者 @param subject: 主題 @param body: 內容 """ doc = self.db.CREATEDOCUMENT doc.sendto = receiver doc.Subject = subject if body: doc.Body = body doc.SEND(0, receiver)
篇幅所限,完整代碼放在我的Github。
歡迎討論和提issue。