# Outlook自動化
## 目錄
- [前言](#前言)
- [基本操作](#基本操作)
- [取得信箱內email](#取得信箱內email)
- [發送email](#發送email)
## 前言
Outlook是在Windows平台上很常見且功能強大的一個電子郵件軟體,藉由Python可以透過操作Outlook來自動收發電子郵件與其它功能來實現Outlook的自動化。
#### 安裝win32com套件
```bash
$ pip3 install pypiwin32
```
或
```bash
$ pip3 install pywin32
```
> **補充:**
>
> `pypiwin32`和`pywin32`實際上是相同的Python套件,只是因爲歷史因素,這個套件在不同的平台上有不同的稱呼。
>
> 在Windows平台上,通常稱為:`pywin32`,因爲它提供了操作Windows API的能力。而在PyPI上,這個套件稱為:`pypiwin32`,這個名稱可以更明確地反映出它是一個Python套件,可以在Windows上使用。
>
> 總之,無論使用哪一個名稱,這個套件都提供了許多可以操作Windows API的模組和函式,例如:操作註冊表、管理程序、操作COM物件等等。因此,如果在Windows平台上開發Python應用程式,這個套件可以在Windows上完成各種系統層級的工作。
#### 引入套件
```python
import win32com.client
```
> **注意:**
>
> 使用pypiwin32套件操作Outlook時,Outlook必須是開啟的狀態才會動作。
## 基本操作
#### 打開outlook
```
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
```
#### 取得所有email帳號
```
for account in outlook.Accounts:
print(account, type(account.DeliveryStore.DisplayName))
```
或
```
accounts = win32com.client.Dispatch("Outlook.Application").Session.Accounts
for account in accounts:
print(account, type(account.DeliveryStore.DisplayName))
```
#### 直接指定要取得的帳號
```
accounts.Item(1)
```
> **注意:**
>
> 帳號的編號是從1開始,而不是從0開始
#### 取得總共有幾個email帳號
```
len(accounts)
```
#### 取得信箱所有目錄
```python
mailbox = outlook.Folders(accounts.Item(1).DeliveryStore.DisplayName)
for folder in mailbox.Folders:
print(folder)
```
#### 取得指定的信箱目錄
方法一:以信箱名稱來取得該信箱的目錄
```python
folder = outlook.Folders('xxxxx@gmail.com').Folders('收件匣')
```
> **補充:**
>
> 如果該目錄下還有子目錄,可以再透過`Folders()`方法來取得所有子目錄
方法二:以信箱編號來取得該信箱的目錄
```
folder = outlook.Folders(1).Folders('收件匣')
```
> **注意:**
>
> 編號從1開始,1表示取得第1個email帳號
#### 取得信箱的目錄數量
```
mailbox = outlook.Folders('xxxxx@gmail.com')
count = len(mailbox.Folders)
```
#### 取得預設信箱
```
folder = outlook.getDefaultFolder(6)
```
代號說明:
| 值 | 说明 |
| ---- | -------- |
| 6 | 收件匣 |
| 4 | 寄件 |
| 5 | 寄件備份 |
| 3 | 垃圾桶 |
#### 接收email
```
outlook.SendAndReceive(True)
```
說明:
参数False代表不把接收時的進度顯示出来,如果要顯示則改為True即可。
## 取得信箱內email
#### 取得信目錄內所有email
```
messages = folders.Items
for message in messages:
if hasattr(message, 'Sender'):
print(message.Sender)
print(message.SenderName)
print(message.SenderEmailAddress)
print(message.Subject)
print(message.ReceivedTime)
print(message.Body)
if hasattr(message, 'HTMLBody'):
print(message.HTMLBody)
```
> **注意:**
>
> 因為有些屬性可能不存在,因此建議先用`hasatter()`函式檢查該屬性使否存在再行取值。
###### 可以拿到的email屬性
| 屬性 | 說明 |
| ------------------ | -------------- |
| Sender | 寄件人 |
| SenderName | 寄件人名字 |
| SenderEmailAddress | 寄件人email |
| To | 收件人email |
| Subject | email標題 |
| Body | email文字內容 |
| HTMLBody | email HTML內容 |
| Attachments | 附件 |
#### 取得附件
```python
attachments = message.attachments
print('附件數量:', attachments.Count)
for attachment in attachments:
print(attachment.filename) # 附件的檔名
attachment.SaveAsFile('D:\\data\\' + attachment.filename)
```
> **注意:**
>
> 1. 存檔的路徑必須是絕對路徑
> 2. 如果檔案已經存在,會覆蓋掉原本的檔案。
#### 取得email回覆狀態
```
reply_status = message.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x10810003")
```
說明:
0 = 未回覆
102 = 回覆給寄件人
103 = 全部回覆
#### email過濾
```python
messages = folders.Items.Restrict('[Subject]="安全性快訊"').Restrict('[Body]="aaronbeango@gmail.com"')
```
可以過濾的條件與上面屬性相同
> **注意:**
>
> 此過濾方式,其條件必須完全吻合,無法做部分條件過濾(例如搜尋標題內包含有「安全」兩個字的所有email),如果需要做部分條件過濾,則需要使用Outlook查詢語言DASL。
#### DASL過濾
###### 只取得今天的email
```
Items.Restrict("@SQL=%today(urn:schemas:httpmail:datereceived)%")
```
###### 取得指定日期的email
```
Items.Restrict("@SQL=(urn:schemas:httpmail:datereceived >= '2024-04-01 00:00')")
```
###### 取得日期區間的email
```less
Items.Restrict("@SQL=(urn:schemas:httpmail:datereceived >= '2024-04-01 00:00' AND urn:schemas:httpmail:datereceived <= '2024-04-01 23:59')")
```
###### 以寄件人來過濾
```
Items.Restrict("@SQL=(urn:schemas:httpmail:sender like '%aaron%')")
```
###### 過濾標題中有包含的文字
```
Items.Restrict("@SQL=(urn:schemas:httpmail:subject LIKE '%包含的文字%')")
```
###### 過濾標題為Google的文字
```
Items.Restrict("@SQL=(urn:schemas:httpmail:subject = 'Google')")
```
###### 以內容來搜尋
```
Items.Restrict("@SQL=(urn:schemas:httpmail:textdescription LIKE '%包含的文字%')")
```
#### 將email存到硬碟
```
message.SaveAs(r'D:\emails\save.msg')
```
> **注意:**
>
> 1. 檔名必須是完整的絕對路徑,且副檔名為`.msg`
> 2. 如果存檔的檔案已經存在,會存檔失敗。
#### 回覆email
```
replyall_email = message.ReplyAll()
replyall_email.Body = "回覆的內容"
replyall_email.HTMLBody = "回覆HTML的內容"
replyall_email.Send()
```
> **補充:
>
> `Body`和`HTMLBody`擇一即可。
如果要直接回覆給寄件人,則呼叫:
```
message.Reply()
```
## 發送email
#### 取得outlook元件
```python
outlook = win32com.client.Dispatch("Outlook.Application")
```
#### 建立新的email
```
mail = outlook.CreateItem(0)
```
#### 指定要使用的email帳號
```python
# 取得第一個email帳號
account= win32com.client.Dispatch("Outlook.Application").Session.Accounts.Item(1)
mail._oleobj_.Invoke(*(64209,0,8,0,account))
```
> **補充:**
>
> 如果沒有指定email帳號,預設會使用第一個email帳號來發送email
#### 指定收件人
```
mail.To = 'xxxxx@gmail.com'
```
#### 指定多個收件人
```
mail.To = 'xxxxx01@gmail.com;xxxxx02@gmail.com;xxxxx03@gmail.com'
```
#### 指定副本收件人
```
mail.CC = 'xxxxx@gmail.com'
```
#### 指定多個副本收件人
```
mail.CC = 'xxxxx01@gmail.com;xxxxx02@gmail.com;xxxxx03@gmail.com'
```
#### 指定密件收件人
```
mail.BCC = 'xxxxx@gmail.com'
```
#### 指定多個密件收件人
```
mail.BCC = 'xxxxx01@gmail.com;xxxxx02@gmail.com;xxxxx03@gmail.com'
```
#### 設定email標題
```
mail.Subject = '我是標題'
```
#### 設定email內容
```
mail.Body = '我是內容'
```
#### 設定email HTML格式內容
```
mail.HTMLBody = '<h1>我是HTML內容</h1>'
```
> **補充:**
>
> `mail.Body`和`mail.HTMLBody`同時設定時,只有`mail.HTMLBody`會生效。
#### 設定附件
```
mail.Attachments.Add(r'D:\data\file.txt')
```
> **補充:**
>
> 需要提供完整的檔案絕對路徑
#### 以Outlook視窗顯示要發送的email內容
```
mail.Display(True)
```
#### 發送email
```
mail.Send()
```