分享我常用的一則 PowerShell 私房小技巧 - 在 Windows 桌面環境透過 Outlook 寄信。

面對一堆煩人的日常瑣事,我習慣用 PowerShell 寫些自動化或半自動化小幫手程式,替我完成枯燥又沒營養的人工作業,應用情境中難免有寄信需求。用程式發信的方法很多,像是透過 SMTP呼叫 EWS (Exchange Web Service)... 等等,但 SMTP 需要伺服器端授權 Relay 轉信,EWS 要找到 Web Service 網址指定登入身分等,都需要相關條件配合。我的小幫手程式多半是在登入 PC 時執行,而大部分辦公環境 Outlook 幾乎會全程開啟,於是一條超簡便的寄信捷徑出現了 - 何不請 Outlook 幫我們寄信呢?程式不用管郵件伺服器 IP、登入身分,只要 Outlook 平常能收發信,信就一定寄得出去。

我寫了一支 Send-OutlookMail.ps1 來示範,傳入收件地址、主旨、內文就完成寄信工作;內文如果以 < 起首會視為 HTML 格式處理,故內容支援字體、大小、顏色,給檔名還可夾附件,程式碼完全不用管連的是 Exchange、Hotmail 還是 Gmail,也不需要知道寄件者帳號密碼,是不是很方便呢?

[CmdletBinding()]
param (
    [Parameter(Mandatory = $true)]
    [string]
    $rcpt,
    [Parameter(Mandatory = $true)]
    [string]
    $subject,
    [Parameter(Mandatory = $true)]
    [string]
    $body,
    $attachment
)

$outlookApp = [System.Runtime.InteropServices.Marshal]::GetActiveObject("Outlook.Application")
if (!$outlookApp) {
    throw "請先開啟 Outlook 程式"
}
# Microsoft.Office.Interop.Outlook.OlItemType.olMailItem = 0
$mailItem = $outlookApp.CreateItem(0)
$rcpt.Split(',') | ForEach-Object {
    # Microsoft.Office.Interop.Outlook.OlMailRecipientType.olTo = 1 (olCC = 2, olBCC = 2)
    $mailItem.Recipients.Add($_).Type = 1
}
$mailItem.Subject = $subject
if ($body.StartsWith('<')) {
    $mailItem.HTMLBody = $body
}
else {
    $mailItem.Body = $body
}
$attachment | ForEach-Object {
    if ($_) {
        if (Test-Path -Path $_ -PathType Leaf) {
            # Microsoft.Office.Interop.Outlook.olAttachmentType.olByValue = 1
            # olByValue = 1 (副本), olByReference = 4 (Outlook 2007 不支援), olEmbeddeditem = 5 (.msg), olOLE = 6
            $fullPath = (Resolve-Path $_).Path
            $mailItem.Attachments.Add($fullPath, 1) | Out-Null
        }
        else {
            Write-Host "Invalid attachment path - $_" -ForegroundColor Red
        }
    }
}
$mailItem.Send()

實測一下:

.\Send-OutlookMail mail-address@mail.com 這是純文字測試信 "純文字內容"
"1234" | Out-File "test.txt"
.\Send-OutlookMail mail-address@mail.com 這是彩色測試信 '<div>可以有<span style="color:red">紅色的字</span>耶</div>' test.txt

成功!

Example of using PowerShell to sending Email via Outlook application.


Comments

# by 王董

Powershell真的要寄信不用特地用Outlook,有發信函式可用。

# by CCY

樓上miss the point, 用發信函式還得針對要使用的mail service設定, 這隻script只要帶到原本有設定好outlook的電腦,開了outlook 都可以用

# by Aaron Sun

謝謝您分享。 這個可以省去公司內部要另外申請發MAIL的程序。 請問如果有既有的郵件範本(內容格式、欄位很多),例如:範本信件.oft,郵件主旨、收件者、附件會變動,內文不變,這要怎麼呼叫出來,然後發送呢?? 謝謝您。

# by Jeffrey

to Aaron Sun, 我沒用過郵件範本,但 Outlook API 支援使用範本發信 https://docs.microsoft.com/zh-tw/office/client-developer/outlook/pia/how-to-create-a-mail-item-by-using-a-message-template 將官方文件的範例改寫成 PowerShell 版應該就 OK 了。

# by Aaron Sun

感謝您幫忙!!

# by Aaron Sun

您好 郵件範本的方式有點麻煩,改弦易轍使用HTML編寫MAIL內容,直接寫網頁轉HTML,然後把必要的資訊用變數帶入(簡易編寫網址:https://www.ifreesite.com/editor/)。 然後參考這篇,把剛剛編輯的HTML設定$EmailBody (https://www.sharepointdiary.com/2015/06/send-mailmessage-powershell-body-html-format.html) 再使用您的"Send-OutlookMail.ps1"...就完工了!!!!! 感謝您的分享^^ 語法範例: .\Send-OutlookMail.ps1 UserEmail@TESMAIL.COM $InputSubject $EmailBody

# by brian

請問一下,若利用 Aaron Sun的方法,有沒有完整的語法展示呢? 謝謝

# by Nic

Hi 版大 小白想問問您,如何用其它script來執行您這支script? 一次二次用powershell來互動是不錯,但如果想要用排程來定期發重覆的信怎麼做? 就好像是 Aaron Sun的把body寫成html(這個我寫好了,但不會放上去一起使用)... 麻煩了,謝謝您。

# by Jeffrey

to Nic, 其他 Script 把 Send-OutlookMail.ps1 當成外部程式呼叫即可,PowerShell 要呼叫其他 .ps1 可以寫 「. .\MyFunc.ps1」https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.2#dot-sourcing-operator- 要設成排程可使用 Windows 工作排程器 https://www.delftstack.com/zh-tw/howto/powershell/automating-powershell-scripts-using-task-scheduler/

# by DDC

Hello 您好, 假使我的信件同時需要多個Recipients和CC, 變成同時存在以下兩者, $mailItem.Recipients.Add($_).Type = 1 $mailItem.Recipients.Add($_).Type = 2 我在$rcpt的迴圈要如何改動比較好, 目前測試多次還未能達成。

# by DDC

Sorry我的問題請忽略, 一開始想太複雜, 已經直接用第二個迴圈解決了,感謝。

Post a comment