?
Solved

mark messages as unread after user reads them

Posted on 2014-07-14
20
Medium Priority
?
736 Views
Last Modified: 2014-07-30
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.
0
Comment
Question by:TownTalk
  • 11
  • 9
20 Comments
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40194757
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
 

Author Comment

by:TownTalk
ID: 40194886
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40195664
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
Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

 

Author Comment

by:TownTalk
ID: 40198972
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40199181
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40199368
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
 

Author Comment

by:TownTalk
ID: 40199876
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40200102
I'm out of the office till Monday, but feel free to post back if there are any issues.
0
 

Author Comment

by:TownTalk
ID: 40204848
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40212990
Are you only concerned with the one folder or could there be multiple folders underneath?
0
 

Author Comment

by:TownTalk
ID: 40213605
I'm just concerned with the Inbox folder on this account. There are no other folders.
0
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40215415
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
 

Author Comment

by:TownTalk
ID: 40223785
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40224574
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40224576
0
 

Author Comment

by:TownTalk
ID: 40226171
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
 
LVL 41

Expert Comment

by:Kyle Abrahams
ID: 40227197
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
 

Author Comment

by:TownTalk
ID: 40228580
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
 
LVL 41

Accepted Solution

by:
Kyle Abrahams earned 2000 total points
ID: 40229238
Distribution groups.  Then people can do what they want and the policy becomes don't forward this unless you're the boss.
0
 

Author Closing Comment

by:TownTalk
ID: 40229321
Yes that's good. A low maintenance solution. We got there in the end. Thnaks for your patience in all of this.

Ian
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will help to fix the below errors for MS Exchange Server 2013 I. Certificate error "name on the security certificate is invalid or does not match the name of the site" II. Out of Office not working III. Make Internal URLs and Externa…
I came across an unsolved Outlook issue and here is my solution.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question