1. 程式人生 > >使用Python傳送和讀取Lotus Notes郵件

使用Python傳送和讀取Lotus Notes郵件

轉載自 https://blog.csdn.net/u013271714/article/details/78364932

轉載自:

Blog:Why So Serious 
Github: LeoLuo22 



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檔案路徑。這兩個可以通過下列步驟找到。


選擇檔案->首選項
選擇場所->聯機(基於你的預設值) 
image
點選編輯
選擇 伺服器 選項,得到你的伺服器名稱 
image
選擇 郵件 選項,得到你的檔案路徑 
image
其次,Notes只提供了COM介面,所以首先需要生成庫。


from win32com.client import makepy
makepy.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)′,′(MAPIUseContacts)’, ‘(Inbox−Categorized1)′,′(JunkMail)’, ‘(Trash)′,′(OAMail)′,′(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 main
mail.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 GetNextDocument
pywintypes.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)