当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 如何使用 Microsoft Graph PowerShell 发送电子邮件

作者:精品下载站 日期:2024-12-14 06:50:09 浏览:16 分类:玩电脑

如何使用 Microsoft Graph PowerShell 发送电子邮件


旧版电子邮件身份验证方法正在成为过去,Exchange Online 的旧版身份验证现已失效,并且第 3 方服务变得越来越难以保护,尤其是在需要将它们添加为域的受信任邮件源时,这是一种以编程方式进行的替代方法发送电子邮件是必不可少的。

Microsoft Graph PowerShell 中的 Send-MgUserMail cmdlet 提供了一种在交互式和非交互式 PowerShell 会话中使用 PowerShell 以编程方式发送电子邮件的便捷方法。

在本教程中,我将向您展示如何使用 Microsoft Graph PowerShell 和 Graph API 通过现有的 Exchange Online 服务以编程方式发送电子邮件。

消除对第三方服务的需求

由于 Exchange Online 的旧身份验证现已无法使用,许多组织一直需要其他安全中继电子邮件的方法。虽然要求苛刻的应用程序(例如 Microsoft Dynamics)或落后的设备(例如 MFP)可以轻松使用 Office 365 Direct Send 等方法(前提是它们位于静态公共 IP 后面)或利用现有的混合基础设施(如果您是不幸的是仍然拥有它......),编程解决方案一直是一个挑战,特别是在使用 Azure 自动化等服务并试图阻止使用第 3 方基础设施时。

SMTP2Go 或 SendGrid 等第三方服务似乎是解决此问题的有吸引力的选择,但存在一个问题:

  • 您应该轮换密码吗?
  • 它们到底有多安全?
  • 他们合规吗?
  • 如何跟踪和监控漏洞?
  • 这样的例子还在继续……

这个问题的简单答案就是根本不使用它们,而是使用您随时可用的东西,即带有 PowerShell 的 Graph API!

关于 Send-MgUserMail

Send-MgUserMail cmdlet 可以在 Microsoft Graph PowerShell SDK 的 Microsoft.Graph.Users.Actions 模块中找到,并且该命令可以与委托权限和应用程序权限一起使用在不同的背景下。

要使用该 cmdlet,您需要同意 mail.send 权限范围,但根据您是否使用委派权限或应用程序权限同意此权限,将授予不同级别的访问权限。

如果您在委派方案中同意 mail.send 权限,您可能会注意到您只能以当前会话(当前用户上下文)中经过身份验证的用户身份发送邮件。

[玩转系统] 如何使用 Microsoft Graph PowerShell 发送电子邮件

但是,当同意同等应用程序权限时,您会注意到您可以以组织中的任何用户身份发送邮件。

[玩转系统] 如何使用 Microsoft Graph PowerShell 发送电子邮件

正如您所看到的,mail.send 是一个危险且强大的权限,应谨慎使用。如果计划将此权限与 Azure 自动化结合使用,请考虑使用托管标识来消除管理客户端机密或证书的需要并确保环境安全。

使用 Microsoft Graph PowerShell 发送电子邮件

发送具有委派权限的电子邮件

要在您自己的用户上下文中使用委派权限发送电子邮件,您需要使用 Connect-MgGraph cmdlet 和 Mail.Send 权限范围连接到 Microsoft Graph:

Connect-MgGraph -scope Mail.Send

然后,需要将实际的邮件消息定义为哈希表,这里是一个从特定地址发送基本基于文本的电子邮件的简单示例。请务必将“您的电子邮件地址”文本更改为您用于向 Microsoft Graph 进行身份验证的帐户的电子邮件地址。

$body = @{
	message = @{
		subject = "My Microsoft Graph Test Email"
		body = @{
			contentType = "Text"
			content = "Hello, this is a test email"
		}
		toRecipients = @(
			@{
				emailAddress = @{
					address = "YOUR EMAIL HERE"
				}
			}
		)
	}
	saveToSentItems = "false"
}

最后,要发送电子邮件,请使用 Send-MgUserMail cmdlet,如下所示:

Send-MgUserMail -UserId %YourUPN% -BodyParameter $body

发送包含申请权限的电子邮件

正如我们所知,在定义 Mail.Send 权限时,应用程序权限会暴露更多的权力。这意味着我们的脚本可以更加灵活。

首先连接到 Microsoft Graph。如果您还不熟悉如何执行此操作,请按照我的指南进行操作:如何使用客户端密钥连接到 Microsoft Graph PowerShell。

使用应用程序权限时可以采取稍微不同的方法,就像下面的示例一样。在这里您可以看到我已将 -to-from 参数添加到我的脚本中,这允许用户定义电子邮件的发送对象和发送对象。如果发件人地址取决于自动操作的结果(例如使用 Azure 自动化),则也可以从其他来源获取这些参数的值。

Param(
    [Parameter(Mandatory)]
    [ValidateNotNull()]
    [mailaddress]
    ${to},

    [Parameter(Mandatory)]
    [ValidateNotNull()]
    [mailaddress]
    ${from}
)

$ApplicationId = "APPID"
$SecuredPassword = "SECRETKEY"
$tenantID = "TENANTID"
$SecuredPasswordPassword = ConvertTo-SecureString -String $SecuredPassword -AsPlainText -Force
$ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPasswordPassword
Connect-MgGraph -TenantId $tenantID -ClientSecretCredential $ClientSecretCredential

$body = @{
	message = @{
		subject = "My Microsoft Graph Test Email"
		body = @{
			contentType = "Text"
			content = "Hello, this is a test email"
		}
		toRecipients = @(
			@{
				emailAddress = @{
					address = "$to"
				}
			}
		)
	}
	saveToSentItems = "false"
}

Send-MgUserMail -UserId $from -BodyParameter $body

使用 Send-MgUserMail 修改邮件标头

邮件标头包含有关电子邮件来源以及邮件所经过的任何电子邮件服务器的重要信息。然后,像我们这样的管理员可以使用邮件标头中的信息来确定电子邮件的详细信息以进行故障排除。有关邮件标头的更多详细信息,请参阅我的教程:查看和解释 Exchange Online 中的邮件标头。

在我们的示例中,我们可以向使用 Send-MgUserMail cmdlet 发送的邮件添加其他信息,以帮助其他用户确定电子邮件的来源和其他故障排除因素。您可能想要执行此操作的另一个充分理由是,您可以对这些邮件应用或排除特定的 Exchange 传输规则,例如,您可以针对任何日记规则排除这些邮件。

为此,您需要在 message=@{} 哈希表中添加以下代码:

InternetMessageHeaders = @(
			@{
				Name = "x-custom-header-name"
				Value = "custom value"
			}
		)

您还可以通过复制以下哈希表来向消息添加多个标头:

InternetMessageHeaders = @(
			@{
				Name = "x-custom-header-name"
				Value = "custom value"
			}
			@{
				Name = "x-custom-header-name2"
				Value = "custom value2"
			}	
		)

x-custom-header-name(同时确保标头以 x- 开头)修改为更具体的内容以及自定义值。您可以在下面看到我迄今为止的消息示例:

$body = @{
	message = @{
		subject = "My Microsoft Graph Test Email"
		body = @{
			contentType = "Text"
			content = "Hello, this is a test email"
		}
		toRecipients = @(
			@{
				emailAddress = @{
					address = "[email "
				}
			}
		)
       	InternetMessageHeaders = @(
			@{
				Name = "x-ocn-header-source"
				Value = "azure-automation"
			}
		)
	}
	saveToSentItems = "false"
}

创建标头后,发送测试电子邮件并查看邮件标头属性。如果您使用的是 OWA,则可以右键单击该消息,然后单击查看 > 查看消息详细信息

[玩转系统] 如何使用 Microsoft Graph PowerShell 发送电子邮件

使用 Microsoft Graph PowerShell 发送附件

附件可能包含收件人的重要信息,因此了解如何在以编程方式发送电子邮件时向电子邮件添加附件非常有用。

使用 PowerShell 时可以从各种来源添加附件,例如:

  • 使用 Invoke-WebRequest 从互联网下载
  • 在 Windows 中使用文件资源管理器手动选择
  • 在 PowerShell 本身内生成

虽然在交互式 PowerShell 会话期间手动选择文件很有用,但非交互式会话将要求您自动处理附件添加。让我们看看如何手动和自动添加附件。

手动选择附件

可以在代码中手动定义现有附件以在电子邮件中使用。您可以通过定义文件路径、将其转换为 Base 64 字符串并将其包含在消息正文中来完成此操作。

要检索附件,您可以使用以下示例并更改文件路径 C:\temp\MyTextFile.txt

$Attachment = "C:\temp\MyTextFile.txt"
$MailAttachement = [Convert]::ToBase64String([IO.File]::ReadAllBytes($Attachment))

然后在 message@{} 哈希表中定义附件。

  attachments = @(
			@{
				"@odata.type" = "#microsoft.graph.fileAttachment"
				name = "$Attachment"
				contentType = "text/plain"
				contentBytes = $MailAttachement
			}
    )

完整的哈希表现在应如下所示:

$body = @{
	message = @{
		subject = "My Microsoft Graph Test Email"
		body = @{
			contentType = "Text"
			content = "Hello, this is a test email"
		}
		toRecipients = @(
			@{
				emailAddress = @{
					address = "[email "
				}
			}
		)
        attachments = @(
			@{
				"@odata.type" = "#microsoft.graph.fileAttachment"
				name = "$Attachment"
				contentType = "text/plain"
				contentBytes = $MailAttachement
			}
        )
	}
	saveToSentItems = "false"
}

在线下载附件

存储文件的更方便的位置是中央 GitHub 存储库。当然,如果您要公开文档,它们应该只是基本模板文件或功能脚本(其中不包含公司或可识别数据,否则,需要访问令牌才能访问私有存储库。

以下示例使用 Invoke-WebRequest cmdlet 从公共 GitHub 存储库下载文件并准备将其附加到消息中。

$attachment = Invoke-WebRequest -Uri "https://raw.githubusercontent.com/DanielBradley1/Public/main/Testing/MyTestCSVFile.csv"
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($attachment.Content)
$MailAttachment = [System.Convert]::ToBase64String($encodedBytes)

您可能还想动态定义附件名称,在这种情况下,您可以使用 Regex 选择文件路径中最后一个正斜杠后面的文件名。例如:

$attachment.BaseResponse.ResponseUri.AbsolutePath -match '([^\/]+$)'
$matches[1]

完整的代码如下所示:

$attachment = Invoke-WebRequest -Uri "https://raw.githubusercontent.com/DanielBradley1/Public/main/Testing/MyTestTextFile.txt"
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($attachment.Content)
$MailAttachment = [System.Convert]::ToBase64String($encodedBytes)
$attachment.BaseResponse.ResponseUri.AbsolutePath -match '([^\/]+$)'
$matches[1]

$params = @{
	message = @{
		subject = "Automated - Inactive User Report"
		body = @{
			contentType = "Text"
			content = "Please see the attached!"
		}
		toRecipients = @(
			@{
				emailAddress = @{
					address = "[email "
				}
			}
		)
    attachments = @(
			@{
				"@odata.type" = "#microsoft.graph.fileAttachment"
				name = $matches[1]
				contentType = "text/plain"
				contentBytes = $MailAttachment
			}
    )
	}
	saveToSentItems = "false"
    
}

使用 PowerShell 对象构建附件

更常见的是,您可能会使用 PowerShell 创建报告,然后将该数据附加到电子邮件中发送。执行此操作的一个简单方法是构建固定的数据数组,然后将其转换为 HTML 报告并附加到您的电子邮件中。

假设您已经拥有数据数组,一个很好的例子是我的非活动用户报告脚本:https://ourcloudnetwork.com/create-an-inactive-m365-user-report-with-microsoft-graph-powershell /。

要将使用我们的脚本构建的 $report 数组附加到电子邮件中,您可以使用下面的示例将其转换为 HTML 格式,应用边框来整理表格,然后准备将其附加到电子邮件中。

$report = $report | ConvertTo-Html
$Report = $report -replace '<table>', '<table border="1">'
$encodedBytes = [System.Text.Encoding]::UTF8.GetBytes($report)
$MailAttachment = [System.Convert]::ToBase64String($encodedBytes)

然后可以按照与前面示例相同的方式将该文件附加到电子邮件中。

Send-MgUserMail 的所有电子邮件选项

从根本上讲,可以使用 Microsoft Graph 发送消息属性的许多其他变体。要了解有关可自定义的消息属性的更多信息,请查看 Microsoft Graph 文档中的消息资源类型文档:https://learn.microsoft.com/en-us/graph/api/resources/message?视图=图-rest-beta

如果您在添加更多属性时遇到任何问题,请在下面发表评论,我将很乐意尽快提供帮助。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯