Skip to main content

Creating a RSS feed of all new items in all public folders over the past 24 hours

I’m having a bit of a RSS feed week this week here’s another interesting one. A while ago I created this RSS event sink for a public folder that would generate a feed whenever a new item was posted in a Public Folder. This is useful but over a large number of folders having a separate feed for every folder is a pain and usually it’s a matter of getting across the new information that’s been added to a possible large number of folders that’s important. So what I’ve come up with is a script that will scan though every folder in the public folder tree on a server and then create a feed that has a post for each new item in each public folder within the whole public folder tree (where theres are replica available). The one problem with this script is it doesn’t really respect permissions so if you have folders that have information in them that is supposed to be restricted you might want to include some if statements so these folders are skipped.


This script use WebDAV to query each public folder it’s loosely based like a few of my scripts lately on the code from the mailbox size KB . Each folder in the public folder tree is recursively queried for items that where created in the last 24 hours and a RSS file is then built using the XMLDom com object. That script use the Admin Virtual root which means it can run using Delegated Exchange Administration rights and won’t be hampered by public folder permission. An ADSI query is used to find out what the default SMTP domain is in the default recipient policy. By default the script isn’t using SSL which may mean you need to adjust the following line if you are using SSL on the ExAdmin Directory.


falias = "http://" & servername & "/exadmin/admin/" & dpDefaultpolicy & "/Public Folders/"

To customize the location where the RSS file is created modify the 2 line

feedfile = ""c:\temp\feedpubnew.xml"

The script itself takes one commandline parameter which is the servername of the server you want to run it against so to run this script you need something like

cscript pubrssnew.vbs servername

I’ve put a download copy of this script here the script itself looks like

Servername = wscript.arguments(0)
feedfile = "feedpubnew.xml"
set shell = createobject("wscript.shell")
strValueName = "HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias"
minTimeOffset = shell.regread(strValueName)
toffset = datediff("h",DateAdd("n", minTimeOffset, now()),now())
dtListFrom = DateAdd("n", minTimeOffset, now())
gmttime = dateadd("h",-toffset,now())
dateto = isodateit(gmttime)
datefrom = isodateit(DateAdd("d",-1,gmttime))
set objdom = CreateObject("MICROSOFT.XMLDOM")
set req = createobject("microsoft.xmlhttp")
rem Create Root RSS feed
Set objField = objDom.createElement("rss")
Set objattID = objDom.createAttribute("version")
objattID.Text = "2.0"
objField.setAttributeNode objattID
objDom.appendChild objField
Set objField1 = objDom.createElement("channel")
objfield.appendChild objField1
Set objField3 = objDom.createElement("link")
objfield3.text = "http://" & Servername & "/public"
objfield1.appendChild objField3
Set objField4 = objDom.createElement("title")
objfield4.text = "Public Folder Feed"
objfield1.appendChild objField4
Set objField5 = objDom.createElement("description")
objfield5.text = "New Public Folder items in the last 24 Hours"
objfield1.appendChild objField5
Set objField6 = objDom.createElement("language")
objfield6.text = "en-us"
objfield1.appendChild objField6
Set objField7 = objDom.createElement("lastBuildDate")
objfield7.text = WeekdayName(weekday(now),3) & ", " & day(now()) & " " &
Monthname(month(now()),3) & " " & year(now()) & " " & formatdatetime(now(),4) &
":00 GMT"
objfield1.appendChild objField7

set com = createobject("ADODB.Command")
set conn = createobject("ADODB.Connection")
Set iAdRootDSE = GetObject("LDAP://RootDSE")
strNameingContext = iAdRootDSE.Get("configurationNamingContext")
strDefaultNamingContext = iAdRootDSE.Get("defaultNamingContext")
Conn.Provider = "ADsDSOObject"
Conn.Open "ADs Provider"
polQuery = "<LDAP://" & strNameingContext &
">;(&(objectCategory=msExchRecipientPolicy)(cn=Default
Policy));distinguishedName,gatewayProxy;subtree"
svcQuery = "<LDAP://" & strNameingContext &
">;(&(objectCategory=msExchExchangeServer)(cn=" & Servername &
"));cn,name,legacyExchangeDN;subtree"
Com.ActiveConnection = Conn
Com.CommandText = polQuery
Set plRs = Com.Execute
while not plRs.eof
for each adrobj in plrs.fields("gatewayProxy").value
if instr(adrobj,"SMTP:") then dpDefaultpolicy =
right(adrobj,(len(adrobj)-instr(adrobj,"@")))
next
plrs.movenext
wend
wscript.echo dpDefaultpolicy
falias = "http://" & servername & "/exadmin/admin/" & dpDefaultpolicy & "/Public
Folders/"
RecurseFolder(falias)
wscript.echo falias
set conn = nothing
set com = nothing
set wfile = nothing
set fso = Nothing
Set objPI = objDom.createProcessingInstruction("xml", "version='1.0'")
objDom.insertBefore objPI, objDom.childNodes(0)
objdom.save("c:\temp\" & feedfile)

Public Sub RecurseFolder(sUrl)

req.open "SEARCH", sUrl, False, "", ""
sQuery = "<?xml version=""1.0""?>"
sQuery = sQuery & "<g:searchrequest xmlns:g=""DAV:"">"
sQuery = sQuery & "<g:sql>SELECT ""http://schemas.microsoft.com/"
sQuery = sQuery & "mapi/proptag/x0e080003"", ""DAV:hassubs"" FROM SCOPE "
sQuery = sQuery & "('SHALLOW TRAVERSAL OF """ & sUrl & """') "
sQuery = sQuery & "WHERE ""DAV:isfolder"" = true and ""DAV:ishidden"" = false
and ""http://schemas.microsoft.com/mapi/proptag/x36010003"" = 1"
sQuery = sQuery & "</g:sql>"
sQuery = sQuery & "</g:searchrequest>"
req.setRequestHeader "Content-Type", "text/xml"
req.setRequestHeader "Translate", "f"
req.setRequestHeader "Depth", "0"
req.setRequestHeader "Content-Length", "" & Len(sQuery)
req.send sQuery
Set oXMLDoc = req.responseXML
Set oXMLSizeNodes = oXMLDoc.getElementsByTagName("d:x0e080003")
Set oXMLHREFNodes = oXMLDoc.getElementsByTagName("a:href")
Set oXMLHasSubsNodes = oXMLDoc.getElementsByTagName("a:hassubs")
For i = 0 to oXMLSizeNodes.length - 1
call procfolder(oXMLHREFNodes.Item(i).nodeTypedValue,sUrl)
wscript.echo oXMLHREFNodes.Item(i).nodeTypedValue
If oXMLHasSubsNodes.Item(i).nodeTypedValue = True Then
call RecurseFolder(oXMLHREFNodes.Item(i).nodeTypedValue)
End If
Next
End Sub

sub procfolder(strURL,pfname)
wscript.echo strURL
ReDim resarray(1,6)
strQuery = "<?xml version=""1.0""?><D:searchrequest xmlns:D = ""DAV:""
xmlns:b=""urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"">"
strQuery = strQuery & "<D:sql>SELECT ""DAV:displayname"",
""urn:schemas:httpmail:subject"", "
strQuery = strQuery & """DAV:creationdate"", ""DAV:getcontentlength"", "
strQuery = strQuery & """urn:schemas:httpmail:fromemail"",
""urn:schemas:httpmail:to"""
strQuery = strQuery & " FROM scope('shallow traversal of """
strQuery = strQuery & strURL & """') Where ""DAV:ishidden"" = False AND
""DAV:isfolder"" = False AND "
'strQuery = strQuery & """urn:schemas:httpmail:datereceived"" &lt; CAST(""" &
dateto & """ as 'dateTime') AND "
strQuery = strQuery & """urn:schemas:httpmail:datereceived"" &gt; CAST(""" &
datefrom & """ as 'dateTime')</D:sql></D:searchrequest>"
req.open "SEARCH", strURL, false
req.setrequestheader "Content-Type", "text/xml"
req.setRequestHeader "Translate","f"
req.send strQuery
If req.status >= 500 Then
ElseIf req.status = 207 Then
set oResponseDoc = req.responseXML
set oNodeList = oResponseDoc.getElementsByTagName("a:displayname")
set oNodeList1 = oResponseDoc.getElementsByTagName("a:href")
set oSize = oResponseDoc.getElementsByTagName("a:getcontentlength")
set odatereceived = oResponseDoc.getElementsByTagName("a:creationdate")
set fEmail = oResponseDoc.getElementsByTagName("d:fromemail")
set TEmail = oResponseDoc.getElementsByTagName("d:to")
For i = 0 To (oNodeList.length -1)
set oNode = oNodeList.nextNode
set oNode1 = oNodeList1.nextNode
set oNode2 = oSize.nextNode
set oNode3 = odatereceived.nextNode
set oNode4 = fEmail.nextNode
set oNode5 = TEmail.nextNode
wscript.echo oNode3.text
export = 0
If InStr(LCase(oNode4.text),LCase(domaintosearch))Then
export = 1
End If
if InStr(LCase(oNode5.text),LCase(domaintosearch))Then
export = 1
End If
If export = 1 Then
Call AddtoFeed(oNode1.text,oNode.text)
End if
Next
Else
End If

end sub

sub AddtoFeed(exporthref,subject)

xmlreqtxt = "<?xml version='1.0'?><a:propfind xmlns:a='DAV:'
xmlns:m='urn:schemas:httpmail:'
xmlns:mapi='http://schemas.microsoft.com/mapi/proptag/'>" _
&
"<a:prop><mapi:x6707001E/></a:prop><a:prop><a:displayname/></a:prop><a:prop><m:subject/></a:prop><a:prop><m:fromemail/>"_
&
"</a:prop><a:prop><m:htmldescription/></a:prop><a:prop><m:datereceived/></a:prop></a:propfind>"
req.open "PROPFIND", exporthref, false, "", ""
req.setRequestHeader "Content-Type", "text/xml; charset=""UTF-8"""
req.setRequestHeader "Depth", "0"
req.setRequestHeader "Translate", "f"
req.send xmlreqtxt
set oResponseDoc1 = req.responseXML
set pfParentFolder = oResponseDoc1.getElementsByTagName("d:x6707001E")
set feFromEmail = oResponseDoc1.getElementsByTagName("e:fromemail")
set sjSubject = oResponseDoc1.getElementsByTagName("e:subject")
set drDateRecieved = oResponseDoc1.getElementsByTagName("e:datereceived")
set bdHtmlBody = oResponseDoc1.getElementsByTagName("e:htmldescription")
set dnDisplayName = oResponseDoc1.getElementsByTagName("a:displayname")

For i = 0 To (sjSubject.length -1)
set pfnode = sjSubject.nextNode
set pfnode1 = feFromEmail.nextNode
set pfnode2 = drDateRecieved.nextNode
set pfnode3 = bdHtmlBody.nextNode
Set pfnode4 = pfParentFolder.nextNode
Set pfnode5 = dnDisplayName.nextNode
wscript.echo pfnode.text
wscript.echo pfnode1.text
wscript.echo pfnode2.text
rem wscript.echo pfnode3.text
wscript.echo pfnode4.text
wscript.echo pfnode5.text
wscript.echo left(Replace(pfnode2.text,"T"," "),19)
Set objField2 = objDom.createElement("item")
objfield1.appendChild objField2
Set objField8 = objDom.createElement("guid")
Set objattID8 = objDom.createAttribute("isPermaLink")
objattID8.Text = "false"
objField8.setAttributeNode objattID8
objfield8.text = exporthref
objfield2.appendChild objField8
Set objField9 = objDom.createElement("title")
objfield9.text = pfnode.text
if objfield9.text = "" then objfield9.text = "Blank"
objfield2.appendChild objField9
Set objField10 = objDom.createElement("link")
objfield10.text = "http://" & Servername & "/public" & pfnode4.text
objfield2.appendChild objField10
Set objField11 = objDom.createElement("description")
objfield11.text = pfnode3.text
if objfield11.text = "" then objfield11.text = "Blank"
objfield2.appendChild objField11
Set objField12 = objDom.createElement("author")
objfield12.text = pfnode1.text
objfield2.appendChild objField12
Set objField13 = objDom.createElement("pubDate")
objfield13.text = WeekdayName(weekday(left(Replace(pfnode2.text,"T"," "),19)),3)
& ", " & day(left(Replace(pfnode2.text,"T"," "),19)) & " " &
Monthname(month(left(Replace(pfnode2.text,"T"," "),19)),3) & " " &
year(left(Replace(pfnode2.text,"T"," "),19)) & " " &
formatdatetime(left(Replace(pfnode2.text,"T"," "),19),4) & ":00 GMT"
objfield2.appendChild objField13
Set objField14 = objDom.createElement("category")
objfield14.text = unescape(Replace(LCase(pfnode4.text),LCase(pfnode5.text),""))
objfield2.appendChild objField14
set objfield2 = nothing
set objfield8 = nothing
set objfield9 = nothing
set objfield10 = nothing
set objfield11 = nothing
set objfield12 = nothing
set objfield13 = nothing
next

End Sub


function isodateit(datetocon)
strDateTime = year(datetocon) & "-"
if (Month(datetocon) < 10) then strDateTime = strDateTime & "0"
strDateTime = strDateTime & Month(datetocon) & "-"
if (Day(datetocon) < 10) then strDateTime = strDateTime & "0"
strDateTime = strDateTime & Day(datetocon) & "T" & formatdatetime(datetocon,4)
&":00Z"
isodateit = strDateTime
end function

Popular posts from this blog

Downloading a shared file from Onedrive for business using Powershell

I thought I'd quickly share this script I came up with to download a file that was shared using One Drive for Business (which is SharePoint under the covers) with Powershell. The following script takes a OneDrive for business URL which would look like https://mydom-my.sharepoint.com/personal/gscales_domain_com/Documents/Email%20attachments/filename.txt This script is pretty simple it uses the SharePoint CSOM (Client side object Model) which it loads in the first line. It uses the URI object to separate the host and relative URL which the CSOM requires and also the SharePointOnlineCredentials object to handle the Office365 SharePoint online authentication. The following script is a function that take the OneDrive URL, Credentials for Office365 and path you want to download the file to and downloads the file. eg to run the script you would use something like ./spdownload.ps1 ' https://mydom-my.sharepoint.com/personal/gscales_domain_com/Documents/Email%20attachments/filena

Export calendar Items to a CSV file using EWS and Powershell

Somebody asked about this last week and while I have a lot of EWS scripts that do access the Calendar I didn't have a simple example that just exported a list of the Calendar events with relevant information to a CSV file so here it is. I've talked on this one before in this howto  but when you query the calendar folder using EWS you need to use a CalendarView which will expand any recurring appointments in a calendar. There are some limits when you use a calendarview in that you can only return a maximum of 2 years of appointments at a time and paging will limit the max number of items to 1000 per call. So if you have a calendar with a very large number of appointments you need to break your query into small date time blocks. In this example script I'm just grabbing the next 7 days of appointments if you want to query a longer period you need to adjust the following lines (keeping in mind what I just mentioned) #Define Date to Query $StartDate = (Get-Date) $EndDate

How to test SMTP using Opportunistic TLS with Powershell and grab the public certificate a SMTP server is using

Most email services these day employ Opportunistic TLS when trying to send Messages which means that wherever possible the Messages will be encrypted rather then the plain text legacy of SMTP.  This method was defined in RFC 3207 "SMTP Service Extension for Secure SMTP over Transport Layer Security" and  there's a quite a good explanation of Opportunistic TLS on Wikipedia  https://en.wikipedia.org/wiki/Opportunistic_TLS .  This is used for both Server to Server (eg MTA to MTA) and Client to server (Eg a Message client like Outlook which acts as a MSA) the later being generally Authenticated. Basically it allows you to have a normal plain text SMTP conversation that is then upgraded to TLS using the STARTTLS verb. Not all servers will support this verb so if its not supported then a message is just sent as Plain text. TLS relies on PKI certificates and the administrative issue s that come around certificate management like expired certificates which is why I wrote th
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.