It is possible to access Exchange 2010 Addressbook from a PowerShell Script which is running on a client?
I want to access the addressbook, search by properties and work with the results.
I have not found any tutorial for the EWS and PowerShell.
[Reflection.Assembly]::LoadFrom("path to ews.dll")
$ExchangeService = new-object ExchangeServiceBinding
$paramName = New-Object UserConfigurationNameType
$paramName.Item = New-Object FolderIdType
$paramName.Name = "CategoryList"
$params = New-Object GetUserConfigurationType
$params.UserConfigurationName = $paramName
$params.UserConfigurationProperties = [UserConfigurationPropertyType]::ALL
$ExchangeService.UseDefaultCredentials
$ExchangeService.Url = "https://path.to.exchange/EWS/Exchange.asmx"
$ExchangeService.GetUserConfiguration($params)
I don't know about PowerShell, but you can accomplish this in Exchange Management Shell (EMC). PowerShell v2.0+ can run remote sessions, so the EMC commands can be used from your clients. Of course they'll need some Exchange rights to do this. Conveniently in Exchange 2010, RBAC allows you to give miniscule Exchange rights to your users. If this is not an option, you could do an LDAP query (that's what Outlook does) but I'm not sure of the exact procedure.
However, if it is an option:
1. Initiate your remote PowerShell session.
1a. $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionURI http://FQDNofCAS/PowerShell/ -Authentication Kerberos
1b. Import-PSSession $session
After that, try one of the following:
1. Get-GlobalAddressList
1b. Note the GAL you'll be using
2. $GAL = (Get-GlobalAddressList "Default Global Address List").DistinguishedName
2b. Replace _Default GAL_ with the output of step one.
3. Get-GlobalAddressList $GAL | Update-GlobalAddressList
4. Get-Recipinet -Filter {Addresslistmembership -eq $GAL}
4b. -Filter may require some tweaking to your specifics.
Note: See http://www.msexchange.org/articles_tutorials/exchange-server-2007/management-administration/address-lists-exchange-2007-part1.html for a better explanation of this.
--OR--
1. Get-User | where($_.RecipientType -like "*Mail*"}
Note: This will show all Mail-Enabled users, so it might not be exactly what you're looking for.
You need the Exchange EWS Managed API:
http://msdn.microsoft.com/en-us/library/dd637749.aspx
Related
I'm trying to write down a powershell script that will automatically finds the mailbox server and connect to it (using the URI https://mailboxserver/powershell).
Problem is I haven't found a way to automatically detect a mailbox server for a given exchange organization. I found a way how to find the CAS server because someone posted how the outlook finds this manually.
I tried to query AD but I do not know which attribute is unique to exchange mailbox server.
I also tried DNS records but found none which helps.
Does anybody know about a unique value of mailbox server which could be queried from AD or GC? Or a DNS record or something else I have not thought of?
Exchange 2010
I could post forest and domain functional level if necessary but I am on the way.
Thanks in advance
Your AD user attributes have this information, albeit you have to parse the mailbox server name from them.
HomeMTA
msExchHomeServerName
So if you have access to the AD cmdlets you might be able to get your mailbox server this way.
$adUser = get-aduser someuser -Properties msExchHomeServerName
$mailboxServerName = ($aduser.msExchHomeServerName -split "cn=")[-1]
Those attributes help you find your current mailbox is hosted. The mailbox server in my case was the last "item" in msExchHomeServerName so I split the string on "cn=" and then the last element of that array would be my mailbox server name.
Then you can use that to connect to an Exchange session!
$Credentials = Get-Credential
$exchangePath = "http://$mailboxServerName/PowerShell/?SerializationLevel=Full"
$ExSession = New-PSSession –ConfigurationName Microsoft.Exchange –ConnectionUri $exchangePath -Credential $Credentials –Authentication Kerberos
Import-PSSession $ExSession
Does the code below get you what you need? It uses EWS - see my SO post for further details on EWS.
# load the assembly
[void][Reflection.Assembly]::LoadFile("D:\Temp\Microsoft.Exchange.WebServices.2.2\lib\40\Microsoft.Exchange.WebServices.dll")
# set ref to exchange - may need to change the version
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
# replace with your email address
$email = "your.email#domain.com"
# grab your own credentials
$s.UseDefaultCredentials = $true
# discover the url from your email address
$s.AutodiscoverUrl($email)
$s.Url.AbsoluteUri
I have the same question as this person:
Remove all ex-employees from ALL distribution groups
There are quite a few disabled users who left the company and need to be removed from all DLs.
Disabled users are locatedin: uk.domain.int/USR/Disabled Users
DL's are located in: uk.domain.int/USR/Distribution Lists
There is the Powerscript provided by #Raymund
and I am not quite certain about the LDAP bit.
Would it be this in my case cos' I am not sure:
LDAP://OU=Disabled Users,OU=USR,DC=uk,DC=Domain,DC=int"
Just need to make sure that the PS script does not run on any other domain apart from the one uk.domain.int and targets disabled users only.
Please advise
ps: Powershell version: Major: 2 | Minor: 0 | Build -1 | Revision -1
This LDAP Filter LDAP://OU=Disabled Users,OU=USR,DC=uk,DC=Domain,DC=int" will look into UK subdomain, USR OU , Disabled Users OU.
Although provided script commands will do the job I rather use exchange management shell commands + active directory powershell module commands for this purpose. This is just to give you some Ideas to write your own script via the right tools.
import-module activedirectory
$session = new-pssession -configurationname microsoft.exchange -connectionuri "http://yourcasserver.yourdomian.com/powershell/" -authentication kerberos -credential (get-credential)
import-pssession $session
$users = get-aduser -filter * -searchbase "OU=Disabled Users,OU=USR,DC=uk,DC=Domain,DC=int"
get-distributiongroup
Another advantage of using Powershell commands is you can make sure of effect of each command in script by running int against a test user and a test DistributionGroup.
It's wise to test your scripts in lab environment first. Specially when your dealing with exchange in an Enterprise.
firstly just to say my powershell skills are limited so please be gentle ;-)...
So I've built 4 or 5 runbooks using microsoft Orchestrator to essentially run some remote powershell scripts which do various simple exchange tasks, such as setting OutOfOffice reply, enabling mailboxes, creating shared mailboxes with various permissions etc. I had been using the same basic connection structure/method for these which works fine, ie
$ExchangeCAS = "<CASServerName>"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<CASServerNameFQDN>/PowerShell/
import-PSSession $Session
<script body with exchange cmdlets>
remove-PSSession $Session
However, I'm trying to create an additional runbook to automatically add IP addresses as relay to our 4 hub servers - its a pretty basic script (that I dug out/tweaked from internet) but its not working when run from Orchestrator. It does work fine when I run it from the Powershell ISE on the server that has the Exchange Tools installed, and the fact that the other exchange (similar) scripts that do work would at least rule out any permissions issues for the Orchestrator service account executing the script. For reference below is the full script I'm trying to run from Orchestrator as a .Net Activity and am testing using the powershell ISE on orchestrator server:-
$ExchangeCAS = "<ExCAS>"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<ExCASFQDN>/PowerShell/
import-PSSession $Session
# Get Receive Connectors to update
$listofIPs = Import-Csv \\<TargetSERVER>\d$\psscripts\MailboxRightsScript\scorch\AddIPlist.TXT
$recCons= Get-ReceiveConnector | Where {$_.Name -match"Anonymous Relay"}
ForEach ($recCon in $recCons)
{
Write-Host "Updating", $recCon.Identity
forEach($line in $listofIPs)
{
$recCon.RemoteIPRanges +=$line.IP
}
Set-ReceiveConnector $recCon -RemoteIPRanges $recCon.RemoteIPRanges
}
remove-PSSession $Session
The error I can see from the Orchestrator server ISE is as below:
Cannot process argument transformation on parameter 'Identity'. Cannot convert the "\Anonymous Relay" value of type "Deserialized.Microsoft.Exchange.Data.Directory.SystemConfiguration.ReceiveConnector" to
type "Microsoft.Exchange.Configuration.Tasks.ReceiveConnectorIdParameter".
From trawling through some articles it seems this is an issue with how data is passed between local and remote powershell and 'hydration' of objects. TBH a lot of the detail of those discussions is a bit over my head when it comes to powershell, so not wishing to be lazy would anyone be able to provide a powershell script solution based on what I was trying above which I can run as a .net activity from Orchestrator to add an IP address/addresses (prefer from input file) as relay. It would be good to know if the solution is easily modified to remove an address as relay aswell.
Any help much appreciated...
Use server distinguish name. It will work
Set-ReceiveConnector $recCon.DistinguishName -RemoteIPRanges $recCon.RemoteIPRanges
I would like A PowerShell script to automatically connect to office 365 and to run as a scheduled task twice a day, THEN assign Reviewer permissions to new users if not possible then reviewer for all users. the reason being is because when a new user is created in outlook 365 their calendar permissions are set to free/busy.
i suggest you take a look at: OfficeDev/PnP - TimerJob
Shows how to create "remote timer job", which could be installed to be running as a WebJob to Windows Azure or scheduled to windows scheduler for on-premises deployment.
This is entirely possible, with the obvious downside that you'll need to store credentials for an account with permissions to edit all user calendars by default to run the script with.
There are two parts to the script that you'll require:
Connecting to Exchange Online
As shown here, connecting to Exchange Online is a very simple process.
Leaving the question of how to store credentials in a secure method out of scope of this question, this will result in a PowerShell session to the Exchange servers:
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
Selecting New Users
You'll then need to either select the new users (by passing them to this script, or scanning AD - this will depend on how you're creating your users - synced from AD or just created in-cloud), and apply the permission change to them. However...
Changing Default Permissions on Calendars
In this case, as I don't know how you're creating the new users, or how best to test that, I'm simply applying it to everyone. This will take far longer in a large environment, and is just a pretty bad idea.
Get-Mailbox -Filter {RecipientType -eq 'UserMailbox' -and IsShared -eq $false}| %{
Set-MailboxFolderPermissions -Identity "$($_.Alias):\Calendar" -User Default -AccessRights Reviewer
}
Finally, according to the original article, you should close the remote session.
Remove-PSSession $Session
Scheduled Tasks
After fixing the issue with credentials, you'll then want to save the script (ensuring that it complies with the Execution Policy on the system you'll be running it on), and create a new scheduled task to run it.
Configure a Scheduled Task as appropriate (in terms of triggers and conditions), and set the Action as Start a program, with that program being powershell.exe. Arguments should include -File C:\Path\to\Saved\Script.ps1 and any arguments (such as a file of new users).
Having said all of that, what you should actually do is change the sharing policy in 365, which will allow you to set the default permission for calendars.
i often use the New-MailboxExportRequest 's command on an exchange server in powershell console, like this one :
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst -verbose
it works correctly. But if I run those commands in PS remote session like this one :
I use the same User (Domain Admin, Exchange Admin)
Invoke-Command -ComputerName vdiv03 -ScriptBlock {
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst
}
I obtain this error :
failed to comunicate with mailbox database
with -verbose
Loading the snapin like that isn't supported in Exchange 2010.
IMHO, you'd be much better off just leveraging the native remoting built into Exchange for management tasks.
$ExchangeServer = <exchange serer name>
$SessionParams =
#{
ConfigurationName = 'Microsoft.Exchange'
ConnectionURI = "http://$ExchangeServer/powershell/"
Authentication = 'Kerberos'
# Credential = $Creds
}
$Session = New-PSSession #SessionParams
Invoke-command -ScriptBlock {New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst} -Session $Session
Remove-PSSession $Session
Set $ExchangeServer to the name of one of your Exchange 2010 servers. The account will need to be a member of the necessary RBAC role for the function you're performing, and you can uncomment the Credential parameter and provide alternate credentials for the session if you need to.
This will also elimnatat the need to have the management tools installed on the computer that's running the script, and the associated headaches of keeping it patched to the same level as what's on the servers.
If you're working interactively, or running a script that uses many Exchange cmdlets you can add the session creation to your profile, and do an Import-PSSession and you'll have proxy functions for the Exchange cmdlets available locally that you can use the same as if you'd loaded the snapin.
Import-PSSsession $Session
Some caveates to be aware of:
When you use implicit remoting like this, the account of the credentiaals used to establish the session will determine what capablilities you will have. What appear to be Exchange cmdlets added to the local session are actually proxy functions ( you can verify this using Get-Command). This set of proxy functions is created dynamically by Exchange when you initially establish the session and will be customized according to the RBAC roles the account making the connection belongs to. If it doesn't have permissions to perform given functions you will not get the proxy functions for those cmdlets, or functions may not have parameters for those functions.
The results you get back will not be the same as the same as the native objects returned if you used an EMS shell, or loaded the snapin. They will be deserialized objects, which means they may be missing methods and will lose some fidelity compared to the native objects. There will be very few instances where this will be an issue, or cannot by worked around.
Also be aware that when you use implicit remoting, updates are made under the authority of an Exchange system account, not your credentials. When you use the snapin, your account must have permission to update the Exchange properties stored in AD directly, and those changes will be logged in Windows audit logs (if enabled) as having been made by that account. When you use implicit remoting they will be recorded as being done by the Exchange service account. Exchange will record the details of the actual user account that made the request in it's admin audit log, and you can use Search-AdminAuditLog to find out when changes were made, and by who even if Windows audit logging is not enabled. If you use the snapin directly and do not have AD audit logging enabled you will lose that audit trail.