I have a folder full of emails that are a custom message class (iXOS-Archive, related to OpenText Enterprise Archive). Each email has a custom metadata property, visible within Outlook, called "Document Identifier". I'm trying to extract this from the emails using a VBA script. I found a script that extracts common metadata (To, From, Subject etc.) from the emails and writes it to Excel. This works well.
http://spreadsheetpage.com/index.php/tip/getting_a_list_of_file_names_using_vba/
I've tried debugging the script and looking within the email properties, but I cannot find any collection that contains custom metadata.
Does anyone know how I can access the custom metadata through the VBA script?
You will probably not be able to do this using a FileSystemObject or DIR function (as given in the code you linked to, above).
I am unable to test without a suitable example, but this might work:
Bind Outlook to Excel
Open the MSG file in Outlook
Use the Outlook object model to review the MSG file's .ItemProperties
Practically speaking you will set this up in a loop, similar to your example code, but for the sake of testing, try it out on a single file and see if this will help you.
'Requires reference to Outlook object model
Sub foo()
Dim olApp As Outlook.Application
Dim msg As Outlook.MailItem
Dim properties As Outlook.ItemProperties
Dim p As Long
Set olApp = GetObject(, "Outlook.Application")
Set msg = olApp.CreateItemFromTemplate("C:\your filename.msg")
Set properties = msg.ItemProperties
For p = 0 To properties.Count - 1
Debug.Print properties(p).Name
Next
Set msg = Nothing
Set olApp = Nothing
End Sub
This should print the list of ItemProperties in the Immediate window, scroll through that list and check to see if the one you're looking for -- "Document Identifier" -- is included. If so, then this should work and you can modify as needed to do whatever it is you want to do with that information.
I cannot be of further assistance unless you can provide a test/sample version of this email format.
Cheers.
Related
Microsoft outlines how to leverage the Microsoft.Office.Interop.Outlook namespace quite well. example
I currently have a window form app created in VB, with a series of text fields requiring input. Upon submission of form, I have a text file that is created locally, but I also want to chain that event with the creation of an email, in a template fashion, having the user values embedded in the body of said email.
In my initial testing, to simply just generate the email, I have imported the appropriate function based on MS's documentation.
Imports Outlook = Microsoft.Office.Interop.Outlook
However when I enter the code provided after my text file creation code, there are many errors highlighted. I was prompted to create a friendclass for "Office."
Build does not like the CType(Application.CreateItem(Outlook.OlItemType - I observe the error CreateItem is not a member of Application.
Is this due to the windows form I selected when building this project?
Dim mail As Outlook.MailItem = CType(Application.CreateItem(Outlook.OlItemType.olMailItem), Outlook.MailItem)
Any help would be appreciated..
this appears to work - different approach but appears to work..
Dim oApp As Outlook.Application
oApp = New Outlook.Application
Dim oMsg As Outlook.MailItem
oMsg = oApp.CreateItem(Outlook.OlItemType.olMailItem)
oMsg.Recipients.Add("test#test.com")
oMsg.Subject = "test"
oMsg.HTMLBody = "<HTML><BODY>test - test</BODY></HTML>"
oMsg.Display()
now it is to figure out how to define a variable within the htmlbody section...
I am trying to add all my "autocompleted addresses" to a new contact folder but I can't get those addresses. What I call "autocompleted addresses" are the addresses saved when you send an email to somebody and you type it again in the "To" field of a new email.
I know I can get all the Global Address List by using
Set objOutlook = CreateObject("Outlook.Application")
Set myNameSpace = objOutlook.GetNamespace("MAPI")
Set GAL = myNameSpace.AddressLists("Offline Global Address List")
But how can I get my autocompleted addresses ?
I am using Outlook 2010 and my account is an Exchange Account.
Thank you for your help and your time.
EDIT
My complete code :
Set objOutlook = CreateObject("Outlook.Application")
Set myNameSpace = objOutlook.GetNamespace("MAPI")
Set folder = myNameSpace.GetDefaultFolder(OlDefaultFolders.olFolderInbox)
Set storage = folder.GetStorage("IPM.Configuration.Autocomplete", OlStorageIdentifierType.olIdentifyByMessageClass)
Set propacc = storage.PropertyAccessor
Set got = propacc.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7C090102")
Problem : got is empty...
instead of
Set got = propertyAcc.GetProperty(yadayada)
Don't use Set... just
got = propertyAcc.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7C090102")
This will give a zero-based array of the bytes used in the text stream.
got(0) = 13
got(1) = 240
etc etc...
From there, you can analyze each byte to get the text... but it would be very very ugly to parse it all out, when Redemption does that for you. In fact, if you've gotten this far in the post, then you've probably sorted out that it would be a better use of time to figure out how to use Redemption than to build your own parser for this purpose.
Autocomplete (nickname) stream is stored in a hidden (associated) message with the message class of "IPM.Configuration.Autocomplete" in the Inbox folder. Its format is documented at https://msdn.microsoft.com/en-us/library/office/ff625288.aspx. You can access that message using MAPIFolder.GetStorage.
If using Redemption is an option (I am its author), it exposes nicknames through the RDOStore / RDOSession.Nicknames collection.
Also note that in case of Outlook VBA you do need to create an instance of the Outlook.Application object, you already have an intrinsic Application variable pointing to that object.
I am trying to create a very simple (because I'm new and learning) scripted rule in Outlook 2010.
The RULE is: If a new mail item comes in from a particular email address, run my script and stop processing rules. The SCRIPT checks the body for a string. If the string is found, it moves the email to destination folder 1, otherwise it moves it to destination folder 2.
Sadly, I can't seem to get the script (code below) to do anything (mail just goes to inbox rather than either folder specified in script). A lot of this was pieced together from online examples, so I don't understand it all, but I figure I'd ask this now while I research the stuff I don't get. Any ideas on how to get this to work as intended?
'Use the MailItem class of item
Public Sub NCRFRule(Item As Outlook.MailItem)
Dim MAPI As NameSpace 'Don't know what this does
Dim dest1, dest2 As Folder 'declare destination folders
Dim newMail As MailItem 'set item type
'Don't know what this does.
Set MAPI = GetNamespace("MAPI")
'Set the destination folders
Set dest1 = MAPI.Folders("Inbox").Folders("NCRFs")
Set dest2 = MAPI.Folders("Inbox").Folders("other's NCRFs")
'Rule if-statement. If text is found, move mail to dest1 folder
If InStr(1, newMail.Body, "Your Required Action") <> 0 Then
newMail.Move dest1
GoTo cutOut:
End If
'If the above If-statement doesn't execute, text wasn't found,
'move mail to other destination folder.
newMail.Move dest2
cutOut:
End Sub
Note: this code is in the "ThisOutlookSession" module.
MAPI.Folders("Inbox")
There is no such folder. Use the GetDefaultFolder method of the Namespace or Store class instead.
Also you may find the Getting Started with VBA in Outlook 2010 article helpful.
Building on What Eugene explained, changing
Set dest1 = MAPI.Folders("Inbox").Folders("NCRFs")
Set dest2 = MAPI.Folders("Inbox").Folders("other's NCRFs")
to
Set dest1 = MAPI.GetDefaultFolder(olFolderInbox).Folders("NCRFs")
Set dest2 = MAPI.GetDefaultFolder(olFolderInbox).Folders("other's NCRFs")
got that part to work. Then I had to remove the line
Dim newMail As MailItem 'set item type
and replace all instances of "newMail" with "Item". Now it works!
I have a code that checks the recipient of the mail, looks what organization is set in the address book for the recipient and dependent on that sets the "SentOnBehalfOfName"-property of the item. If the recipient is working for client2, he will get the mail from "we_love_to_serve_client2#domain.com".
I call the code either before sending the mail via a button in my ribbon, that calls this Sub:
Sub Signatur()
Dim olApp As Outlook.Application
Dim objMail As Outlook.MailItem
Set olApp = Outlook.Application
Set objMail = Application.ActiveInspector.CurrentItem
Call Signatur_auto(objMail)
End Sub
I do this if I want to know which mail-adress is going to be chosen.
In the itemSend-section of thisOutlookSession I also call the same sub
Call Signatur_auto(Item)
Part of the Signatur_auto (i do not copy that in, the question is too long already...) is dealing with the SentOnBehalfOfName-property, the other part is putting the item into the right folder. The Folder is chosen depending on the SentOnBehalfOfName-property.
Now comes the interesting part: Although the folder-part is always working (which can only be when the SentOnBehalfOfName has worked before), the SentOnBehalfOfName only works "half". In the preview-line the mail sent is shown as from "we_serve_client2#domain.com", but when I open the mail it says it was sent by me. The Client always only sees my address, and also answers to my address - which I do not want....
How cant be, that the same code is having different results dependent on where it is called? Is it a Problem to change the sendonbehalf-field in the item send-section?
Thanks for any Inputs!
Max
Why it does not work?
Try this in ItemSend.
Dim copiedItem As mailItem
Set copiedItem = Item.Copy
copiedItem.SentOnBehalfOfName = "we_love_to_serve_client2#domain.com"
copiedItem.Send
Item.delete
Cancel = True ' In case your setup generates an error message as described in the comments
Why it works? Appears "copiedItem.Send" bypasses ItemSend.
I hope it's okay to ask this kind of question. Attempting to write the code myself is completely beyond me at the moment.
I need a macro for Outlook 2007 that will permanently delete all content of the Sent Items folder whenever anything arrives in it. Is it possible? How do I set everything up so that the user doesn't ever have to click anything to run it?
I know I'm asking for a fish, and I'm embarrassed, but I really need the thing...
edit:
I've pasted this into the VBA editor, into a new module:
Public Sub EmptySentEmailFolder()
Dim outApp As Outlook.Application
Dim sentFolder As Outlook.MAPIFolder
Dim item As Object
Dim entryID As String
Set outApp = CreateObject("outlook.application")
Set sentFolder = outApp.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
For i = sentFolder.Items.Count To 1 Step -1
sentFolder.Items(i).Delete '' Delete from mail folder
Next
Set item = Nothing
Set sentFolder = Nothing
Set outApp = Nothing
End Sub
It's just a slightly modified version of a piece of code I found somewhere on this site deleting Deleted Items. It does delete the Sent Items folder when I run it. Could you please help me modify it in such a way that it deletes Sent Items whenever anything appears in the folder, and in such a way that the user doesn't have to click anything to run it? I need it to be a completely automated process.
edit 2: Please if you think there's a better tool to achieve this than VBA, don't hesitate to edit the tags and comment.
edit 3: I did something that works sometimes, but sometimes it doesn't. And it's ridiculously complicated. I set a rule that ccs every sent email with an attachment to me. Another rule runs the following code, when an email from me arrives.
Sub Del(item As Outlook.MailItem)
Call EmptySentEmailFolder
End Sub
The thing has three behaviors, and I haven't been able to determine what triggers which behavior. Sometimes the thing does purge the Sent Items folder. Sometimes it does nothing. Sometimes the second rule gives the "operation failed" error message.
The idea of acting whenever something comes from my address is non-optimal for reasons that I'll omit for the sake of brevity. I tried to replace it with reports. I made a rule that sends a delivery report whenever I send an email. Then another rule runs the code upon receipt of the report. However, this has just one behavior: it never does anything.
Both ideas are so complicated that anything could go wrong really, and I'm having trouble debugging them. Both are non-optimal solutions too.
Would this be an acceptable solution? Sorry its late but my copy of Outlook was broken.
When you enter the Outlook VB Editor, the Project Explorer will be on the left. Click Ctrl+R if it isn't. It will look something like this:
+ Project1 (VbaProject.OTM)
or
- Project1 (VbaProject.OTM)
+ Microsoft Office Outlook Objects
+ Forms
+ Modules
"Forms" will be missing if you do not have any user forms. It is possible "Modules" is expanded. Click +s as necessary to get "Microsoft Office Outlook Objects" expanded:
- Project1 (VbaProject.OTM)
- Microsoft Office Outlook Objects
ThisOutlookSession
+ Forms
+ Modules
Click ThisOutlookSession. The module area will turn white unless you have already used this code area. This area is like a module but have additional privileges. Copy this code to that area:
Private Sub Application_MAPILogonComplete()
' This event routine is called automatically when a user has completed log in.
Dim sentFolder As Outlook.MAPIFolder
Dim entryID As String
Dim i As Long
Set sentFolder = CreateObject("Outlook.Application"). _
GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
For i = sentFolder.Items.Count To 1 Step -1
sentFolder.Items(i).Delete ' Move to Deleted Items
Next
Set sentFolder = Nothing
End Sub
I have taken your code, tidied it up a little and placed it within an event routine. An event routine is automatically called when the appropriate event occurs. This routine is called when the user has completed their log in. This is not what you requested but it might be an acceptable compromise.
Suggestion 2
I have not tried an ItemAdd event routine on the Sent Items folder before although I have used it with the Inbox. According to my limited testing, deleting the sent item does not interfere with the sending.
This code belongs in "ThisOutlookSession".
Option Explicit
Public WithEvents MyNewItems As Outlook.Items
Private Sub Application_MAPILogonComplete()
Dim NS As NameSpace
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
With NS
Set MyNewItems = NS.GetDefaultFolder(olFolderSentMail).Items
End With
End Sub
Private Sub myNewItems_ItemAdd(ByVal Item As Object)
Debug.Print "--------------------"
Debug.Print "Item added to Sent folder"
Debug.Print "Subject: " & Item.Subject
Item.Delete ' Move to Deleted Items
Debug.Print "Moved to Deleted Items"
End Sub
The Debug.Print statements show you have limited access to the sent item. If you try to access more sensitive properties, you will trigger a warning to the user that a macro is assessing emails.