Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Parse email msgs in VB 1

Status
Not open for further replies.

eramgarden

Programmer
Aug 27, 2003
279
0
0
US
I need to parse email messages to extract information........Can it be done in VB?

My app is VB6, uses CDO dll using outlook2000...

Now when we receive an email, we like to parse it and only keep part of the incoming email..is this possible?
 
Yes it's perfectly possible. If you want to catch the mail as it's received then in theory you could create a COM addin for OL2000 to which is passed the mail received event. However, I've found that when several mails are received in quick succession the event doesn't fire for each one and it's hard to get it to work reliably.

Using the Outlook object model you can get a refernce to the Items collection of the Inbox folder and use the Restrict method to select the e-mails to process. Then it's simple to extract the sender, body etc for each item and parse as required. It's usually the parsing that needs the most coding! If you need the sender e-mail address then you have to use CDO as well to return the item; it isn't available directly from the Outlook object model. Using only Outlook you have to create a dummy reply to the item and get the addr from its Recipients collection.

You might like to have a look at OLServices on my web site: See the GetMailTags method of the OMailItem object. You pass it the selection criteria and it returns a collection of MailTag objects which represent the key properties of the selected e-mails; subject body etc. I use this frequently for parsing jobs. A common application is to search the Inbox for e-mails returned undeliverable, parse out the failed e-mail address then find and delete it from a database.

Paul Bent
Northwind IT Systems
 
Thanks for your response...

I looked at your website...great info...

let me ask you this...

Is there a dll for "Outlook object model"?? where, how can I get it? Any ideas on how to code the "parse" section?

Any leads would be great!
 
let me ask one more thing about your product...

Can that oServices actually parse out emails?
 
If you want to code directly against the Outlook object model then all you need is Outlook installed on the end-user's system. Set a reference to Microsoft Outlook nn.n Object library and the object model is available to your project.

If you use OLServices then as I explained, you can return a collection of selected mail items with GetMailTags and from there access properties such as Sender. Subject, Body etc. You can also get a reference to items in the collection with a view to processing the item such as forward it, copy/move it, delete it etc. That's as far as OLServices goes; it will return the e-mail bodies but you have to write your own parsing function depending on your requirements.

Here's a sample parsing function to extract failed e-mail addresses from bounced e-mails. Different mail servers use different subject lines and text in the return notifications. I've declared constants for text strings that immediately precede and follow the address. The function loads these constants in an array then attempts to find them in the text. If found the start and end positions of the e-mail address is known and it can be parsed out:
Code:
'Constants for search strings in the body immediately preceding and following the failed e-mail address
Public Const RTN_S1 = "----- The following addresses had permanent fatal errors -----"
Public Const RTN_FTAG1 = &quot;<&quot;
Public Const RTN_ETAG1 = &quot;>&quot;
'and so on...
Public Const RTN_S11 = &quot;message was addressed&quot;
Public Const RTN_FTAG11 = &quot;, &quot;
Public Const RTN_ETAG11 = &quot;,&quot;

Public Const RTN_S12 = &quot;The user(s) account is disabled&quot;
Public Const RTN_FTAG12 = &quot;<&quot;
Public Const RTN_ETAG12 = &quot;>&quot;


Public Type RTN_EMAIL
	intNum As Integer 'Number of occurence of search string
	strTgt As String  'Search string
	strFTag As String  'Tag preceding e-mail address
	strETAg As String  'Tag following e-mail address
End Type
'_________________________

Public Function fParseRtnEmail(Byval strText As String) As String
	
 '--- Given the text of an e-mail return notification,
 '    parses the failed e-mail address
	
 '--- Parameters
 '	[In]
 '	strText: the string to parse
	
 '--- Return value
 '	returns the e-mail address else an empty string if the parsing was unsuccessful
	
 Dim intC1 As Integer	'Counter
 Dim intC2 As Integer   'Counter
 Dim intTmp   'Temp position
 Dim intP1 As Integer  'Position of first character after the search string
 Dim intP2 As Integer  'Position of tag preceding the e-mail address
 Dim intP3 As Integer  'Position of tag following the e-mail address
 Dim intFlag As Integer  'True if the e-mail address was parsed from Text
 Dim audtTags() As RTN_EMAIL 'Tags to search for e-mail address
 Dim strData As String  'Current value parsed from Text
	
 'Check strText isn't empty
 If Len(strText) = 0 Then
  Exit Function
 End If
	
 'Load the search tags in the udt array
 Redim audtTags(0 To 12)
 audtTags(0).intNum = 2
 audtTags(0).strTgt = RTN_S1
 audtTags(0).strFTag = RTN_FTAG1
 audtTags(0).strETag = RTN_ETAG1
 audtTags(1).intNum = 1
 audtTags(1).strTgt = RTN_S2
 audtTags(1).strFTag = RTN_FTAG2
 audtTags(1).strETag = RTN_ETAG2
 audtTags(2).intNum = 1
 audtTags(2).strTgt = RTN_S3
 audtTags(2).strFTag = RTN_FTAG3
 audtTags(2).strETag = RTN_ETAG13
 audtTags(3).intNum = 1
 audtTags(3).strTgt = RTN_S4
 audtTags(3).strFTag = RTN_FTAG4
 audtTags(3).strETag = RTN_ETAG4
 audtTags(4).intNum = 1
 audtTags(4).strTgt = RTN_S5
 audtTags(4).strFTag = RTN_FTAG5
 audtTags(4).strETag = RTN_ETAG5
 audtTags(5).intNum = 1
 audtTags(5).strTgt = RTN_S6
 audtTags(5).strFTag = RTN_FTAG6
 audtTags(5).strETag = RTN_ETAG6
 audtTags(6).intNum = 1
 audtTags(6).strTgt = RTN_S7
 audtTags(6).strFTag = RTN_FTAG7
 audtTags(6).strETag = RTN_ETAG7
 audtTags(7).intNum = 1
 audtTags(7).strTgt = RTN_S8
 audtTags(7).strFTag = RTN_FTAG8
 audtTags(7).strETag = RTN_ETAG8
 audtTags(8).intNum = 2
 audtTags(8).strTgt = RTN_S9
 audtTags(8).strFTag = RTN_FTAG9
 audtTags(8).strETag = RTN_ETAG9
 audtTags(9).intNum = 1
 audtTags(9).strTgt = RTN_S10
 audtTags(9).strFTag = RTN_FTAG10
 audtTags(9).strETag = RTN_ETAG10
 audtTags(10).intNum = 1
 audtTags(10).strTgt = RTN_S11
 audtTags(10).strFTag = RTN_FTAG11
 audtTags(10).strETag = RTN_ETAG11
 audtTags(11).intNum = 1
 audtTags(11).strTgt = RTN_S12
 audtTags(11).strFTag = RTN_FTAG12
 audtTags(11).strETag = RTN_ETAG12
 audtTags(12).strTgt = RTN_S13
 audtTags(12).strFTag = RTN_FTAG13
 audtTags(12).strETag = RTN_ETAG13
	
 'Move through the primary search string array and parse the failed address
 intFlag = False
 For intC1 = Lbound(audtTags) To Ubound(audtTags)
  'Look for each search string
 If Instr(1, strText, audtTags(intC1).strTgt) Then
   'Store the position of the first character after the primary search string
   If audtTags(intC1).intNum < 2 Then
    'The string only occurs once before the e-mail address
    intP1 = Instr(1, strText, audtTags(intC1).strTgt) + _
    Len(audtTags(intC1).strTgt)
   Else
    'The string may occur more than once before the e-mail address
    intTmp = 1
    For intC2 = 1 To audtTags(intC1).intNum
     intP1 = Instr(intTmp, strText, audtTags(intC1).strTgt)
     If intP1 = 0 Then
      intP1 = intTmp
      Exit For
     Else
      intTmp = intP1 + Len(audtTags(intC1).strTgt)
     End If
    Next
   End If
   'Store the position of the tag preceeding the e-mail address
   intP2 = Instr(intP1, strText, audtTags(intC1).strFTag)
   If intP2 >= intP1 Then
    'Store the position of the tag following the e-mail address
    intP3 = Instr(intP2 + Len(audtTags(intC1).strFTag), strText, audtTags(intC1).strETag)
    'Parse the data
    If intP3 > intP2 + 1 Then
     strData = Trim$(Mid$(strText, intP2 + Len(audtTags(intC1).strFTag), _
     intP3 - intP2 - Len(audtTags(intC1).strFTag)))
     If Not strData = &quot;&quot; Then
      'Verify it is an e-mail address
      If Instr(1, strData, &quot;@&quot;) > 0 Then
       fParseRtnEmail = strData
       'Flag we found it
        intFlag = True
      End If
     End If
    End If
   End If
  End If
  'Exit if we found a primary search string
  If intFlag Then Exit For
 Next
	
End Function
Paul Bent
Northwind IT Systems
 
Hi,

In this thread, paulbent made this statement:

&quot;If you want to catch the mail as it's received then in theory you could create a COM addin for OL2000 to which is passed the mail received event.&quot;

I'm trying to create a COM addin for OL2000 to which is paseed the mail sent event. Based on paulbent's statement I'm assuming this is possible but I can't figure out how to trap the event. Does anyone know how to do this?

Thanks!

Jeff
 
A Com Addin is an ActiveX DLL that's loaded by and runs in the same process as Outlook. You need to implement the IDTExtensibility2 interface which will pass to your addin the events that take place within Outlook.

Set a project reference to Microsoft Add-In Designer (the IDTExtensibility2 library), MSADDNDR.DLL and put this statement in the declaration section of the class module:

Implements IDTExtensibility2

The IDTExtensibility2 object in the Object list has five event procedures. You must create at least a stub for all 5 containing at least a comment else you'll get a compile error.

Then declare a private module level variable for the Outlook app object:

Private mobjOLApp As Outlook.Application

Then use the IDTExtensibility2 OnConnection procedure to instantiate the Outlook object. OnConnection automatically supplies a reference to whatever container application is alerting the addin.

Private Sub IDTExtensibility2_On Connection()
'Application returns the container application
Set mobjOLApp = Application
End Sub

Now you can declare a module level variable such as:

Private WithEvents mobjItems As Outlook.Items

This will tell Outlook to notify the addin when events of the Items collection object occur. You can put code behind the ItemAdd event to process new Items when they are received in the Inbox.

This is a very simplified explanation of a complex topic. I think you may find a tutorial/code example at
Paul Bent
Northwind IT Systems
 
Thanks for the great info Paul! I really appreciate it. I actually got it to work using an ActiveX DLL project and using the Addin designer in VB6. I did have to add a reference to the Microsoft Outlook 9.0 Object Library.

My next questions are which method should I use and how do I implement this on roughly 15 workstations? From what I've read, the ActiveX DLL solution is more direct and efficient than using the Addin designer but the Addin designer solution is easier to register. Do you have any experience in this arena?

Thanks again,

Jeff
 
That's probably true but I haven't bothered with the COM Add-in Designer myself so can't comment from first hand experience. I prefer to code it from scratch in the regular VB interface and create a distribution package (using a commercial tool) which handles the registration.

Both methods yield the same result - an ActiveX DLL registered with Outlook as an addin.

Paul Bent
Northwind IT Systems
 
I discovered that my DLL can be registered by simply using regsvr32.exe. I'm not sure if this works for DLL's created as ActiveX DLL projects in VB6 but it definitely works for DLL's created as Addin projects in VB6. To distribute, I'm going to add a couple statements to the login script to copy the DLL to the user's workstation and register it using regsvr32 with the /s flag.

Now that this is complete, I need to figure out how to circumvent the Outlook E-Mail Security update. I have some good leads, one being some freeware called Outlook Redemption ( If anyone has any feedback on this product or any other ways to stop the Outlook warning when our own apps are accessing the user's mailbox, I would apprecitate it.
 
You also have to create several registry entries under Outlook\Addins. The key is in both the HKCU and HKLM hives. If you register in HKCU the addin is loaded on a user-by-user basis per the settings under Tools | Options | Other | Advanced | COM Addins. If under HKLM then the addin is loaded for every user of the computer.

For example, under HKLM\Software\Microsoft\Office\Outlook\Addins you would create a key named in the form MyLibarary.MyClass and in it, these value names:

FriendlyName (string)
Filename (string)
Description (string)
LoadBehaviour (dWord)

Oulook locates the addin from its class name which is defined as the name of the registry key, MyLibrary.MyClass

Redemption is the way to go to avoid the Outlook object model guard but it isn't freeware to developers, only personal users. Dimitri Streblechenko, the author, is a real star and gives a lot of his free time answering questions in the MS newsgroup. He deserves his licence fees!

Paul Bent
Northwind IT Systems
 
Paul,

I think you need to add those other keys if you create it as an ActiveX DLL project in VB6. I created my DLL as an Addin project. I copied it to a folder on the user's hard drive and typed &quot;regsvr32 myaddin.dll&quot; from a command prompt on the user's machine and it worked. For some reason, these DLL's don't need to be added to the ...Software\Microsoft\Office\<office app>\Addins folder. I noticed this after making my DLL in VB6 and checking to see what keys it created. I guess this is why KB article 238228 says the downside of the IDTExtensibility2 solution is the registration. If you think I'm missing something, please let me know.

As for Redemption, thanks for the feedback. I'll look into the cost and I hope I can talk my boss into purchasing it.

Thanks again for all of your help!
 
OK, my DLL is complete, I beta tested on 3 user's PCs and I'm trying to distribute it to a larger audience. I chose to distribute it via a login script that copies the DLL to the user's PC and runs REGSVR32 with the /s switch. This worked great except 2 users are unable to register the DLL. I first learned of the problem because the DLL wasn't running. I checked their registries and there was no sign of the DLL. I tried to run it manually while logged on as them and received the following error: &quot;DLLREGISTERSERVER in myaddin.dll Failed. Return code was 0x80004005.&quot; I've searched Tek-tips, MS Knowledge base, and done several google searches and the best I could come up with was a permissions issue. However, the registration was successful for a user that does not have Admin rights to her PC which contradicts the potential solution of giving the users Admin rights to their PCs. Also, I logged onto one of the &quot;problem PCs&quot; and the registration was successful (I'm an admin). However, when I logged off and the user logged on, the DLL didn't run - presumably because she is not the person that registered it. I'm at a complete loss as to how to solve the 0x80004005 issue. Please help!

Thanks!

Jeff
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top