Mysterious Mails, Delivery Notices, Bounced mails Vs Outlook Delegates


This is what happened to me on one fine day. An Executive Admin complaints that she was getting Exchange mail delivery notices and bounced mails (NDRs) from an unknown user. 

She said it’s pretty annoying that she sends mails to bunch of users and gets bounced mails from some unknown (or long gone) users. I assured her that I will find out the issue and solution.

I laid back with my tea and thinking about the issue. If she sends mails to someone, but she gets NDRs (delivery notices in other cases) from a user who was not in TO or CC or BCC list. I know that Outlook Delegates are gets mails and meeting requests behalf of whoever delegated. I finished my last sip of tea and said myself, That is it.  "Delegates".

I started wondering about how to find out if anyone is delegated to someone else or not. After a few Live and Google search, I found out Active Directory stores the delegates and delegated users list in User properties. The following properties has the list of delegates,

publicDelegates
publicDelegatesBL

I wrote a script to find out who’s delegated to whom. I ran my script against the "bunch of users" given by Admin. Voila!!! I found the list of delegates, made some phone calls and fixed the issue.  I informed the admin with the details and she praised "IT is great!!!" as always.

If you are the guy who is sipping your coffee or tea like me thinking about the same issue, Help is on the way here in this blog.

1. Manual Lookup of delegates

1. Open the ADSIEdit.msc by typing it in Start –> Run.
2. Expand Domain [domain name] container and find the user you want to check
3. Right click on the User and select "Properties"
4. Find publicDelegates and publicDelegatesBL properties and check the value

2. Use my Script to find out the delegates

Copy and Paste the following script in Notepad and save as "Delegates.vbs" to an known location.
Open Command prompt, go the directory where you saved the Delegates.vbs file.
Run "CScript Delegates.vbs <UserAccountName>"

e.g., CScript Delegates.vbs JDoe
CScript Delegates.vbs BGates

If you find what you looking for, Thank me.

‘*****************************************************************************
‘*****************************************************************************
‘*********                          DELEGATES.VBS                   **********
‘********* Parameters: Active Directory User Account Name           **********
‘*********                                                          **********
‘********* This script displayes User X’s Delegates and who else is **********
‘********* delegated to User X in Exchagne 2000/2003 via Outlook.   **********
‘*********                                                          **********
‘********* Usage: Cscript Delegagtes.vbs JDoe                       **********
‘*********                                                          **********
‘********* Written By: Anand Venkatachalapathy                      **********
‘*****************************************************************************
‘*****************************************************************************

Dim rootDSE                 ‘LDAP Direcotry Services Object
Dim DomainContainer         ‘Currently logged On Domain
Dim conn                    ‘ADODB connection object
Dim sUID            ‘Account Name from command line parameter
Dim ldapStrUsers            ‘LDAP Query
Dim rs1                     ‘LDAP Query Result Set
Dim FoundObject             ‘LDAP Query Result value
Dim objArgs                 ‘Commmand line Arguments

‘Find the local logged on AD Domain name
Set rootDSE=GetObject("LDAP://RootDSE")
DomainContainer = rootDSE.Get("defaultNamingContext")

‘If you know your domain name, you may comment the above two lines and
‘Assign your domain name yourself. Uncomment the below line and change
‘the Domain name as below format
‘DomainContainer = "DC=local,DC=company,DC=com"

‘ Connect to Active Service Connection provder
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "ADSDSOObject"
conn.Open "ADs Provider"

‘Get the command line parameter
Set objArgs = WScript.Arguments

If objArgs.Count = 0 Then
   WScript.Echo "Invalid Arguments!! provide a user account name as below…"
   WScript.Echo
   WScript.Echo "CScript Delegates.vbs jdoe"
   WScript.Quit
End If

sUID =  objArgs(0)  

‘Make a LDAP query string
ldapStrUsers = "<LDAP://" & DomainContainer & ">;(&(&(& (sAMAccountName=" & _
               sUID & ") (| (&(objectCategory=*)(objectClass=*)) ))));adspath;subtree"

‘Run the Query
Set rs1 = conn.Execute(ldapStrUsers)

‘Loop through the result set
While Not rs1.EOF
   Set FoundObject = GetObject (rs1.Fields(0).Value)
   WScript.Echo FoundObject.CN
   WScript.Echo "—————————————-"

   ‘Call the ListDelegates sub routine
   ListDelegates "LDAP://" & FoundObject.distinguishedName, FoundObject.CN

   rs1.MoveNext   ‘Move to next result
Wend

‘Free up the memory
Set rs1=Nothing
Set conn = Nothing
Set rootDSE = Nothing

‘*****************************************************************************
‘********** Sub Routine: ListDelegates                              **********
‘********** Parameters: User’s AD Distinguished Name, Common Name   **********
‘**********                                                         **********
‘********** This sub find the provided user’s delegates and others  **********
‘********** delegated to the same user. Technically, it displays    **********
‘********** PublicDelegates and PublicDelegatesBL values from the   **********
‘********** Active Directory User Properties                        **********
‘*****************************************************************************
Sub ListDelegates(sDN, sCN)
    Dim oUser   ‘User Object
    Dim objRecip ‘Dummy User Object

    Set oUser = GetObject (sDN)
    Set objRecip = oUser
    WScript.Echo "Users Delegated to " & sCN
    vDelegates = objRecip.publicDelegates
    nDelegates = UBound(vDelegates)
    If nDelegates > 0 Then
        i = 0
        Do While i <= nDelegates
            WScript.Echo vDelegates(i)
            i = i + 1
        Loop
    End If
    WScript.Echo sCN & " delegated to these users "
    vDelegates = objRecip.publicDelegatesBL
    nDelegates = UBound(vDelegates)
    If nDelegates > 0 Then
        i = 0
        Do While i <= nDelegates
            WScript.Echo vDelegates(i)
            i = i + 1
        Loop
    End If

    objRecip = Nothing
    oUser = Nothing
End Sub

Advertisements

RunAs using VBScript


If you want a VBScript to run a program using RunAs DOS command, go straight to the bottom of the blog. If you want to read the build-up for the final product, keep reading.

Time to time I came across I wanted to run a script or program as administrative privileges. The few needs are like,

  • Install a program or do something on client machines via logon script
  • Run a program using different account

Duh! RunAs command. Sure RunAs command works, but using VBScript??? You can find a VBScript example for running a program using RunAs command like below,

set oShell= Wscript.CreateObject("WScript.Shell")

oShell.Run "runas /user:domainaccount ""Notepad.exe""", 2      ‘Note 2 means minimized Window
WScript.Sleep 100

oShell.Sendkeys "password~"    ‘Note the ~ character in the end. ~ means ENTER

Wscript.Quit

What’s wrong with the above script? After all it should work as expected. You know who the villain for above script. Guess…..OK. It’s attention hungry programs. When you run this script, it might send the password keys to wrong window,  while you running along with zillion programs in foreground and background. So what to do?

I rewrite the script few times and tested the script running along many programs. (Take ‘many programs’ as WinDVD, IE, Downloading a file in IE, Notepad, Command prompt and Active Directory Users and Computers). The final product is below,

Dim oShell
set oShell= Wscript.CreateObject("WScript.Shell")

oShell.Run "runas /user:domainuser ""program.exe""",2     ‘Note 2 means minimized Window
WScript.Sleep 100

For i = 0 to 10
      oShell.Popup "Opening Program.exe…",3,"Administrator",0+64  
     
‘3 means 3 seconds, 0+64 means OK button with Information Icon
     

      Activated = oShell.AppActivate ("runas")
      WScript.Sleep 10

      If Activated = 0 Then
             oShell.Sendkeys "password~"           ‘Note the ~ in the End..~ means ENTER
             Exit For
      End If
Next

Wscript.Quit

Few Tips and Tricks:

  1. If you want to run a VBScript in runas, try running RunAs /user:domainuser "WScript script1.vbs"
    • RunAs command run only executable files, so *.VBS or *.JS will not run
  2. If you want to run an *.MSC file, try running RunAs /user:domainuser "MMC test.msc"
  3. If you want tor run an Non-Executable file (other than above), try creating a DOS batch file and run the batch file using RunAs
  4. It’s not really safe to leave the VBScript file command location. Passwords are visible to any eyes. Try Encoding the VBScript using VBScript Encoder (can be downloaded from Microsoft).

Alternatives

For non-believer of my above VBScript sample, here is the nice list of alternatives.

http://www.commandline.co.uk/sanur_unsupported/index3.html

http://www.wingnutsoftware.com/erunas.html

http://www.shareup.com/RunAs_Professional-download-12339.html

Display more than 2000 Users (objects) in Active Directory Users and Computers Console


I have had it. We have more then 2000 objects to be displayed in Active Directory Users and Computers console every time I open it. This goddamn console doesn’t stick the Maximum number of items displayed per folder. Somehow it goes back to 2000.

Then I found a workaround by creating my own MMC console. That resolved my problem. Now, I am very 🙂 to see all the users in ADUC console every time I open it. No nagging warning popup windows.

If somebody frustrated with ADUC console with the same problem, here is the help to make a custom MMC console with custom settings.

1. MMC” in Start -> Run.

sshot-1.jpg

2.  Select File  -> Add/Remove Snap-in. Click Add.

sshot-2.jpg

3. Select "Active Directory Users and Computers”. Add and Click OK.

sshot-3.jpg

4. Select the Active Directory Users and Computers in MMC console. Click View and Filter Options. Type the number (of objects you want to see). Click OK to Close.

sshot-4.jpg

5. Click File -> Save. Type the name and your own location. It will be saved as *.mmc e.g., Active Directory Console.msc.

sshot-5.jpg

6.You can double click that saved mmc file (e.g., Active Directory Console.msc) to open the ADUC console with your own custom options. Custom options will stick permanently.

7. Thank me if you find it useful. 😉

VBScript: Monitor a folder for new files


The Following link from MS Technet Script Center was exactly what I wanted.

Link to Hey, Scripting Guy! How Can I Automatically Run a Script Any Time a File is Added to a Folder?

Scripting guys at Technet are doing a great job on scripts and examples. I usually I look in script center before I try searching all over the Internet. I met Peter Costantini and Dean Tsaltas on a NT user group occation. Awesome guys.

Exchange ActiveSync Gripes


Notes and ActiveSync – Why?

I came pretty disappointed when I realized Exchange ActiveSync is not supported with (Outlook) Notes sync. So,I looked Exchange 2007 Active Sync and no where mentioned Notes sync is on the horizon. So, I take it Notes sync will never be included in ActiveSync now or in future.

According to this link, Exchange 2007 ActiveSync can sync voice messages and fax attachments from mailbox, but NOT "Notes".

I don’t know what complication MS has with Notes synching using Exchange ActiveSync. Otherguys on the same block (BlackBerry, Good, iAnywhere,Seven, etc.,) have no problem synching Notes.

PocketPC/Smartphone Backup and ActiveSync – Missing feature

You know what else would be really cool feature…over the air Backup and Restore. I know iAnywhere has it with OneBridge software. It’s a full backup (including memory card) to the server wirelessly. If it saves you at least one time  in a critical situation, it’s worth it. May be, some third party guys should work on extending Exchange ActiveSync if it is possible. (On this paragraph,I have to mention that WM5 has no in-built backup feature and I don’t see it in ActiveSync 4.5 Beta 2)

ISA 2004: OWA, RPC/HTTP, OMA, ActiveSync on same Listener (works)


Here is one conflicting information goes around the Internet. ISA 2004 cannot publish all four Exchange features (OWA, OMA, ActiveSync and RPC/HTTP) in one single listener. I have searched the Microsoft site (technet) and ISAServer.org.  Here is the links for related ISA 2004 and Exchange publishing.

http://www.microsoft.com/technet/isa/2004/plan/outlook_web_access_publishing_ee.mspx

http://www.microsoft.com/technet/isa/2004/library/default.mspx

http://www.isaserver.org/articles/2004pubowartm.html

http://www.isaserver.org/tutorials/Redirecting-OWA-Users-Part1.html

http://support.microsoft.com/kb/839357/en-us

http://www.isaserver.org/articles/2004unihomedowapart1.html

 

None of the above links describes how to run all 4 features published in one single listener on same External network card. The problem I am talking about is this….

-OWA needs to be setup with Forms Based Athentication on ISA 2004 server (more secure design)

– Rest of the items (OMA, ActiveSync and RPC/HTTP) requires Basic Authentication (over SSL). Outlook 2003 or mobile devices will not handle the Form Based Authentication, so it needs to be on Basic authentication.

So, all the Microsoft and other documents leads to create two different listeners (one with FBA and one with Basic authentication). Two listener cannot listen on same IP address and same port (443). Two different listener means two different IP addresses.  And it also means two different domain names (owa.xxx.com and rpc.xxx.com). It complicates more like we have to buy two different digital certifications from provides (VeriSign) unless you choose to run Certificate Services in home.

Then, I found this article and may shed light for the solution: http://www.isaserver.org/tutorials/2004pubowamobile.html.

After I reading the above link, I realized this is not going to work for me. We bought a SSL certificate from legitimate provider and we don’t run certificate services at my company and we don’t plan to setup. For some small business and other companies, it may do some magic.

I was frustrated and about to gave up. I fiddled around and found something in the middle. All four features (OWA, OMA,ActiveSync and RPC/HTTP) are working on a single listener. Here is my setup. See the drawing and I will explain it below.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Here is the steps:

– Create a Listener called FBA_443_Listener with above settings in the drawing. Note this listener has only FBA selected. Don’t forget to set the default domain (your AD domain). If the users are from different domain in the forest, they have to type "domainusername" format.

– Create a Firewall Rule with Mail Server Publishing Wizard. Name it "OWA Publishing Rule". Select only OWA during the wizard. Setup the rule with above settings as it is in the drawing. When asked, select FBA_443_Listener. You need to enter path after finish creating the rule.

– Create a second firewall rule with Web Server Publishing Wizard and name it "RPC/HTTP,OMA and ActiveSync Publishing Rule". (Note the bold letters, this has to be created using web server publishing wizard and NOT using mail server publishing wizard). When asked, provide the path name as /rpc/* with your OWA domain name (mail.xxx.com). Make sure the settings are correct with above drawing. You need to add all the paths manually after creating the rule.

Voila! It worked. I am no geek on ISA server side, but here the explanation. The magic here is you create the rule for RPC, OMA and ActiveSync using WEB SERVER PUBLISHING WIZARD. I still don’t get it that how Outlook and my Mobile handles Form based authentication with above setup. But some how it handles it.

One possibility is Microsoft made Outlook and WM5 to manage the FBA through the latest patches. OR ISA 2004 with SP2 handles the NON Browser calls with Basic Authentication. So, don’t forget to patch your servers and clients.

Here is the result:

– Outlook Web Access link is provided with FBA logon page

– OMA provided with Basic Authentication page

– ActiveSync works and NO errors

– RPC/HTTP is provided with logon window in Outlook 2003 and it works without errors

This above setup works and I can do all four Exchange features beautifully.  With all that above, I am running ISA 2004 in single network configuration. The listener is set to listen on local network.

Hope it helps someone desperately looking for the information.

Convert UTC to local time and vice versa using VBScript


 

Today, I was stumbled upon UTC time conversions. I needed to convert UTC date/time to local date/time and vice versa. I was hunting this information everywhere with no luck.

I didn’t get the straight answer anywhere. So, I gathered all the info and created two VBScript based Functions. Hope it helps someone.

Here is the formula for converting time:

Local time to UTC: local time + (Bias / 1440 ) = UTC 
UTC to Local Time: UTC – (Bias/1440) = Local Time

Bias is available on the registry which tell what Time Zone is on the local computer. You can check the registry location at HKEY_LOCAL_MACHINESystemCurrentControlSetControlTimeZoneInformationActiveTimeBias

The ActiveTimeBias is the value of Bias/1400.

So, it came down to Adding the Bias to Local Time gives you the UTC time and Subtracting the Bias from UTC gives the local time.

Now the VBScript implementation of converting the times back and fourth.

‘*************************************************************************
‘ Name: ConvertToUTCTime ( sTime as Date )
‘ Parameters: Takes the Local Time. eg., 11/07/2006 10:00:00 AM
‘ Returns the converted UTC Time as 2006-11-07T18:00:000Z

‘ Written by : Anand Venkatachalapathy
‘*************************************************************************
Function ConvertToUTCTime(sTime)

          Dim od, ad, oShell, atb, offsetMin
          Dim sHour, sMinute, sMonth, sDay

od = sTime
‘if you passed sTime as sting, comment the above line and
‘uncomment the below line.
‘od = CDate(sTime)

‘Create Shell object to read registry
Set oShell = CreateObject("WScript.Shell")

atb = "HKEY_LOCAL_MACHINESystemCurrentControlSet" & _
"ControlTimeZoneInformationActiveTimeBias"
offsetMin = oShell.RegRead(atb) ‘Reading the registry

‘Convert the local time to UTC time
ad = dateadd("n", offsetMin, od)

‘ If Month is single digit value, add zero
sMonth = Month(CDate(ad))
If Len(sMonth) = 1 Then
            sMonth = "0" & sMonth
End If

‘If Day is single digit, add zero
sDay = Day(CDate(ad))
If Len(sDay) = 1 Then
          sDay = "0" & sDay
End If

‘if Hour is single digit, add zero
sHour = Hour(CDate(ad))
If Len(sHour) = 1 Then
          sHour = "0" & sHour
End If

‘if Minute is single digit, add zero
sMinute = Minute(CDate(ad))
If Len(sMinute) = 1 Then
         sMinute = "0" & sMinute
End If

‘Assign the reutrn value in UTC format as 2006-11-07T18:00:000Z
ConvertToUTCTime = Year(CDate(ad)) & "-" & _
sMonth & "-" & _
sDay & "T" & _
sHour & ":" & _
sMinute & ":00Z"

End Function
‘ End of Function ConvertToUTCTime

 

‘*************************************************************************
‘ Name: ConvertToLocalTime ( sTime as Date )
‘ Parameters: Takes the UTC Time as 2006-11-07T18:00:000Z
‘ Returns the converted Local Time. eg., 11/07/2006 10:00:00 AM

‘ Written by : Anand Venkatachalapathy
‘*************************************************************************
Function ConvertToLocalTime(sTime)

Dim od, ad, oShell, atb, offsetMin
Dim sHour, sMinute, sMonth, sDay
Dim ResultDate

‘Convert the UTC time 2006-11-07T18:00:000Z to
‘a normal date format 11/07/2006 10:00:00
‘Note the converted date would be 24 hr format
od = CDate( _
                     Mid(sTime,9,2) & "-" & _
                     Mid(STime,6,2) & "-" & _
                     Mid(STime,1,4) & " " & _
                     Mid(STime,12,8) _
                )

‘Create Shell object to read registry
Set oShell = CreateObject("WScript.Shell")

atb = "HKEY_LOCAL_MACHINESystemCurrentControlSet" & _
"ControlTimeZoneInformationActiveTimeBias"
offsetMin = oShell.RegRead(atb) ‘Reading the registry

‘Make the Bias as negative value. This step is required,
‘because VBScript offers only DateAdd function. I wish,
‘there is DateSubtract function in VBScript.
offsetMin = -(offsetMin)

‘Convert the UTC time to Local Time,
‘Note the OffsetMin is negative value
ad = dateadd("n", offsetMin, od)

‘ If Month is single digit value, add zero
sMonth = Month(CDate(ad))
If Len(sMonth) = 1 Then
                sMonth = "0" & sMonth
End If

‘ If Day is single digit value, add zero
sDay = Day(CDate(ad))
If Len(sDay) = 1 Then
              sDay = "0" & sDay
End If

‘ If Hour is single digit value, add zero
sHour = Hour(CDate(ad))
If Len(sHour) = 1 Then
              sHour = "0" & sHour
End If

‘ If Minute is single digit value, add zero
sMinute = Minute(CDate(ad))
If Len(sMinute) = 1 Then
            sMinute = "0" & sMinute
End If

‘ Gather up all fields and convert to a Date format
ResultDate = cDate(sDay & "-" & sMonth & "-" & Year(CDate(ad)) & " " & sHour & ":" & sMinute & ":00")

‘In the above step, ResultDate is in 24 hour format.
‘So convert into 12 hr format and assign the return value
ConvertToLocalTime = FormatDateTime(ResultDate,vbShortDate) & " " & FormatDateTime(ResultDate,vbLongTime)

End Function
‘End of ConvertToLocalTime Function