InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

How to grant access to all mailboxes on a mailbox store to a special account.

Description

To grant an account access to all mailboxes on a mailbox store, the easiest way it to grant the "Receive as" and "Send as" permissions on the mailbox store. To do this, navigate to the mailbox store in the Exchange Systems manager:


The mailbox store in the Exchange Systems Manager

Next, select "Properties" on the context menu of the mailbox store and select the "Security tab".

If you want to grant the access to all mailboxes to a non-administrative account, you can simply add that account to the list and grant the "Send As" and "Receive As" permission.

To grant those permissions to an administrative account, you must perform a few additional steps, since members of the Domain Administrators have a deny on these permission


The security properties of the mailbox store

This denial is placed at the organizational level. This can be examined with ADSIEdit (adsiedit.msc):


ADSI edit displaying the security settings for the Exchange Organization

You can see, that the Domain Administrators have both, an allow as well as a deny permission. This is propagated down to the mailbox store, and prevents administrative accounts from accessing other users mailboxes. Now, you can remove these deny permission, but this is not advisable - they are there for a reason. You would end up with far too many people having these rights.

A better approach is to give only one specific account these rights. If this account is also in the Domain Administrators group and already displayed in the security tab, click "Advanced" and then "Add". Select the account the grant the "Receive As" and "Send as" permissions.

The account will be granted the permissions, because an explicit allow on a lower level overrides an inherited deny.


Posted by Henning Krause on Thursday, April 13, 2006 12:00 AM, last modified on Thursday, April 13, 2006 12:00 PM
Permalink | Post RSSRSS comment feed

A search on a calendar folder can not span more than 732 days

More Information

A SEARCH on an Exchange calendar folder with a constraint of a begin and an end date is called an expansion query. This means, that all recurring appointments are expanded, and each instance is returned in the query. (See Searching Calendar Folders with WebDAV on MSDN for more information. The article specifically targets the WebDAV  protocol, but the issue explained here applies to the ExOleDB provider as well).

An example of such a query is displayed below.

If you run this query and use values for the start and end properties where the difference between start and end is greater than 732 days, you get the following error:

Error while processing WHERE clause in the SQL statement.

Example

An example of such an expansion query might look like this:

    1 SEARCH /exchange/~username/calendar/ HTTP/1.1

    2 Host: www.example.com

    3 Content-Type: text/xml

    4 

    5 <?xmlversion="1.0"?>

    6 <g:searchrequestxmlns:g="DAV:">

    7   <g:sql>

    8     Select "urn:schemas:calendar:location", "urn:schemas:httpmail:subject",

    9     "urn:schemas:calendar:dtstart", "urn:schemas:calendar:dtend",

   10     "urn:schemas:calendar:busystatus", "urn:schemas:calendar:instancetype"

   11     FROM Scope('SHALLOW TRAVERSAL OF ""') WHERE

   12     "DAV:contentclass" = 'urn:content-classes:appointment'

   13     AND "urn:schemas:calendar:dtstart" &gt; CAST("2005-01-01T00:00:00Z" AS 'dateTime.tz')

   14     AND "urn:schemas:calendar:dtend" &lt; CAST("2006-01-01T00:00:00Z" AS 'dateTime.tz')

   15     ORDER BY "urn:schemas:calendar:dtstart" ASC

   16   </g:sql>

   17 </g:searchrequest>

Workaround

To work around this problem, do your search in multiple steps, with a time span of two years or less.

Status

This is a known limitation in the Exchange Server: Expansion queries are limited to a time span of two leap years.

Posted by Henning Krause on Thursday, April 13, 2006 12:00 AM, last modified on Thursday, April 13, 2006 12:00 PM
Permalink | Post RSSRSS comment feed

Workaround: A status of 409 - conflict is received when adding an attachment to a mail via WebDAV

More Information

The WebDAV protocol can be used to send emails. This can be done by creating the email in a mailbox folder (i.e. the Drafts folder) and moving this item to the ##DavMailSubmissionURI## folder. This is described in this MSDN article: Sending a Message (WebDAV).

Attachments can be either added to this mail using the Outlook Web Access method, or by issuing a PUT, using the address of the mail as folder: If the address of the item is

http://myserver/exchange/jdoe/drafts/new_mail.eml

the url for the PUT command would be something like http://myserver/exchange/jdoe/drafts/new_mail.eml/attachment.zip.

If you created the mail item via the PUT method, instead of a PROPPATCH, you might get a 409  - conflict error when adding attachments to the item.

Solution

A workaround seems to be to issue a PROPPATCH on the mail item itself. The PROPPATCH does not necessarily have to change the item. It's more like a touch command. After this PROPPATCH command, the PUT command for the attachment will be successful.

Status

The status of this problem is unknown.

Posted by Henning Krause on Thursday, April 13, 2006 12:00 AM, last modified on Thursday, April 13, 2006 12:00 PM
Permalink | Post RSSRSS comment feed

HowTo: Use the SUBSCRIBE Method to get Exchange store notifications

A few more words...

Generally, there are two event systems in place with Exchange: Eventsinks that run as COM+ applications on the server, or remote clients, which are notified via UDP packets. Depending on the task you want to accomplish, you should take the one or the other:

  • If you must process items in the store synchronously, you must use conventional eventsinks (OnSyncSave and OnSyncDelete).
  • If your task is performance critical, you should also use the conventional eventsinks.
  • If you are not allowed to run any code on the Exchange server, the only option you have is the WebDAV event system.

The WebDAV event system, has the following drawbacks:

  • You are only notified that a change (new item, update or delete) has occured. For example, if you monitor a folder for changes, you will get a notification when a change has occured. You won't, however, get the URL of the changed item. Traditionally, this means that you must du a SEARCH and search for all items with the DAV:getlastmodified property set to a greater value than your last search. With Exchange 2003, new promising system has been introduced, namely WebDAV replication.
  • The notification packets are sent via UDP. This means that there are difficulties with firewalls and such things. In this case, you can still use the system, but you must use the POLL method frequently to get information on changed items.

How it works

The chain of action is the following:

  1. The client sends a SUBSCRIBE method to the Exchange server and sets up the subscriptions for the specified folder

  2. The Exchange Server returns a subscription ID to the client that uniquely identifies the subscription.

  3. An item within the monitored folder is modified.

  4. The Exchange server sends an UDP packet to the client which contains a list of all triggered subscription IDs. Until the packet is acknowledged, Exchange will continue sending packets with a decreasing frequency.

  5. After the client has processed the request, it sends a POLL message with the subscription IDs of the events he has handled.

  6. When the client does not need the subscription any longer, it issues an UNSUBSCRIBE call on the folder specifying the subscription IDs he want to cancel.

Example code

The example code attached to this article is a console application that monitors a folder or element on an Exchange server for changes. Full source code is included. Note that this example uses the WebDAVLayer component.

Downloads

SubsriptionDemo.zip (31,370 Bytes)
Demo program with full source

Technorati:

Posted by Henning Krause on Thursday, July 28, 2005 12:00 AM, last modified on Monday, December 26, 2005 12:00 PM
Permalink | Post RSSRSS comment feed

HOWTO: Customize Delivery Status Notifications generated by Microsoft Exchange

More Information

As this blog points out, it is sometimes necessary to control the generation of delivery status notifications, for example if the Exchange Server is responsible for multiple domains. In this case, Exchange uses the default SMTP domain as the sender for DSNs.

The blog entry briefly describes the necessary steps but it turns out that the entire process of registering the sink is poorly documented. Additionally diffculties arose because I wanted to implement the sink with managed code.

Also Microsoft offers an example on how to implement managed transport event sinks and also includes the necessary type libraries, this library lacks the necesssary interface definitions required for the OnSyncGenerateDSN event sink.

This implementation changes the domain for the DSN to the domain of the first recipient of the original mal.

Solution

The first step was to generate a type library which contains the interface definitions for the event sink. To do this, I modified the smtpevent.idl file, which is included in the Platform SDK. The modified version is attached to this article.

I compiled the modified smtpevent.idl with the MIDL compiler and created an interop assembly with the Type library import utility (tlbimp.exe).

Unfortunately, some of the methods are incorrectly marshalled, and thus, can't be used. So, the next step is to decompile the generated assembly with ildasm.exe, correct the definition of the methods and recompile the source with the ilasm.exe compiler. The modified interop dll is also attached to this article.

The implemention of the actual interface is the most easy part of the entire process. The only method that has to be implemented is the IDSNGenerationSink.OnSyncGenerateDSN:

    1 public void OnSyncGenerateDSN(ISMTPServer pISMTPServer, IDSNSubmission pIDSNSubmission, IMailMsgProperties pIMsg, IMailMsgPropertyBag pIDSNProperties, IDSNRecipientIterator pIRecipIter)

    2 {

    3     StringBuilder sb;

    4     IMailMsgRecipientsBase recipients;

    5     string domain;

    6 

    7     Trace.WriteLine("[DSNRewriter] OnSyncGenerateDSN called");

    8     try

    9     {

   10         recipients = (IMailMsgRecipientsBase)pIMsg;

   11 

   12         sb = new StringBuilder(512);

   13         try

   14         {

   15             recipients.Item(0, (uint)_CAT_ADDRESS_TYPE.CAT_SMTP, 512, sb);

   16             domain = sb.ToString();

   17             domain = domain.Substring(domain.IndexOf("@") + 1);

   18 

   19             Trace.WriteLine("[DSNRewriter] Domain of first recipient is: " + domain);

   20 

   21             Trace.WriteLine("[DSNRewriter] Setting default domain to " + domain);

   22             pIDSNProperties.PutStringA((uint)eDSNProperties.DSNPROP_SZ_DEFAULTDOMAIN, domain);

   23             Trace.WriteLine("[DSNRewriter] Done");

   24         }

   25         catch (Exception ex)

   26         {

   27             Trace.WriteLine("[DSNRewriter] The following exceptions occured: " + ex.ToString());

   28         }

   29 

   30     }

   31     catch (Exception ex)

   32     {

   33         Trace.WriteLine("[DSNRewriter] Failed. Exception: " + ex.ToString());

   34     }

   35 }

This implementation sets the domain for the DSN to the domain of the first recipient of the original message.

After the code has been compiled to an assembly it must be registered on the Exchange server with the regasm.exe utility.

The final step is the registration of the event sink within the store. Again, Microsoft offers a script which handles registration, unregistration and enumeration of SMTP event sinks. And again, this script lacks the functionality to register DSN related event sinks. A modified version of this script is also attached to this article.

To register the event sink run the modified smtpevent.vbs with the following parameters:

    1 csript smtpevent.vbs /add 1 dsngenerationsink dsnrewriter dsnrewriter.dsnrewriter ehlo=*

This installs the event sink on the first SMTP virtual server.

To uninstall the event sink, run the following command:

    1 cscript smtpevent.vbs /remove 1 dsngenerationsink dsnrewriter

Remarks

  • If you want to modify the interop DLLs or the implementation of the event sink, you must sign them with a strong name. Use the sn.exe utility to create one. The attached binary is signed with a key that is, for obvious reasons, not included in the attached files.
  • The example implementation does not write any log files. Trace output is, however, written to the Windows debug interface. You can use DebugView from Sysinternals to view this trace output.

Downloads

SMTPInterop.zip (64,375 Bytes)
Modified interop files
Binaries.zip (17,054 Bytes)
Binary of the described implementation
DsnRewriter.zip (56,221 Bytes)
Sourcecode as Visual Studio 2003 Project
SMTPEventScript.zip (6,775 Bytes)
Modified SMTPEvent.vbs management script

Technorati:

Posted by Henning Krause on Sunday, June 26, 2005 12:00 AM, last modified on Monday, December 26, 2005 12:00 PM
Permalink | Post RSSRSS comment feed

Scripts no longer function after you run an ASP.NET page which displays performance data

Symptoms

After you view an ASP.NET webpage which displays performance counter data via the PerformanceCounter class, scripts no longer function. This includes scripts launched from a command line as well as client-side scripts in any browser window that is opened after you viewed the original page. Scripts are working again after you have stopped the Word Wide Publishing service.

Cause

A deadlock occurs because of a bug in one of the WMI providers. An event tracing is done which calls the RegisterTraceGuids API which in turn calls into one of the WMI Service hosted within the Services.exe.

<xsl:template match="xhtml:img" mode="xhtmlimage">

<xsl:param name="caption" select="@title" />

< xsl:copy >

<xsl:apply-templates select="@*" mode="xhtmlattributes" />

</ xsl:copy >

<xsl:element name="span">

<xsl:attribute name="class">clsCaption</xsl:attribute>

<xsl:value-of select="$caption" />

</ xsl:element >

</ xsl:template >

Resolution

A hotfix is available from Microsoft, at least in english and german.

To resolve this problem, contact Microsoft Product Support Services to obtain the hotfix. For a complete list of Microsoft Product Support Services phone numbers and information about support costs, visit the following Microsoft Web site: http://support.microsoft.com/default.aspx?scid=fh;[LN];CNTACTMS

Status

This problem was first corrected in Microsoft Windows XP Service Pack 2

Steps to reproduce the problem

  1. Create a new ASP.NET web application
  2. Add a label control to the page
  3. Add this code to the Page_Load event:

    using (PerformanceCounter counter = new PerformanceCounter())

    {

    counter.CategoryName = "Memory";

    counter.CounterName = "Available MBytes";

    Label1.Text = counter.NextValue().ToString();

    }

  4. Compile the application

  5. Open the webform with Internet Explorer

  6. Now, open any website which has client-side scripting

References

See KB Article 834010 for more information

Posted by Henning Krause on Tuesday, May 31, 2005 9:46 PM, last modified on Tuesday, July 26, 2011 9:57 PM
Permalink | Post RSSRSS comment feed

How to get the Global Address List programatically

More Information

The Exchange Address Lists are not stored somewhere on the Exchange Store, neither are they directly stored within Active Directory. The only thing that is stored in the Active Directory database is a LDAP search filter that matches the participants of the address list.
To get a glimpse on these filters you can use ADSI Edit, a very handy tool to examine the Active Directory database.
BUT: As with regedit, the improper use of this tool may affect the stability of your Active Directory. You have been warned! The tool can be found on the Windows CDROM under the Support Tools.


(click to enlarge)
Anyway, take a look on the image to left. Under the node
CN=All Global Address Lists,CN=Address Lists Container,CN=Contoso Ltd,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=contoso,DC=local you will find all global address lists. In most cases, however, there will only be one.
The entry CN=Default Global Address Lists has a property called purportedSearch which contains the LDAP filter for this address list.
The default value is:

    1 (& (mailnickname=*)​(|(&(objectCategory=person)​(objectClass=user)​(!(homeMDB=*))​(!(msExchHomeServerName=*)))​(&(objectCategory=person)​(objectClass=user)​(|(homeMDB=*)​(msExchHomeServerName=*)))​(&(objectCategory=person)​(objectClass=contact))​(objectCategory=group)​(objectCategory=publicFolder)​(objectCategory=msExchDynamicDistributionList)))

This is the default LDAP filter for the Global Address List used by the Recipient Update Service (RUS).

Under the node CN=All Address Lists you will find the other address lists. As with the Global Address List, every list has its own node with the property purportedSearch set to the corresponding LDAP filter.

However, it would be very slow to actually use this LDAP filter. Instead, one would do the search the other way around: Every element which is listed in the global address book has the attribute showInAddressbook. It is much faster to use the following search filter:

    1 (&(mailNickname=*)​(showInAddressBook=<dn of addressbook>))

Simply replace the <dn of addressbook> with the the distinguished name of the address book you want to get. For the global address book, this would be CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,CN=<your organization>,CN=Microsoft
Exchange,CN=Services,CN=Configuration,DC=joe,DC=com.

Depending on your programming language you can use different tools to do a LDAP search. If you are using Visual Basic or VBScript you’ll use the IADS Interfaces via the GetObject() command. In any .NET language you can use the System.DirectoryServices.DirectorySearcher class.

VBScript example

Here is an example using VBScript. Note that this example only searches the default domain of an Active Directory.

    1 optionexplicit

    2 

    3 dim oRoot

    4 dim oConnect, oCommand, rs

    5 dim strConfigurationContext

    6 dim oGAL

    7 dim strGalContainer

    8 dim strSearchRoot

    9 dim entry

   10 dim oSearchRoot

   11 

   12 'to get LDAP namespace

   13 set oRoot = GetObject("LDAP://RootDSE")

   14 strConfigurationContext = oRoot.Get("configurationNamingContext")

   15 

   16 'Open the global address list container

   17 strGalContainer = "LDAP://CN=All Global Address Lists,CN=Address Lists Container,CN=Contoso,CN=Microsoft Exchange,CN=Services, " & strConfigurationContext

   18 

   19 ' Iterate through global address lists. In this example, only the last one is used.

   20 foreach entry in GetObject(strGalContainer)

   21     set oGAL = entry

   22 next

   23 

   24 'Get the searchroot

   25 strSearchRoot = "LDAP://" & oRoot.Get("defaultNamingContext")

   26 

   27 'Using ADO to query the Active Directory for a particule user

   28 set oConnect = CreateObject("ADODB.Connection")

   29 set oCommand = CreateObject("ADODB.Command")

   30 

   31 'Open the connection

   32 oConnect.Provider = "ADsDSOObject"   

   33 oConnect.Open "Active Directory Provider"

   34 

   35 'Create a command object for this connection

   36 Set  oCommand.ActiveConnection = oConnect

   37 oCommand.CommandText = "SELECT samAccountName, givenName, sn FROM '" & strSearchRoot & "' WHERE msExchHideFromAddressLists <> true AND showInAddressBook = '" & oGal.Get("distinguishedName") & "' ORDER BY sAMAccountName ASC"

   38 

   39 'Create a recordset based on the ADO command

   40 set rs = oCommand.Execute

   41 

   42 while (not rs.EOF)

   43     wscript.echo rs.Fields("samAccountName") & " (" & rs.Fields("givenName") & " " & rs.Fields("sn") & ")"

   44     rs.MoveNext

   45 wend

References

Many thanks to Joe Richards for the hint on the showInAddressBook property.

Technorati:

Posted by Henning Krause on Sunday, February 27, 2005 12:00 AM, last modified on Monday, November 29, 2010 8:01 PM
Permalink | Post RSSRSS comment feed

OWA Options dialog from a programmers perspective

Description

Outlook Web Access can be configured to some extent by the means of a settings page. This page is opened when you click Options in the main menu. However, Microsoft lacks documentation about which properties within the store reflect these settings.
All the properties below are stored on the root folder of a mailbox.
Here is an example that gets the current timezone setting from the administrators mailbox:

    1 PROPFIND /exchange/administrator

    2 Host: www.contoso.com

    3 Translate: f

    4 

    5 <?xml version="1.0" encoding="utf-8" ?>

    6 <a:propfind xmlns:a="DAV:">

    7   <a:prop>

    8     <timezone xmlns="http://schemas.microsoft.com/exchange/" />

    9   </a:prop>

   10 </a:propfind>

The properties

All the affected properties are within the http://schemas.microsoft.com/exchange/ namespace.

(click to enlarge)

1-3: <unknown>

4: http://schemas.microsoft.com/exchange/viewrowcount; Integer type

5: http://schemas.microsoft.com/exchange/nextsel; Valid values:

    0: Open the previous item
    1: Open the next item
    2: return to the view
6: http://schemas.microsoft.com/exchange/newmailnotify; To enable, set bit 0 to 1. To disable, clear the flag
7: http://schemas.microsoft.com/exchange/newmailnotify; To enable, set bit 1 to 1. To disable, clear the flag
8: http://schemas.microsoft.com/exchange/autoaddsignature; True/False
9: http://schemas.microsoft.com/exchange/signaturetext and http://schemas.microsoft.com/exchange/signaturehtml
10: Different properties are managed with this setting:
    http://schemas.microsoft.com/exchange/composefontcolor: HTML Code of the color, i.e. #000000 for black
    http://schemas.microsoft.com/exchange/composefontname: The name of the font, i.e. Arial
    http://schemas.microsoft.com/exchange/composefontsize: The fontsize to use. Valid values are:
    http://schemas.microsoft.com/exchange/composefontflags. The value is a combination of the following bit values:

11: http://schemas.microsoft.com/exchange/previewmarkasread; Valid values:

    0: Mark item displayes in reading pane as read
    1: Mark item as read when seletion changes
    2: Do not automatically mark items as read

12: http://schemas.microsoft.com/exchange/prevreaddelaytime; Number of seconds;

13: http://schemas.microsoft.com/exchange/spellingignoreuppercase; True/False
14: http://schemas.microsoft.com/exchange/spellingignoremixeddigits; True/False
15: http://schemas.microsoft.com/exchange/spellingcheckbeforesend; True/False
16: http://schemas.microsoft.com/exchange/spellingdictionarylanguage; Valid values:

    "en-au": English (Australia)
    "en-ca": English (Canada)
    "en-gb": English (United Kingdom)
    "en-us": English (United States)
    "fr": French
    "de-p": German (post-reform)
    "de-a": German (pre-reform)
    "it": Italian
    "ko": Korean
    "es": Spanish

17: http://schemas.microsoft.com/exchange/smimeencrypt; True/False
18: http://schemas.microsoft.com/exchange/smimesign; True/False
19: <unkown>
20: http://schemas.microsoft.com/exchange/readreceipt; Valid values:

    0: Do not automatically send a response
    1: Always send a response
21: http://schemas.microsoft.com/exchange/blockexternalcontent; True/False
22: http://schemas.microsoft.com/exchange/themeid; Valid values:
    0: Default (blue)
    1: Olive Green 
    2: Silver
    3: Burgundy
    4: Dark Blue

23: http://schemas.microsoft.com/exchange/shortdateformat; Valid values:
    "M/d/yyyy": 1/1/2005 - 12/31/2005
    "M/d/yy": 1/1/05 - 12/31/05
    "MM/dd/yy" 01/01/05 - 12/31/05
    "MM/dd/yyyy" 01/01/2005 - 12/31/2005
    "yy/MM/dd" 05/01/01 - 05/12/31
    "yyyy-MM-dd" 2005-01-01 - 2005-12-31
    "dd-MMM-yy" 01-Jan-05 - 31-Dec-05

24: http://schemas.microsoft.com/exchange/longdateformat; Valid values:

    "dddd, MMMM dd, yyyy": Saturday, January 01, 2005 - Saturday, December 31, 2005
    "MMMM dd, yyyy": January 01, 2005 - December 31, 2005
    "dddd, dd MMMM, yyyy": Saturday, 01 January, 2005 - Saturday, 31 December, 2005
    "dd MMMM, yyyy": 01 January, 2005 - 31 December, 2005

25: http://schemas.microsoft.com/exchange/timeformat; Valid values:
    "h:mm tt": 1:01 AM - 11:59 PM
    "hh:mm tt": 01:01 AM - 11:59 PM
    "H:mm": 1:01 - 23:59
    "HH:mm": 01:01 - 23:59

26: http://schemas.microsoft.com/exchange/timezone (See appendix A for valid values)
27: http://schemas.microsoft.com/exchange/weekstartday; Valid Values:
    "0": Sunday
    "1": Monday
    "2": Tuesday
    "3": Wednesday
    "4": Thursday
    "5": Friday
    "6": Saturday

28: http://schemas.microsoft.com/exchange/workdaystarttime; Time offset in minutes from midnight: 30 equals 0:30, 720 equals 12 PM
29: http://schemas.microsoft.com/exchange/workdayendtime; Values have the same meaning as in field 30.
30: http://schemas.microsoft.com/exchange/firstweekofyear; Valid Values are:

    "0": Do not display week numbers
    "1": Starts on Jan 1
    "2": First 4-day week
    "3": First full week
31: http://schemas.microsoft.com/exchange/enablereminders; To enable, set bit 2 to 1. To disable, clear the bit.
32: http://schemas.microsoft.com/exchange/enablereminders; To enable, set bit 3 to 1. To disable, clear the bit.
33: http://schemas.microsoft.com/exchange/enablereminders; To enable, set bit 0 to 1. To disable, clear the bit.
34: http://schemas.microsoft.com/exchange/reminderinterval; Interval in seconds.
35: http://schemas.microsoft.com/exchange/anrcontactsfirst; Valid values:

    "0": Global Address Book
    "1": Contacts

Appendix A – Timezone settings

Valid values for the http://schemas.microsoft.com/exchange/timezone property are the following:

  • "Dateline Standard Time": (GMT-12:00) Eniwetok, Kwajalein
  • "Samoa Standard Time": (GMT-11:00) Midway Island, Samoa
  • "Hawaiian Standard Time": (GMT-10:00) Hawaii
  • "Alaskan Standard Time": (GMT-09:00) Alaska
  • "Pacific Standard Time": (GMT-08:00) Pacific Time (US & Canada); Tijuana
  • "Mexico Standard Time 2": (GMT-07:00) Chihuahua, La Paz, Mazatlan
  • "US Mountain Standard Time": (GMT-07:00) Arizona
  • "Mountain Standard Time": (GMT-07:00) Mountain Time (US & Canada)
  • "Central America Standard Time": (GMT-06:00) Central America
  • "Central Standard Time": (GMT-06:00) Central Time (US & Canada)
  • "Mexico Standard Time": (GMT-06:00) Mexico City
  • "Canada Central Standard Time": (GMT-06:00) Saskatchewan
  • "SA Pacific Standard Time": (GMT-05:00) Bogota, Lima, Quito
  • "Eastern Standard Time": (GMT-05:00) Eastern Time (US & Canada)
  • "US Eastern Standard Time": (GMT-05:00) Indiana (East)
  • "Atlantic Standard Time": (GMT-04:00) Atlantic Time (Canada)
  • "SA Western Standard Time": (GMT-04:00) Caracas, La Paz
  • "Pacific SA Standard Time": (GMT-04:00) Santiago
  • "Newfoundland Standard Time": (GMT-03:30) Newfoundland
  • "E. South America Standard Time": (GMT-03:00) Brasilia
  • "Greenland Standard Time": (GMT-03:00) Greenland
  • "SA Eastern Standard Time": (GMT-03:00) Buenos Aires, Georgetown
  • "Mid-Atlantic Standard Time": (GMT-02:00) Mid-Atlantic
  • "Azores Standard Time": (GMT-01:00) Azores
  • "Cape Verde Standard Time": (GMT-01:00) Cape Verde Is.
  • "Greenwich Standard Time": (GMT) Casablanca, Monrovia
  • "GMT Standard Time": (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London
  • "W. Europe Standard Time": (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
  • "Central Europe Standard Time": (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
  • "Romance Standard Time": (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
  • "Central European Standard Time": (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
  • "W. Central Africa Standard Time": (GMT+01:00) West Central Africa
  • "GTB Standard Time": (GMT+02:00) Athens, Istanbul, Minsk
  • "E. Europe Standard Time": (GMT+02:00) Bucharest
  • "Egypt Standard Time": (GMT+02:00) Cairo
  • "South Africa Standard Time": (GMT+02:00) Harare, Pretoria
  • "FLE Standard Time": (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
  • "Israel Standard Time": (GMT+02:00) Jerusalem
  • "Arabic Standard Time": (GMT+03:00) Baghdad
  • "Arab Standard Time": (GMT+03:00) Kuwait, Riyadh
  • "Russian Standard Time": (GMT+03:00) Moscow, St. Petersburg, Volgograd
  • "E. Africa Standard Time": (GMT+03:00) Nairobi
  • "Iran Standard Time": (GMT+03:30) Tehran
  • "Arabian Standard Time": (GMT+04:00) Abu Dhabi, Muscat
  • "Caucasus Standard Time": (GMT+04:00) Baku, Tbilisi, Yerevan
  • "Afghanistan Standard Time": (GMT+04:30) Kabul
  • "Ekaterinburg Standard Time": (GMT+05:00) Ekaterinburg
  • "West Asia Standard Time": (GMT+05:00) Islamabad, Karachi, Tashkent
  • "India Standard Time": (GMT+05:30) Kolkata, Chennai, Mumbai, New Delhi
  • "Nepal Standard Time": (GMT+05:45) Kathmandu
  • "N. Central Asia Standard Time": (GMT+06:00) Almaty, Novosibirsk
  • "Central Asia Standard Time": (GMT+06:00) Astana, Dhaka
  • "Sri Lanka Standard Time": (GMT+06:00) Sri Jayawardenepura
  • "Myanmar Standard Time": (GMT+06:30) Rangoon
  • "SE Asia Standard Time": (GMT+07:00) Bangkok, Hanoi, Jakarta
  • "North Asia Standard Time": (GMT+07:00) Krasnoyarsk
  • "China Standard Time": (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi
  • "North Asia East Standard Time": (GMT+08:00) Irkutsk, Ulaan Bataar
  • "W. Australia Standard Time": (GMT+08:00) Perth
  • "Singapore Standard Time": (GMT+08:00) Kuala Lumpur, Singapore
  • "Taipei Standard Time": (GMT+08:00) Taipei
  • "Tokyo Standard Time": (GMT+09:00) Osaka, Sapporo, Tokyo
  • "Korea Standard Time": (GMT+09:00) Seoul
  • "Yakutsk Standard Time": (GMT+09:00) Yakutsk
  • "Cen. Australia Standard Time": (GMT+09:30) Adelaide
  • "AUS Central Standard Time": (GMT+09:30) Darwin
  • "E. Australia Standard Time": (GMT+10:00) Brisbane
  • "AUS Eastern Standard Time": (GMT+10:00) Canberra, Melbourne, Sydney
  • "West Pacific Standard Time": (GMT+10:00) Guam, Port Moresby
  • "Tasmania Standard Time": (GMT+10:00) Hobart
  • "Vladivostok Standard Time": (GMT+10:00) Vladivostok
  • "Central Pacific Standard Time": (GMT+11:00) Magadan, Solomon Is., New Caledonia
  • "New Zealand Standard Time": (GMT+12:00) Auckland, Wellington
  • "Fiji Standard Time": (GMT+12:00) Fiji, Kamchatka, Marshall Is.
  • "Tonga Standard Time": (GMT+13:00) Nuku'alofa

Technorati:

Posted by Henning Krause on Wednesday, February 16, 2005 12:00 AM, last modified on Monday, December 26, 2005 12:00 PM
Permalink | Post RSSRSS comment feed

Recover deleted elements from an Exchange 2000/2003 folder

More Information

Outlook and Exchange know two ways how to delete a file: A soft-delete, which is performed when you simply press delete on an item. The affected item is then moved to the recycle-bin. The other method is called hard-deletion. These items are kept in the store for a configurable duration, typically 30 days.
To check if there are any deleted items or folders within a given public or private folder, you can read the values of these properties:

  • PR_DELETED_MSG_COUNT
    This property contains the number of deleted messages in the folder
  • PR_DELETED_FOLDER_COUNT
    This property contains the number of deleted folders in the folder

To enumerate the deleted items, a SEARCH command is issued on the folder:

    1 SEARCH /public/folder / HTTP/1.1

    2 Host: www.contoso.com

    3 Depth: 0

    4 Content-type: text/xml;

    5 Content-Length: XXXXX

    6 

    7 <?xml version="1.0"?>

    8 <a:searchrequest xmlns:a="DAV:">

    9   <a:sql>

   10     SELECT “DAV:displayname", "DAV:contentclass", "DAV:getcontentlength", "DAV:href", "DAV:isfolder" FROM SCOPE('SOFTDELETED TRAVERSAL OF "http://www.contoso.com/public/folder"')

   11   </a:sql>

   12 </a:searchrequest>

To recover one or more of these items, a BCOPY command is issued:

    1 BCOPY /public/container/ HTTP/1.1

    2 Host: www.contoso.com

    3 Depth: 0

    4 Content-type: text/xml;

    5 Content-Length: XXXXX

    6 

    7 <?xml version="1.0"?>

    8 <a:copy xmlns:a="DAV:">

    9   <a:target>

   10     <a:href>http://www.contoso.com/public/folder-softdeleted-/-FlatUrlSpace-/93c5676ddb37ee4690b4756339818e46-6d89</a:href>

   11     <a:dest>http://www.contoso.com/public/folder/recovereditem</a:dest>

   12   </a:target>

   13 </a:copy>

After the item has been recovered, the deleted element can safely be removed from the store via the BDELETE command:

    1 BDELETE /public/container/ HTTP/1.1

    2 Host: www.contoso.com

    3 Depth: 0

    4 Content-type: text/xml;

    5 Content-Length: XXXXX

    6 

    7 <?xml version="1.0" encoding="UTF-8"?>

    8 <a:delete xmlns:a="DAV:">

    9   <a:target>

   10     <a:href>http://www.contoso.com/public/folder/-softdeleted-/-FlatUrlSpace-/93c5676ddb37ee4690b4756339818e46-6d89</a:href>

   11   </a:target>

   12 </a:delete>


Technorati:

Posted by Henning Krause on Monday, February 7, 2005 12:00 AM, last modified on Monday, December 26, 2005 12:00 PM
Permalink | Post RSSRSS comment feed

Retrieve the size of a Microsoft Exchange 2000/2003 public folder

More Information

The size of all messages in a folder is stored on each folder object. This information can be extracted from several fields, for example the http://schemas.microsoft.com/exchange/foldersize property. But this property seems to be mapped to the MAPI property PR_MESSAGE_SIZE. The drawback with this property is, that it is limited to 32 bit, so it works only for folders containing not more than 4 GB.
Luckily, this property is also available as a 64 bit value, stored in the MAPI property PR_MESSAGE_SIZE_EXTENDED

Example

The following Visual Basic script shows how to use the above mentioned property:

    1 option explicit

    2 dim xmlhttp

    3 dim xmldoc

    4 dim strrequest

    5 dim ie

    6 

    7 strrequest = "<?xml version=""1.0"" ?><D:propfind xmlns:D=""DAV:"" xmlns:E=""http://schemas.microsoft.com/mapi/proptag/""><D:prop><E:x0e080014 /></D:prop></D:propfind>"

    8 Set xmlhttp = CreateObject("msxml2.xmlhttp")

    9 Set xmldoc = CreateObject("Msxml2.DOMDocument")

   10 xmldoc.loadXML(strrequest)

   11 

   12 wscript.echo "Connecting to " & wscript.Arguments(0) & "..."

   13 xmlhttp.Open "PROPFIND", wscript.Arguments(0), false, wscript.Arguments(1), wscript.arguments(2)

   14 xmlhttp.setRequestHeader "Content-type:", "text/xml"

   15 xmlhttp.setRequestHeader "Depth", "0"

   16 xmlhttp.send strrequest

   17 wscript.echo "Return status: " & xmlhttp.status & " " & xmlhttp.statustext

   18 

   19 set xmldoc = xmlhttp.responseXml

   20 if (xmlhttp.status = 207) then

   21     xmldoc.setProperty "SelectionNamespaces", "xmlns:ex='http://schemas.microsoft.com/mapi/proptag/'"

   22     wscript.echo "Size of folder: " & xmldoc.selectSingleNode("//ex:x0e080014").text & " Bytes"

   23 end if

To use this script, simply copy it into a text file and save it as foldersize.vbs file. Then open a command prompt and type the following:

    1 cscript foldersize.vbs http://myserver/public/myfolder username password

Where myserver is the exchange server that contains the folder you want to check and myfolder ist the name of the folder.

More Information

This script can also be run against a folder withing a mailbox of a user. To do this, open a command prompt and type the following:

    1 cscript foldersize.vbs http://myserver/exchange/alias/myfolder username password

Where alias is the alias of the user's mailbox to check.

Technorati:

Posted by Henning Krause on Friday, December 31, 2004 12:00 AM, last modified on Monday, November 29, 2010 6:42 PM
Permalink | Post RSSRSS comment feed