Agregar direcciones X500 para alternativa a LegacyExchangeDN

Si se ha recreado una (o miles) de cuentas de Mailbox o Contactos en Exchange, por más que se hayan ajustado las propiedades de las address books, habrán problemas con la cache del Cliente de Outlook. Este utiliza la propiedad de la cuenta “LegacyExchangeDN” para ubicar la cuenta, y si la cuenta recreada no tiene el mismo LegacyExchangeDN, no se podrá utilizar salvo que se limpie la caché del Cliente Outlook.
Lamentablemente, todos los correos que se respondan anterior a la fecha de cambio, también se guían con esta propiedad.
Para “salir del paso” (y que no nos maten), se pueden hacer 2 cosas:
  1. Modificar la propiedad LegacyExchangeDN: LO CUAL TRAE PROBLEMAS en PRESENTE y a FUTURO. 
  2. Agregar una dirección X500 con la ruta LegacyExchangeDN antigua.
Para ilustrar, si 1 mailbox o contacto (o miles) tenían como ExchangeLegacyDN:
“/o=FirstExchOrg/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=NOMBREAPELLIDO”
Y se recrea/n (se eliminan y se vuelven a crear), quizás la propiedad quede como:
“/o=FirstExchOrg/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=NOMBRE APELLIDO” (con espacio).

Esto, para los nuevos correos no hay problema, pero la caché de Outlook y todos los mensajes antiguos en mailbox que referencien a esta cuenta lo harán a “NOMBREAPELLIDO”

Agregando una dirección X500, volvemos a permitir que Outlook “encuentre” este elemento (es inmediato).

#region intro
  #descripcion: agregar direccion X500 a todos los contactos de una OU
  #fecha creac: 04/11/2013
  #versión    : 0.1 (04/11/13)
  #autor      : Jorge Mestre
  #Changelog  : 04/11/13 - Creado
#endregion intro
param( $archOrigen,`
       $ou = 'OU=NomOU,DC=Lab,DC=local'
     )

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction `
            SilentlyContinue
$ErrorActionPreference = "continue"

$LegacyDNRaiz = "/o=FirstExchOrg/ou=Exchange Administrative Group `
     (FYDIBOHF23SPDLT)/cn=Recipients/cn="
$contactos = Get-MailContact -OrganizationalUnit $ou

foreach ($con in $contactos)
{
 $user = $con.alias
 $user
 $con.EmailAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]`
(("X500:"+"$LegacyDNRaiz"+"$user"))
 Set-MailContact -Identity $con.alias -EmailAddresses $mails.EmailAddresses
}

Como "Bonus track", el código de Exchange de la propiedad es un EasterEgg:



comprobar que un host responde a varios puertos

Comprueba y registra el estado de puertos en un host remoto. Útil para detectar cortes si tenemos ofuscadas partes de la red.
 
#region intro
# nombre     : Comprobar-Puertos.ps1
# descripción: comprueba que un host responde a varios puertos
# fecha creac: 11/07/2011
# versión    : 0.2(15/07/2013)
# autor      : Jorge Mestre
# Changelog  : 11/07/2011 - creado
# Changelog  : 15/07/2013 - Agregado param $infinito
#keywords    : puertos,comprobar,telnet
#endregion intro


param($puertos,$dst,[switch]$infinito,$tamLog)

if (
 ((-not $puertos) -or (-not $dst)) -or `
 (($infinito) -and (-not $tamLog)))
{
  Write-Host "faltan argumentos`nEj: .\comprobar-puertos.ps1 -dst `"server`" `
  -puertos 80,81,9000 [-infinito -tamLog MB]" -ForegroundColor Yellow
  exit
}
#region MODIFICAR
$ArchLog = ".\LogPuertos.log"
$LimTamArchLog = $tamLog # MBs
$intervalo = 5 # segundos
#EndRegion MODIFICAR

#Region Funciones
function RevisarTamLog($ArchLog)
{
 $tamArch = ((Get-Item $ArchLog).length)/1mb | Out-Null
 if ($TamArch -gt $LimTamArchLog)
 {
  rm $ArchLog
 }
}

function eLog($texto)
{
 $fecha = get-date -F "dd/MM/yyyy - hh:mm:ss"
 $txt = "$fecha`: puerto $puerto en $dst $texto"
 Write-Host $txt
 $txt | Out-File -Encoding utf8 -delimiter ';' -Append $ArchLog
}

function comprobarPuertos
{
 RevisarTamLog $ArchLog
 foreach ($puerto in $puertos)
 {
  try
  {
   $socket = new-object Net.Sockets.TcpClient
   $socket.Connect($dst, $puerto)
   $socket.Close()
   eLog "abierto"
  }
  catch
  {
   eLog "cerrado"
  }
  $socket = $null
 }
}
#EndRegion Funciones

#Region principal
if (-not $infinito)
{
 comprobarPuertos
}
else
{
 while (1 -eq 1)
 {
  comprobarPuertos
  sleep $intervalo  
 }
}
#EndRegion principal

Función para Enviar correo

Function Enviar-Correo
{
 #region intro_funcion
  #descripcion: Enviar correo con formato HTML de un objeto de PS
  #fecha creac: xx/xx/11
  #versión    : 0.3 (31/10/13)
  #autor      : Jorge Mestre
  #Changelog  : xx/xx/11 - creado
  #Changelog  : 05/08/13 - Corregido formato y agrupado en una sola funcion.
  #Changelog  : 31/10/13 - Parametrizacion
 #endregion intro_funcion
 [CmdletBinding(PositionalBinding=$false)]
 param(
 [Parameter(Mandatory=$true)]$cuerpo,
 [switch]$cuerpoHTML,
 [switch]$attach,
 $asunto     = 'Prueba envío',
 $cabecera   = "Primera linea en el cuerpo del correo",
 $de         = "prueba@labo.local",
 $para       = ("dest1@labo.local","destN@labo.local"),
 $SMTPserver = "hostname_server_SMTP"
 )
 
 #Formato tabla HTML
 [string]$fhtml = "<style>"
 $fhtml = $fhtml + "TABLE{font-family:Arial,Helvetica,sans-serif;`
          border-spacing:1px;border-width: 1px;border-style: solid;`
          border-color: black;border-collapse: collapse;}"
 $fhtml = $fhtml + "TH{white-space: nowrap;border-spacing:1px;font-size:10pt;`
          border-width: 1px;padding: 3px;border-style: solid;border-color: black;`
          background-color:#E0ECFF}"
 $fhtml = $fhtml + "TD{white-space: nowrap;border-spacing:1px;font-size:10pt;`
          border-width: 1px;padding: 3px;border-style: solid;border-color: black;}"
 $fhtml = $fhtml + "</style>"
  
 #si es un Array, convertirlo en HTML
 if (-not $cuerpoHTML)
 {
  $infoExtra = try{InfoExtraScriptCorreo}catch {""}
  [string]$cuerpo = $cuerpo | convertto-html -Head $fhtml
  $cuerpo = '<p>'+$cabecera+'</p>'+$cuerpo+$infoExtra
 }
 
 if ($attach)
 { 
  Send-MailMessage -To $para -Subject $asunto -SmtpServer $SMTPserver -From $de `
  -Body $cuerpo -Bodyashtml:$true  -Encoding ([System.Text.Encoding]::UTF8) `
  -Attachments $attach 
 }
 else
 {
  Send-MailMessage -To $para -Subject $asunto -SmtpServer $SMTPserver `
  -From $de -Body $cuerpo -Bodyashtml:$true  ` 
  -Encoding ([System.Text.Encoding]::UTF8)
 }
} # Function Enviar-Correo


 
PS >; $unArray = Get-Command | select name,Module -last 10
PS >; Enviar-Correo -cuerpo $unArray


try...catch en powershell, prueba de concepto

$puerto = 3380 # puerto inválido
$servidor = "localhost"

"vamos con try...`n"
try
{
 $socket = new-object Net.Sockets.TcpClient
 $socket.Connect($servidor, $puerto)
 $socket.Close()
 "abierto"
}
catch
{
 "cerrado (con try)"
 $conCatch = $_.Exception
}

"vamos con if...`n"
$socket = $null
$socket = new-object Net.Sockets.TcpClient
$socket.Connect($servidor, $puerto)
if ($socket.Connected)
{
 $socket.Close()
 "abierto"
}
else
{
 "cerrado (con if)"
}
$socket = $null

"`ncon Catch, el error no me saltó en el medio del script, abajo lo pongo`
 (controlando cuando muestro el error):`n"
write-host $conCatch -ForegroundColor green 

 

Formatear texto en Capitales "EL TEXTO" > "El Texto"

function ProperCase($txt)
{
 ## String -> String
 ## Formatea de Forma Capitalizada: EL TEXTO > El Texto
 $txt = $txt.ToLower()
 $txt = [Regex]::Replace($txt, '\b(\w)', { param($m) $m.Value.ToUpper() })
 return $txt.trim()
}
 
PS > ProperCase "HOLA QUE tAl ToDO Bien"
Hola Que Tal Todo Bien