大约一年前,我的任务是使用PowerShell/EWS在公司用户的日历中创建约会。我很幸运,在www上找到了一个很好用的脚本(代码如下)。脚本导入多个CSV文件,并为CSV中的每一行创建一个约会。剧本运行了几个月没有任何问题。但在过去几周里,剧本不断失败。但它并不总是失败。有时候重启一下就够了。有时需要3或4次重启。它不会在同一个文件上失败,而且--正如所说的--它并不总是失败。所以我想脚本和处理的数据必须是有效的。
当脚本失败时,它通常会说“请求失败。远程服务器返回错误(503)。服务器不可用”。错误并不总是相同的,但总是与exchange服务器的连接失败有关。在许多情况下,会显示我应该在其中输入exchange online凭据的弹出窗口。但显然我之前输入了这些凭据(加密密码的导入)。所以我想连接中断了,所以我被要求重新输入它们。
没有防火墙或AV阻止连接。我的网络连接没有中断...
param([string]$CSVFileName,[string]$EmailAddress,[string]$Username,[string]$Password,[string]$Domain,[bool]$Impersonate,[string]$EwsUrl,[string]$EWSManagedApiPath);
#
# Import-CalendarCSV.ps1
#
# By David Barrett, Microsoft Ltd. Use at your own risk.
# C:\Program Files\Microsoft\Exchange Server\V14\Bin
Function ShowParams()
{
Write-Host "Import-CalendarCSV -CSVFileName <string> -EmailAddress <string>";
Write-Host " [-Username <string> -Password <string> [-Domain <string>]]";
Write-Host " [-Impersonate <bool>]";
Write-Host " [-EwsUrl <string>]";
Write-Host " [-EWSManagedApiPath <string>]";
Write-Host "";
Write-Host "Required:";
Write-Host " -CSVFileName : Filename of the CSV file to import appointments for this user from.";
Write-Host " -EmailAddress : Mailbox SMTP email address";
Write-Host "";
Write-Host "Optional:";
Write-Host " -Username : Username for the account being used to connect to EWS (if not specified, current user is assumed)";
Write-Host " -Password : Password for the specified user (required if username specified)";
Write-Host " -Domain : If specified, used for authentication (not required even if username specified)";
Write-Host " -Impersonate : Set to $true to use impersonation.";
Write-Host " -EwsUrl : Forces a particular EWS URl (otherwise autodiscover is used, which is recommended)";
Write-Host " -EWSManagedApiDLLFilePath : Full and path to the DLL for EWS Managed API (if not specified, default path for v1.1 is used)";
Write-Host "";
}
$RequiredFields=@{
"Subject" = "Subject";
"StartDate" = "Start Date";
"StartTime" = "Start Time";
"EndDate" = "End Date";
"EndTime" = "End Time"
}
# Check email address
# if (!$EmailAddress)
# {
# ShowParams;
# throw "Required parameter EmailAddress missing";
# }
# CSV File Checks
if (!$CSVFileName)
{
ShowParams;
throw "Required parameter CSVFileName missing";
}
if (!(Get-Item -Path $CSVFileName -ErrorAction SilentlyContinue))
{
throw "Unable to open file: $CSVFileName";
}
# Import CSV File
try
{
$CSVFile = Import-Csv -Path $CSVFileName;
}
catch { }
if (!$CSVFile)
{
Write-Host "CSV header line not found, using predefined header: Subject;StartDate;StartTime;EndDate;EndTime";
$CSVFile = Import-Csv -Path $CSVFileName -header Subject,StartDate,StartTime,EndDate,EndTime;
}
# Check file has required fields
foreach ($Key in $RequiredFields.Keys)
{
if (!$CSVFile[0].$Key)
{
# Missing required field
throw "Import file is missing required field: $Key";
}
}
# Check EWS Managed API available
if (!$EWSManagedApiPath)
{
$EWSManagedApiPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
}
if (!(Get-Item -Path $EWSManagedApiPath -ErrorAction SilentlyContinue))
{
throw "EWS Managed API could not be found at $($EWSManagedApiPath).";
}
# Load EWS Managed API
[void][Reflection.Assembly]::LoadFile($EWSManagedApiPath);
# Create Service Object. We only need Exchange 2007 schema for creating calendar items (this will work with Exchange>=12)
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
# Set credentials if specified, or use logged on user.
if ($Username -and $Password)
{
if ($Domain)
{
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Username,$Password,$Domain);
} else {
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Username,$Password);
}
} else {
$service.UseDefaultCredentials = $true;
}
# Set EWS URL if specified, or use autodiscover if no URL specified.
if ($EwsUrl)
{
$service.URL = New-Object Uri($EwsUrl);
}
else
{
try
{
Write-Host "Performing autodiscover for $EmailAddress";
$service.AutodiscoverUrl($EmailAddress, {$true});
}
catch
{
throw;
}
}
# Bind to the calendar folder
# Parse the CSV file and add the appointments
foreach ($CalendarItem in $CSVFile)
{
# Create the appointment and set the fields
$NoError=$true;
if ($Impersonate)
{
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $CalendarItem."Email");
}
try {
$CalendarFolder = [Microsoft.Exchange.WebServices.Data.CalendarFolder]::Bind($service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar);
} catch {
throw;
}
try
{
$Appointment = New-Object Microsoft.Exchange.WebServices.Data.Appointment($service);
$Appointment.Subject=$CalendarItem."Subject";
$StartDate=[DateTime]($CalendarItem."StartDate" + " " + $CalendarItem."StartTime");
$Appointment.Start=$StartDate;
$EndDate=[DateTime]($CalendarItem."EndDate" + " " + $CalendarItem."EndTime");
$Appointment.End=$EndDate;
$Appointment.LegacyFreeBusyStatus = [Microsoft.Exchange.WebServices.Data.LegacyFreeBusyStatus]::Busy;
$Appointment.IsAllDayEvent= $CalendarItem."IsAllDayEvent";
$Appointment.IsReminderSet= $CalendarItem."IsReminderSet";
}
catch
{
# If we fail to set any of the required fields, we will not write the appointment
$NoError=$false;
}
# Check for any other fields
foreach ($Field in ($CalendarItem | Get-Member -MemberType Properties))
{
if (!($RequiredFields.Keys -contains $Field.Name))
{
# This is a custom (optional) field, so try to map it
try
{
$Appointment.$($Field.Name)=$CalendarItem.$($Field.Name);
}
catch
{
# Failed to write this field
Write-Host "Failed to set custom field $($Field.Name)" -ForegroundColor yellow;
}
}
}
if ($NoError)
{
# Save the appointment
$Appointment.Save([Microsoft.Exchange.WebServices.Data.SendInvitationsMode]::SendToNone)
Write-Host "Created $($CalendarItem."Subject")" -ForegroundColor green;
}
else
{
# Failed to set a required field
Write-Host "Failed to create appointment: $($CalendarItem."Subject")" -ForegroundColor red;
}
}
Get-PSSession | Remove-PSSession
$AdminName = “XXXXXXXX@XXXXXXX.COM”
$Pass = Get-Content “C:\Scripte\CalendarUpdate\cred.txt” | ConvertTo-SecureString
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
$TCredentials = New-Object System.Management.Automation.PSCredential $AdminName, $Pass
$TPassword = $TCredentials.GetNetworkCredential().Password
$Emails = import-csv "C:\Scripte\CalendarUpdate\Users.csv"
ForEach ($i in $Emails) {
$TEMP = Search-Mailbox $i.Emails -SearchQuery 'Subject:"Frei/Abwesend - Automatische Anlage"' -SearchDumpster:$false -EstimateResultOnly
While($TEMP.ResultItemsCount -ne 0){
Search-Mailbox $i.Emails -SearchQuery 'Subject:"Frei/Abwesend - Automatische Anlage"' -SearchDumpster:$false -DeleteContent -Force
$TEMP = Search-Mailbox $i.Emails -SearchQuery 'Subject:"Frei/Abwesend - Automatische Anlage"' -SearchDumpster:$false -EstimateResultOnly
}
$userfilename = 'C:\Scripte\CalendarUpdate\Users\' + $i.Emails + '.csv'
C:\Scripte\CalendarUpdate\Import-CalendarCSV.ps1 -CSVFileName $userfilename -Username XXXXXXX@XXXXXXX.com -Password $TPassword -Impersonate $true -EwsUrl https://outlook.office365.com/EWS/Exchange.asmx -EWSManagedApiPath "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
Remove-Item $userfilename
}
stop-Process -Name powershell
我真的希望这里的任何人都能帮我做这件事!提前多谢了。亲切地问候蒂姆
第一,从这个类似的问题:
首先要从Github https://Github.com/officedev/ews-managed-api获取最新版本的EWS托管API。您使用的版本[2.2.0]自2015年以来就没有更新过,当时Microsoft停止发布该库的编译版本。但是,在GitHub上,该代码已经更新并修复了许多bug
如果问题通常是暂时的,则可以向第二个脚本添加重试循环:
$retries = 0
While ($retries -lt 3) {
Try {
C:\Scripte\CalendarUpdate\Import-CalendarCSV.ps1 @params
$retries = 3
}
Catch { $retries += 1 }
}
如果那些建议都不起作用,那么主脚本的哪一行是失败的呢?确切的错误信息是什么?
这可能是由azureAd或O365中的各种问题引起的,通常是无法与O365正确同步,因此也要检查服务器端的错误。
[编辑]从你的评论中的错误来看,问题可能与会话超时或其他被EXO限制有关。您可能希望尝试Exchange团队创建的以下模块:
robustCloudCommand-github:Functionstart-robustCloudCommand
是一个包装脚本,它试图确保脚本块在O365中针对较大的对象计数成功完成执行。
[编辑]针对您关于使用-credential
进行基本身份验证的评论,我在RobustCloudCommand.PSM1
(位于(Get-moduleRobustCloudCommand).Path
)中执行了以下操作:
#lines 104-105
[String]$UserPrincipalName, ## Removed Mandatory
[pscredential]$credential, ## Added -credential parameter
#lines 256-260:
# Create the session
Write-Log "Connecting to Exchange Online"
if ($credential) {Connect-ExchangeOnline -Credential $credential}
elseif ($UserPrincipalName) {Connect-ExchangeOnline -UserPrincipalName $UserPrincipalName -ShowBanner:$false}
else {Write-Error 'Either -Credential or -UserPrincipalName must be used to create a session'}
我们正在尝试使用EWS管理的应用编程接口集成办公365。我们使用办公365管理中心创建了一个具有模拟角色的服务号。现在,我们如何使用该服务号访问应用程序中其他用户的数据(如邮件、联系人、日历)?谢谢,罗希特
您好,我正在使用服务帐户和添加的与会者创建一个活动。回复正确,但与会者没有收到邀请邮件。该服务账户未与任何谷歌账户链接(共享)。不过,为了登录API控制台,我使用了我的gmail帐户。日历Id被指定为主日历Id。活动将在哪里创建,在服务帐户的日历上还是在我的主日历上?。我在日历上看不到,但回复状态为“已确认”。我更感兴趣的是邀请,而不是最初的活动是在哪里创建的。 任何帮助都将不胜感激!!!
我想编写一些代码来查询Exchange服务器,以查找一组用户的日历条目。这可能吗? 我不熟悉使用EWS。我发现很难找到任何好的概述文档来指导我如何使用它。 无论如何,我正在尝试的代码是这样的: 最后一行抛出一个Service响应异常:"在存储区中找不到指定的文件夹。" 上述方法是否接近正确?也许有一种完全不同的更好的方法来实现这一点? 请注意,我上面的服务对象是一个ExchangeService对
我需要在日历上创建谷歌日历活动,并将其他用户添加为该活动的参与者。其目的是向应用程序用户发送日历事件,而无需征得他们的同意(O-Auth)。 在阅读了谷歌的留档后,我发现我需要一个服务号。所以我从我们的G-Suite的一个电子邮件地址创建了一个项目和一个服务号,noreply@xxxxx.com并为其启用了日历应用编程接口。 我创建并下载了一个密钥对(JSON),其内容是, 根据文档,我开始编写身
问题内容: PHP中有没有一种方法可以获取服务器上所有会话的列表(以及每个会话中的变量)? 基本上,我们具有维护功能,该功能需要知道当前哪些用户登录到该站点。我们已经在会话变量中存储了每个用户的数据,但是我希望可以遍历每个会话并提取所需的数据。 我的PHP非常有限(我通常是.NET开发人员),但是如果有人知道这样做是否可行(以及如何做到),我将不胜感激。我用谷歌搜索,发现的结果倾向于表明这是不可能
我正在尝试使用SpringBootInitialize创建一个SpringCloudEureka服务器。 但是我得到了下面的例外。 java.lang.IllegalStateExcture:未能加载应用程序上下文造成的:org.springframework.beans.factory.不满意依赖异常:错误创建名为'org.springframework.cloud.netflix.eureka