SOLVED! The Fox comes through again!
Using the two links that Gianni provided, I started playing around with the code provided there and looking at what options were available to the various Outlook Objects and was able to put together a quick and dirty program that parses through all of the folders and PST files I have open in Outlook and extracts all of the sender email addresses from all of the emails I've received in the past 25 years. It also captures the name, the first date and last dates I received a message from every email address, so I can filter the list further. There are two cursors created during the process, the first captures the folders examined and the second captures all of the email addresses. I'll attach the program below just in case someone else needs something similar.
As I said it is about 95% complete meaning there are a few things I'd probably do differently, like force case to upper or lower to ensure no duplicates get through ( I fixed this while editing the results in Excel), there's no real user interface which would be nice, it would be very easy to create a drop-down to allow you to choose the starting folder/pst file to scan or to provide filter text to extract all of the messages for certain domain or something. I can think of lots to do with this, but it will have to wait until another day. In the meantime, if you can learn something from my rough coding or offer suggestions for improvements, go for it!
Thanks to those who responded to my request for help! You came through and here are the results of your help:
---------------------------------------------------------------- LOCAL loOutlook AS "Outlook.Application" LOCAL lnBegProcess, lnCounter, lnEndProcess, loFolders, loM, loNameSpace
CLEAR
m.lnBegProcess = SECONDS()
CREATE CURSOR FolderList (FolderName C(100) NOT NULL)
CREATE CURSOR EmailSenders (SentBy c(100) NOT NULL, Address C(100) NOT NULL, firstcontact T NOT NULL, lastcontact T NOT NULL) INDEX ON DELETED() TAG pkdel INDEX ON Address TAG Address
m.loOutlook = CREATEOBJECT("Outlook.Application") m.loNameSpace = m.loOutlook.GetNameSpace("MAPI") m.loFolders = m.loNameSpace.Folders
FOR m.lnCounter = 1 TO m.loFolders.COUNT
IF TYPE("loFolders.ITEM(lnCounter).Folders.count") = "N"
IF m.loFolders.ITEM(m.lnCounter).Folders.COUNT > 0
? m.lnCounter, m.loFolders.ITEM(m.lnCounter).NAME
INSERT INTO FolderList (FolderName) VALUES (TRANSFORM(m.lnCounter) + SPACE(1) + m.loFolders.ITEM(m.lnCounter).NAME)
FOR EACH m.loM IN m.loFolders.ITEM(m.lnCounter).Items
IF TYPE("lom.Sender.Address") = "C"
SEEK PADR(m.loM.Sender.Address, 100) ORDER TAG Address IN EmailSenders
IF !FOUND("EmailSenders")
INSERT INTO EmailSenders (SentBy, Address, firstcontact, lastcontact) VALUES (m.loM.Sender.Name, m.loM.Sender.Address, m.loM.ReceivedTime, m.loM.ReceivedTime)
ELSE
IF m.loM.ReceivedTime > EmailSenders.lastcontact
REPLACE EmailSenders.lastcontact WITH m.loM.ReceivedTime IN EmailSenders
ENDIF
ENDIF
ENDIF
ENDFOR
GetChildren(m.loFolders.ITEM(m.lnCounter).Folders, 1)
ENDIF
ENDIF
ENDFOR
m.loNameSpace = NULL m.loOutlook = NULL RELEASE m.loNameSpace RELEASE m.loOutlook
m.lnEndProcess = SECONDS() ? ? ? "Minutes To Process:", ROUND((m.lnEndProcess - m.lnBegProcess) / 60, 2)
PROCEDURE GetChildren LPARAMETERS toFolders, tnLevel
LOCAL lnCounter
FOR m.lnCounter = 1 TO m.toFolders.COUNT
IF TYPE("toFolders.ITEM(lnCounter).Folders.count") = "N"
? SPACE(m.tnLevel * 5), m.lnCounter, m.toFolders.ITEM(m.lnCounter).NAME INSERT INTO FolderList (FolderName) VALUES (SPACE(m.tnLevel * 5) + TRANSFORM(m.lnCounter) + SPACE(1) + m.toFolders.ITEM(m.lnCounter).NAME)
FOR EACH m.loM IN m.toFolders.ITEM(m.lnCounter).Items
IF TYPE("lom.Sender.Address") = "C"
SEEK PADR(m.loM.Sender.Address, 100) ORDER TAG Address IN EmailSenders
IF !FOUND("EmailSenders")
INSERT INTO EmailSenders (SentBy, Address, firstcontact, lastcontact) VALUES (m.loM.Sender.Name, m.loM.Sender.Address, m.loM.ReceivedTime, m.loM.ReceivedTime)
ELSE
IF m.loM.ReceivedTime > EmailSenders.lastcontact
REPLACE EmailSenders.lastcontact WITH m.loM.ReceivedTime IN EmailSenders
ENDIF
ENDIF
ENDIF
ENDFOR
IF m.toFolders.ITEM(m.lnCounter).Folders.COUNT > 0
GetChildren(m.toFolders.ITEM(m.lnCounter).Folders, m.tnLevel + 1)
ENDIF
ENDIF
ENDFOR
ENDPROC ----------------------------------------------------------------
Paul H. Tarver Tarver Program Consultants, Inc.
-----Original Message----- From: ProfoxTech [mailto:profoxtech-bounces@leafe.com] On Behalf Of Gianni Turri Sent: Sunday, August 11, 2024 7:06 AM To: profoxtech@leafe.com Subject: Re: Outlook Automation Help Needed
Hi Paul,
did you find these posts during your Internet searches?
Enumerating Outlook Folders into Treeview https://www.tek-tips.com/viewthread.cfm?qid=913176
Copying Emails into a VFP table from Outlook https://www.tek-tips.com/viewthread.cfm?qid=1784442
Probably you need to open and connect to your Outlook instance your variuos .PST files before running any code that searches for folders and emails.
HTH, Gianni
On Fri, 9 Aug 2024 12:17:51 -0500, "Paul H. Tarver" paul@tpcqpc.com wrote:
Ok, before I ask my question, I want to confirm that I've looked at the Microsoft Office Automation with Visual FoxPro book, searched for Outlook related messages on this list and spent more than I wanted to on the Internet and still haven't found a solution that I can use or modify to accomplish my goal. So, it's up to ProFox now.
Here's what I need to do: I have a system with Outlook 2010 running on it. I need to access the individual emails stored in multiple pst files with multiple sub-folders and extract the unique email addresses found on those emails. Ideally, I'd like to select the .PST file and have a program loop through all of the folders/subfolders, touch each email and extract any email addresses that contain a search string.
I can get an Outlook object active in VFP, but things get muddy after that.
Any ideas? Or is this even doable? I feel like the Fox is capable, but at the moment I'm not. J
Paul H. Tarver Tarver Program Consultants, Inc.
--- StripMime Report -- processed MIME parts --- multipart/alternative text/plain (text body -- kept) text/html ---
[excessive quoting removed by server]