Restrict Mailing Public Groups Part 1

I had to put together some code for my company and I thought I would share it here. My requirements were to restrict certain people (approximately 300 out of many thousands) from mailing any of the groups (approximately 1300) in the public NAB of our store environment.

I would first like to recognize Thomas J McArthur who put together some awesome code to address this need, and it is this same code that I started with as a base. It can be found here.

http://www-10.lotus.com/ldd/46dom.nsf/55c38d716d632d9b8525689b005ba1c0/7e2a6f2ff45b049685256d95005577b5?OpenDocument

One of the major shortcomings with this code though, was that it only worked if a user was online or, if they were offline, if they in fact had a local replica of their public NAB and you knew what that file name was. If you could not access the “allow” group for some reason you cannot send the message. In his environment, he seemed to be able to count on knowing that his users could access at least a local replica of their public NAB. I could not count on that constant here. My users are bound to have either no local replica of local replicas named something along the lines of

“ahu32r523-ausdfas4fdashid10t.nsf”

Also I found that it only worked if you were mailing only one of the restricted groups. If you were mailing more than one or if the group name was buried in the midst of a whole bunch of other recipients, it did not pick it up. Also was the problem for me that the restricted groups were hard-coded in the formula itself. This was not practical for me since I had over 1300 restricted groups. Lastly was the problem for me that his code found a user in a group and then allowed them to send the mail. I had to reverse that because only 300 people were to be restricted. So my logic had to change to state that if you find them in the group, restrict them.

So, a very long-story-short and after many, many, many (did I say many?) changes and evolutions of my code, I decided to store all of the restriction documents in a user’s mail database. This addressed the online/offline issue. I did this by creating a db on a server that contained a simple form (form name = “fkeylist”) with only a few fields. One contained the doc name that I keyed on in the first column of my view (for @dblookups) and the other contained the members.

I then gave the business owner access to change those documents as they needed. In this db I created three docs. The first containing half of the restricted groups, the second containing the other half, and the third containing all the restricted users.

I then wrote some code in lotus script and put it in the post open event of our mail db template to copy the restriction docs into a user’s mail file – if they were in the restriction group. Additionally, I had to add a view called “($Keyword Fields)” in the mail db template so that my @dblookups in the formula code would have the proper view to do a lookup against. I also changed my “all documents” and “drafts” view selection to not contain docs with the form “fkeylist.” This prevented users from seeing the docs and deleting them mistakenly or otherwise. Here is this code:

Sub Postopen(Source As Notesuidatabase)

' written by Bryan Horton

Function AbbName(canonicalname As Variant) As String

’ Abbreviate a canonical name.

Dim nname As NotesName

Dim session As New NotesSession

Set nname = session.CreateName(canonicalname)

If nname.IsHierarchical Then

	AbbName = nname.Abbreviated

Else

	AbbName = canonicalname

End If

End Function

On Error Goto errhand



' declare some stuff



Dim s As New notessession

Dim localyn As String

Dim usn As String

Dim db As notesdatabase

Set db = s.currentdatabase

Dim view As notesview

Dim ldoc As notesdocument

Dim lndoc As notesdocument

Dim doc As notesdocument

Dim doc1 As NotesDocument

Dim doc2 As notesdocument

Dim kwdb As New notesdatabase("whatsmyservername","Keydb.nsf")

Dim kview As notesview

Dim keylist As Variant

Dim newdoc As New NotesDocument( db )

Dim newdoc1 As New NotesDocument( db )

Dim newdoc2 As New NotesDocument( db )

Dim kl As Variant

Dim fn As Variant

%REM check to make sure user is from ACME, if not script ends

%END REM

usn = s.UserName

If Not usn Like "*OU=ACME*" Then

	Exit Sub

End If

%REM check to see if user is in local db. If so I assume no connection to the network and end the script

%END REM

localyn = db.server

If localyn = "" Then

	Exit Sub

End If

%REM get handles on needed docs in keyword db and on first restriction doc in mail file if it exists.

%END REM

Set view = db.getview("($Keyword Fields)")	

Set ldoc = view.getfirstdocument	

Set kview = kwdb.getview("Keyword Fields")	

Set doc = kview.GetDocumentByKey("M&MGroupsA-H")

Set doc1 = kview.GetDocumentByKey("M&MGroupsM-T")	

Set doc2 = kview.GetDocumentByKey("M&MGroupsBlockList")

%REM Check to see if user is in restriction group on server and to see whether or not they have any restriction docs

 in their mail file. If they are not in the group on the server and they have no restriction docs in their mail file

 the script ends. If they are not in the group but they do have local restriction docs, the docs are deleted and then the script ends.

This covers those people who were once in the restriction group and then removed and should no longer be restricted.

%END REM

If Not (doc2 Is Nothing) Then

	keylist = doc2.KeyList

	If Isnull(Arraygetindex(  keylist, AbbName(usn)  )) And ldoc  Is Nothing Then

		Exit Sub

	Elseif Isnull(Arraygetindex(  keylist, AbbName(usn)  )) And Not ldoc  Is Nothing Then

		While Not(ldoc Is Nothing)

			Set lndoc = view.getnextdocument(ldoc)

			Call ldoc.remove(True)

			Set ldoc = lndoc

		Wend

		Exit Sub

	End If

End If

%REM check to make sure I have handle on all three docs needed for mail restriction formula (in the send action) to work properly.

If I have the handles, I delete old docs in user's mail file and then create new documents containing the field values out of the source db. This insures users have the most up-to-date version of the restricted docs.

 and no, (copytodb) method does not work as it retains the same unid and screws up replication (because of deletion stubs).

%END REM

If Not (doc Is Nothing) And Not (doc1 Is Nothing) And Not (doc2 Is Nothing) Then

	

	While Not(ldoc Is Nothing)

		Set lndoc = view.getnextdocument(ldoc)

		Call ldoc.remove(True)

		Set ldoc = lndoc

	Wend

	

	kl = doc.KeyList

	fn = doc.FieldName

	

	newdoc.KeyList = kl

	newdoc.FieldName = fn

	newdoc.Form = "fkeylist"

	Call newdoc.save(True, False)

	

	kl = doc1.KeyList

	fn = doc1.FieldName

	

	newdoc1.KeyList = kl

	newdoc1.FieldName = fn

	newdoc1.Form = "fkeylist"

	Call newdoc1.save(True, False)

	

	kl = doc2.KeyList

	fn = doc2.FieldName

	

	newdoc2.KeyList = kl

	newdoc2.FieldName = fn

	newdoc2.Form = "fkeylist"

	Call newdoc2.save(True, False)

	

	

End If

errhand:

If Erl() <> "0" Then

	Print Err & Error & " on " & Erl

	Resume Next

End If

End Sub

See Part Two here:

http://www-10.lotus.com/ldd/nd6forum.nsf/DateAllThreadedweb/8076a4689494ab9f85256fa90061246d?OpenDocument

Subject: Other thoughts:

I was just surfing and read your article. You have done fantastic job. Thanks for sharing it with us.

I haven’t gone into details. I am sure you must have explored other possibilities. Do you think may be we can achieve the same by using:

  1. Readers fields in the group: Add a reder field in the group doc with a role or another group name. Groups will be hidden to them who are not part of the reader fields.

That way, you can also ensure Finance_Group can be used by only Finance Folks.

What if a user knows the restrictive group name & type it manually? - Need to test

  1. If server expand the group names after receiving it in Mail.Box then using C API we can check group name and user name, what to restrict. One place to check & Modify

  2. Some of your code + Server Rule in R6.

Cheers,

Pankaj

Subject: RE: Other thoughts:

Thanks for compliment and thoughts. To answer you questions.

“Do you think may be we can achieve the same by using: 1. Readers fields in the group: Add a reder field in the group doc with a role or another group name. Groups will be hidden to them who are not part of the reader fields. That way, you can also ensure Finance_Group can be used by only Finance Folks”

What if a user knows the restrictive group name & type it manually? - Need to test”

I have read that reader fields will not work if a user knows the name and types it in as all the readers field does is prevents them from seeing the doc. I have not tested whether or not that is true, but it makes sense to me.

But the way I have coded my solution matters not whether or not they manually type it or not. If the group name matches, it blocks it – whether or not they are connected or disconnected to the network.

  1. If server expand the group names after receiving it in Mail.Box then using C API we can check group name and user name, what to restrict. One place to check & Modify.

Possibly, but I am just really learning to code in somewhat of a decent manner and don’t know anything about how to use the c api. That said, and though the server does expand it in the mail.box per say, it doesn’t really expand the field in its place so much as it reads the value of the compressed field into a memory space or something and then creates mail messages based off of those values. When a user receives the message, if the personal group was not expanded, it does not show them the names of the people in the group. I had to force an expansion of the group in place and then refresh the field so that I could count and see if there were more than 19 addresses addressed to particular users.

“3. Some of your code + Server Rule in R6”

I am not sure what you mean here. But if I understand you correctly, a mail rule would not work for me because part of my requirments was to notify the user (assuming they were restricted) of their inability to mail groups the instant they hit the send button and stop the message from being processed any further.

Subject: RE: Other thoughts:

Just one comment - in ND6 the router now obeys the reader fields, so if some types the group name in, they will still be restricted from sending to the group. One of the things I love about ND6!

Subject: RE: Other thoughts:

I am assuming it generates a failure notification to the user?Even so, it would not meet the requirements I had because the business wanted it to stop and notify the user the moment they tried to send the email. In addition, it wanted someone to be notified that they had attempted to send to a restricted group. Not to mention that in my case, I would then have to maintain a group with thousands of people to be placed in these readers fields as only a small amount of people were to be restricted.

None-the-less, that is good info to have, so thanks.