mark messages as unread after user reads them

We have a shared mailbox which is administered by our boss. Other users have read/only access to this mailbox. Our problem is that we need to prevent the messages being marked as read when these other users read them. We need the messages only to be marked as read when the boss has read them.

I know that I can go into the Outlook Reading pane options and change the setting there, but this applies to the user's entire mailbox. So this is not suitible.

I can program in vba. So I was wondering if someone can show me a vba script which will fire when a user has read an email, and mark the message as unread again.
TownTalkAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kyle AbrahamsSenior .Net DeveloperCommented:
This has a sample that shows you how to get at the item and make it unread;
http://www.mrexcel.com/forum/general-excel-discussion-other-questions/267884-outlook-macro-mark-folder-items-read.html

That combined with objNS.CurrentUser.AddressEntry.GetExchangeUser.PrimarySmtpAddress
(from:
http://www.mrexcel.com/forum/excel-questions/655209-need-retrieve-outlook-user-email-visual-basic-applications-string.html)

is all you should need.
0
TownTalkAuthor Commented:
Thanks for the reply. I need some explanation please.... I can see how the first thread shows how to iterate through a folder marking the items. I don't understand your reason for the second thread. I'm not aware that I need the user's email address.

It's how to trigger the script that i'm not understanding. I'm looking to create a script which triggers when/after the current user reads an email in a particular folder. Obviously I would only place this script on the machines which have read only access to the shared mailbox.
0
Kyle AbrahamsSenior .Net DeveloperCommented:
That took a bit of work:

2 Parts:

1)  add this to ThisOutlookSession
Dim mh As MailHandler
Dim WithEvents oExpl As Outlook.explorer

Private Sub Application_Startup()
Set oExpl = Application.ActiveExplorer
Set mh = New MailHandler
End Sub

Private Sub oExpl_SelectionChange()

If TypeName(Application.ActiveExplorer.Selection(1)) = "MailItem" Then
    Set mh.myItem = Application.ActiveExplorer.Selection(1)
  End If
  
End Sub

Open in new window



Add a new Class called MailHandler    Note that you have to insert a class. It gets called class one, you then can change the name in the properties window (bottom left)

Public WithEvents myItem As Outlook.MailItem

Private Sub Class_Initialize()
 'you can initialize stuff here.  This gets called when class is instantiated. 
End Sub
 
 Sub myItem_Read()
 
  'add if statement here:  

  'if current user is not whomever then
         'myitem.UnRead = true
  'else 
        'myItem.unread = false
  'end if
 
 myItem.Save
 
End Sub

Open in new window

0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

TownTalkAuthor Commented:
Sorry for the delay in replying. I wasn't in the office yesterday, but thanks for writing the code :-)

I pasted your code as per your instructions. My first problem is that it won't compile. it highlights

Dim mh As MailHandler

and gives the error "User defined type not defined"

Assuming there is a simple fix, the next thing I would like to point out is that there is no need for me to test the identity of the user because I will only put this code on the machines where the user is going to mark the messages as unread again. However I do need to test which mailbox the message resides in. I only want this code to mark the message as unread if the message is in the shared mailbox. Messages in the users own mailbox should be ignored by this routine.
0
Kyle AbrahamsSenior .Net DeveloperCommented:
Can you post a screen shot of your project?  I'm assuming that you didn't rename the class.  (If you see a "Class 1" or don't see a class folder you missed something).

I understand you're going to only put this on the machines for people who have access to the mailbox . . . (minus your admin/manager).  I just like being more consistent.   (EG: Put it on everyone's machine, shouldn't effect target user).  What happens if the manager/admin uses a computer where this is installed?  It's an additional check, but won't hurt anything.


You can use the following to detect the email address where the mail item resides:
Application.ActiveExplorer.Selection(1).Parent.Parent

if calling from within the MailHandler you can use:

if myItem.Parent.Parent = "myEmail@theDomain.com" then
  myitem.Unread = true
  myItem.save
end if
0
Kyle AbrahamsSenior .Net DeveloperCommented:
I'm reposting the entire solution as there were changes made in both.  You can't use the Parent.Parent . . . a new function was created to handle it.

In ThisOutlookSession:

Dim WithEvents oExpl As Outlook.explorer
Dim mh As MailHandler

Private Sub Application_Startup()
Set oExpl = Application.ActiveExplorer
Set mh = New MailHandler
End Sub

Private Sub oExpl_SelectionChange()

'HANDLE FOLDER SWITCHING
On Error Resume Next

If TypeName(Application.ActiveExplorer.Selection(1)) = "MailItem" Then
    Set mh.myItem = Application.ActiveExplorer.Selection(1)
  End If
  
End Sub

Open in new window


And then in the MailHandler Class:

Public WithEvents myItem As Outlook.MailItem

Private Sub Class_Initialize()
 'you can initialize stuff here.  This gets called when class is instantiated.
End Sub
 
 Sub myItem_Read()
 
'CHANGE THE RIGHT SIDE TO BE WHATEVER EMAIL YOU WANT
 If GetAccount = "SomeAddress@Domain.Com" Then
    myItem.UnRead = True
    myItem.Save
 End If
 
End Sub


Public Function GetAccount() As String
Dim email As String
email = ""

Dim folder As Outlook.folder
Set folder = myItem.Parent

Dim store As Outlook.store
Set store = folder.store

Dim accounts As accounts
Dim account As account

Set accounts = Application.Session.accounts
Dim smtpAddress

Dim i As Integer
i = 1

    While i <= accounts.Count
        If accounts(i).DeliveryStore.StoreID = store.StoreID Then
            email = accounts(i).smtpAddress
            'there's no break for a while wend, break the loop.
           i = accounts.Count + 1
        End If
    Wend
    
   
    GetAccount = email
     
     

End Function

Open in new window


I used http://msdn.microsoft.com/en-us/library/office/ff866712.aspx as a template to figure out how to get the account name based on the folder.  It gave me the looping over accounts and compare storeIds portion.
0
TownTalkAuthor Commented:
Sorry. I saw that you told me how to rename the class. I didn't realise that it was essential that I did so. It compiles now.

I've run out of time today, and i'm not in the office tomorrow. I'll be picking this up on Friday hopefully. Thanks for your patience so far.

Ian
0
Kyle AbrahamsSenior .Net DeveloperCommented:
I'm out of the office till Monday, but feel free to post back if there are any issues.
0
TownTalkAuthor Commented:
Ok, i'm getting to grips with this now.....

I'm finding that the GetAccount() function isn't working how i need it to.

accounts.count always seems to have a value of 1. So the loop only ever goes around the one time and it only ever finds my own mailbox.

In outlook I have my own mailbox and the shared 'Info' mailbox which is what I am actually concerned with.
0
Kyle AbrahamsSenior .Net DeveloperCommented:
Are you only concerned with the one folder or could there be multiple folders underneath?
0
TownTalkAuthor Commented:
I'm just concerned with the Inbox folder on this account. There are no other folders.
0
Kyle AbrahamsSenior .Net DeveloperCommented:
You should be able to get away with the Parent.Parent implementation then.  

if myItem.Parent.Parent = "myEmail@theDomain.com" then
  myitem.Unread = true
  myItem.save
end if
0
TownTalkAuthor Commented:
I think we're getting a bit closer now,but there's still a problem.  But first I should explain.... When I click on an email in my own mailbox, myitem.parent.parent returns my email address as you stated. but for messages in the shared mailbox  MyItem.parent.parent returns the name of the mailbox, rather than the email address. So this is easier for me to deal with because there are multiple email addresses on this account. The mailbox is called 'Info'. So This is my code.

 Sub myItem_Read()
 
  iF myItem.Parent.Parent = "Info" THEN
           myItem.UnRead = True
           myItem.Save
     End iF
End Sub

I put a break point in there, and when I click on an email I can step through the code. It all executes as we want it to, but the email is marked as read afterwards.  Then I realised there is another problem.... If I click on an email which has already been read, it is then marked as unread. So this routine is toggling the state of the flag each time you read the email. When the boss has read an email, we don't want it being marked as unread again when one of the other users has read it.

I was wondering if this is a timing issue. Is there another event I can use which executes slightly later?

Thanks for your patience so far.

Ian
0
Kyle AbrahamsSenior .Net DeveloperCommented:
Hi Ian,

You could try saving whether the message is read or unread at the beginnging:

EG:


If TypeName(Application.ActiveExplorer.Selection(1)) = "MailItem" Then
    Set mh.myItem = Application.ActiveExplorer.Selection(1)
   mh.UnRead = mh.myItem.UnRead
  End If


'mail handler:
Public WithEvents myItem As Outlook.MailItem
Public bool UnRead


Sub myItem_Read()
 
  If myItem.Parent.Parent = "Info" AND UnRead THEN
           myItem.UnRead = True
           myItem.Save
     End iF
End Sub
0
Kyle AbrahamsSenior .Net DeveloperCommented:
0
TownTalkAuthor Commented:
That's cured half the problem. It's correctly detecting that a message was previously read, and it's not flagging it as unread. However, unread messages are still being flagged as read. The code in MyItem_Read() is executing correctly and the Item is flagged as Unread and saved. But some process is intercepting it later and marking it as Read again.

I had a look at the list of Events you sent me. My knowledge is not sufficient to know if any of them would be a better place for my code.
0
Kyle AbrahamsSenior .Net DeveloperCommented:
When I was trying this myself I couldn't catch when outlook flagged the message as read.  You may not be able to do this without writing some kind of plugin.  Maybe there's another way we can address what you're trying to accomplish?  

What's the importance of only having the boss mark it as read?
0
TownTalkAuthor Commented:
He regards himself as being the only person who is competent to read these messages and forward them on to the relevant people. If a message gets marked as read by someone else, then the boss could potentially miss seeing something important.

I'm coming around to the idea of sending people copies of these messages, I can create a local rule to put them them in a separate folder, and tell them to delete what they don't want.  I could also setup Autoarchive to clear out that folder after a specified period.
0
Kyle AbrahamsSenior .Net DeveloperCommented:
Distribution groups.  Then people can do what they want and the policy becomes don't forward this unless you're the boss.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
TownTalkAuthor Commented:
Yes that's good. A low maintenance solution. We got there in the end. Thnaks for your patience in all of this.

Ian
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Outlook

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.