How to get SMTP server name through PowerShell when $PSEmailServer is empty? - powershell

Windows 7, PowerShell 4.0. Computer is in the Windows domain.
I need to get SMTP server name (for using of the send-mailmessage cmdlet). The $PSEmailServer is empty.
I read this TechNet page about the Get-AcceptedDomain cmdlet. But I see this (on the TechNet page):
This cmdlet is available in on-premises Exchange Server 2016 and in
the cloud-based service.
How can I get SMTP server name or its IP-address?

If properly defined, the SMTP server address, either host name or IP, can be set through the SCP record in AD or Autodiscover DNS record of Exchange Server. There is a Powershell solution for querying SCP but Autodiscover solution is shorter, so I'll go on with it.
This works on Exchange Server 2010 and later. It should work with Exchange Server 2007 also but personally I have never used it.
You can get the host name;
$MailServer = [Net.DNS]::GetHostByAddress([Net.DNS]::GetHostEntry("Autodiscover").AddressList[0]).Hostname
or IP address (as string);
$MailServer = [Net.DNS]::GetHostByAddress([Net.DNS]::GetHostEntry("Autodiscover").AddressList[0]).AddressList[0].IPAddressToString
Since the GetHostByAddress(string) returns an instance of class System.Net.IPHostEntry, you can have some properties to make use of. For details, please read Microsoft Docs.
PS: I know, that's not the best practice to use the index of integers for values, but AddressList is an array of strings. So it does not define a method such as FirstOrDefault() or a property like DefaultAddress. So far, that is the most optimal and practical solution AFAIK.

Assuming the computer is member of a domain with Exchange deployed, and you want to use Exchange as STMP relay for send-mailmessage, you could ask the exchange configuration in the AD Configuration Context:
import-module activedirectory
$ag = "Exchange Administrative Group (ABCDEFGHIJKLM)" #enter your EAD
$c = "Acme" # Enter your company name (get this form ADSIEdit if unknown)
$sb = ("CN=Servers,CN=" + $ag + ",CN=Administrative Groups,CN=" + $c + ",CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=staff,DC=hsrw")
$server = Get-ADObject -Properties cn, msExchSMTPReceiveConnectorFQDN, msExchSmtpReceiveBindings, msExchSMTPReceiveInboundSecurityFlag -SearchBase $sb -filter { objectClass -eq "msExchSmtpReceiveConnector"}
$server | ft cn, msExchSMTPReceiveConnectorFQDN, msExchSmtpReceiveBindings, msExchSMTPReceiveInboundSecurityFlag
This will spit out the hostnames and port bindings of every receive connector in your organisation. You then have to choose which one to use.
As I don't know how much Exchange knowledge you have, I will stop here. If something's unclear, just ask.

Related

Check who is Cached mode client - Exchange 2019 on premiss, Office365 Clients

In the last few days i was looking for a way to make report or gather information about all outlook users, which of them are using Chache mode, and who are connected online.
As mentioned in Title, we are working with Exchange 2019 on premiss, and all of our clients using Office365.
Here and there, i found few ways to find out about it, but all of thos ways are related to older server/client versions. like:
Some scripts looking for some registry values. in specific - "00036601" key, but not only. because some offers other keys which supposed to be there for Office365 clients, but are not there in my case.
Use Exchange Shell involving Get-LogonStatistics, but this cmdlet is not working in Exchange 2019.
Proccess RPC Client Access Logs, but RPC connections are blocked in our network, and Outlook clients access the servers via HTTPS. tried to look into HTTP MAPI logs, but coudn't find there somthing that tells me weather the client is Cached mode or not.
The only way i've found that works, is to use client-side script, base on user identity, to load MAPI to Powershell and find out it's status:
$outlook = New-Object -com Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$mailbox = $namespace.Stores | ? {$_.displayname.split("#")[0] -like $env:USERNAME}
$result = $env:USERNAME + ": " + $env:COMPUTERNAME + ": " + $mailbox.IsCachedExchange
$result | Add-Content -Path "\\server\Network-Shared-Folder\chache.txt"
if (!(Test-Path C:\users\$env:username\documents\cache)) {
New-Item -ItemType Directory -Name cache -Path C:\users\$env:username\documents\
}
"Done" | Add-Content -Path C:\users\$env:username\documents\cache\testresult.txt
I can distribute this script with SCCM and some of the line i wrote for detection method. so i can run it also with Invoke-Command or other ways.
But in the bottom line, i'm not eager to use this way, since it's involve the client side and identity, and can interfere with his own work on outlook.
I'm looking for different way, server-side preferably, to gather this information.
Ofcource, something that is works with Exchange 2019 On-Premiss, and Office365 Clients which connecting via HTTPS.
Thanks for help.
Yosi.
I don't think you can do that from the server - caching is client-only feature, plus a single Outlook profile can access the primary mailbox in the cached mode, but a delegate mailbox in on online mode.
More than that, for some feature cached Outlook might open server objects in the online mode, e.g. when searching, and the user wants older items not cached locally.

Possible to use PowerShell's Get-AppvClientPackage to list AppV packages on a machine other than my own?

I can use Get-AppvClientPackage -all [| select name] or Get-WmiObject -Namespace root\appv -Class AppvClientPackage [|select name] to list all installed AppV packages installed on my own machine. It doesn't appear to be possible to use this cmdlet to get the AppV packages installed on another machine, without remote execution.
I am asking this question in hopes of finding something that works (see purpose) or get a definitive answer that it's not possible. There may be better options available (other than PS), but my question is simply if it is possible or not, so that if the latter is the case, we can push to develop a script (which could be run by someone with elevated privileges) to gather information needed.
Purpose: Our team doesn't have visibility into SCCM (that's another option is to have that team report on what is installed where, though sometimes we need answers quickly) and remote PS execution is restricted to one security team (which is understandable), but at times (for support or decommission purposes) we need to check to see if a specific client machine has a package installed, check what AppV packages a specific client has installed, as well as check to see which machines have a particular package installed.
If there is another module or cmdlet (or even something other than powershell or WMI) that might be able to yield the same information, suggestions are welcome.
Get-WmiObject utilizes RPC to connect to remote PCs and does not require PSRemoting. In this effort, all you need to do is add the -ComputerName parameter.
#Requires -Version 3
$Target = 'localhost'
$Params=#{
Namespace = 'root\appv'
Class = 'AppvClientPackage'
Property = 'Name'
ComputerName = $Target
}
Get-WmiObject #Params
PS C:\> Get-Help -Name 'Get-WmiObject' -Parameter 'ComputerName'
-ComputerName <String[]>
Specifies the target computer for the management operation. Enter a fully
qualified domain name (FQDN), a NetBIOS name, or an IP address. When the remote
computer is in a different domain than the local computer, the fully qualified
domain name is required.
The default is the local computer. To specify the local computer, such as in a
list of computer names, use "localhost", the local computer name, or a dot (.).
This parameter does not rely on Windows PowerShell remoting, which uses
WS-Management. You can use the ComputerName parameter of Get-WmiObject even if
your computer is not configured to run WS-Management remote commands.
Required? false
Position? named
Default value None
Accept pipeline input? False
Accept wildcard characters? false

Finding mailbox server

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

How to check if a server is running windows 2003 or Windows 2008 by checking its RDP screen, through script?

We have recently acquired a small firm having 1500 servers on which our team doesn't has access as of now although they are in domain. We need to find out how many servers are running Windows 2k3 and how many are Windows 2k8.
I know the RDP screen of both of these versions are different , for example: if we RDP a Win2k3 machine, it gives a warning notice first and once we click Ok, it takes us to the credentials screen , but in case of Win2k8, it directly takes us to Crendentials which is a proof of the OS on the server. Doing this manually for 1500 servers is a time consuming task.
Can we implement this RDP screen logic using a script to find out the Windows OS version.
I can imagine an Algorithm something like that:
Enter server name.
Invoke mstsc for that server
Verify if the dialogue box is a direct prompt for credentials or not?
If so, print Windows 2k8, else 2k3/2k.
If this logic successful on one server, I can use it in a foreach loop for all servers and export in in Excel.
With 1500 servers I'm going to assume that you have an Active Directory in place. In that case you should be able to simply run a query against AD to retrieve the desired information:
Import-Module ActiveDirectory
$server = 'somehostname'
$dc = '...' # domain controller of trusted domain
$fltr = "OperatingSystem -like '*server*'"
Get-ADComputer -Filter $fltr -Property OperatingSystem -Server $dc |
Where-Object { $_.Enabled } |
Select-Object Name, OperatingSystem |
Sort-Object OperatingSystem, Name
Pipe the result into Export-Csv to create a CSV file that you can import into Excel.

Specify domain controller with get-aduser in powershell

Get-ADUser -identity $ntaccount1 -properties name, samaccountname, mail, enabled, passwordlastset
Is it possible, when looking up the user account information in powershell, to specify a domain controller to use? We have some DC's that get the data faster than others.
From Get-Help Get-ADUser -Parameter *
-Server <string>
Specifies the Active Directory Domain Services instance to connect to, by providing one of the following values for a
corresponding domain name or directory server. The service may be any of the following: Active Directory Lightweight Domain
Services, Active Directory Domain Services or Active Directory Snapshot instance.
Domain name values:
Fully qualified domain name
Examples: corp.contoso.com
NetBIOS name
Example: CORP
Directory server values:
Fully qualified directory server name
Example: corp-DC12.corp.contoso.com
NetBIOS name
Example: corp-DC12
Fully qualified directory server name and port
Example: corp-DC12.corp.contoso.com:3268
The default value for the Server parameter is determined by one of the following methods in the order that they are listed:
-By using Server value from objects passed through the pipeline.
-By using the server information associated with the Active Directory PowerShell provider drive, when running under that drive.
-By using the domain of the computer running Powershell.
The following example shows how to specify a full qualified domain name as the parameter value.
-Server "corp.contoso.com"
Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false
I know that this is a bit of an old question, but I would like to expand on the answer given, to aid anyone else who had a similar query.
The following allows you to define a specific Domain Controller, which the entire of a script would be able to use... Why might you want to do this when the -server parameter is available to Get-ADUser, New-ADUser, Set-ADObject, etc?
Well I put together a script that creates an AD user, sets multiple properties and creates an exchange mailbox - However, one set of properties revolves around the RDS properties on a 2008 R2 user account, which cannot be set from within New-ADUser. I had to create a function that calls ADSI and uses psbase.invokeSet to update the settings. There is no parameter setting for -server that I'm aware of.
This in itself wouldn't be a big deal, but the script also creates an Exchange mailbox for the user. As my Exchange server is in different AD Site from my workstation, the user account gets created on my local DC, but the mailbox isn't set, because the DC in the same site as the Exchange server hasn't yet received a replicated copy of the new user account.
The solution I found is as follows and is courtesy of http://www.joseph-streeter.com/?p=799
Having loaded import-module activedirectory, you'll have access to AD options in the New-PSDrive commandlet which among everything else allows you to define a new Active Directory Provider to work with.
New-PSDrive -Name <<NameofYourChoice>> -PSProvider ActiveDirectory -Server <<DC Server>> -Root "//RootDSE/" -Scope Global
Once created, you can then change the working Provider with the following command.
CD <<NameofYourChoice>>:
To view the existing list of Providers, type Get-PSDrive. AD is the default Active Directory Provider created when using the ActiveDirectory commandlet. You should also see your newly created Provider.
So for instance if my remote DC is called RemoteDC I would run:
New-PSDrive -Name RemoteAD -PSProvider ActiveDirectory -Server RemoteDC -Root "//RootDSE/" -Scope Global
to create a new Provider called RemoteAD. If I then run:
CD RemoteAD:
All further active directory related commands in the script or the active shell will work with the new Provider RemoteAD. If I would need to change back to my original Provider, I'd simply type
CD AD:
Hope someone finds this useful...
This is what i use:
Get-ADUser -server dcservername.domain.local -identity username