bigfudge
Goto Top

Outlook newMailex oder NewMail?

Guten Tag,

Ich stehe vor der Aufgabe ein Macro für Outlook zu schreiben, welches auf eingehende
eMails reagiert.
Bin bisher auf 2 Events gestoßen, welche dies gut bewerkstelligen sollten (s.o.).

Der Hauptunterschied den ich bisher festgestellt habe ist, dass newMailEx die IDs der eingehenden ELEMENTE (MailItem, MeetingItem, ...)
mitgibt, was für mein weiteres vorhaben wahrscheinlich sehr nützlich ist.

NewMail dagegen wird wohl bei jeder eingehenden EMAIL ausgelöst, was wiederum auch sehr nützlich ist.

Gibt es eine Möglichkeit beide Events zu vereinen? z.B. durch eine Prüfung am Anfang des Macros o.Ä.

EDIT: Vielleicht hilft es ja, ich würde das Event gerne so wie in diesem Artikel benutzen: http://msdn.microsoft.com/de-de/library/office/ff863686(v=office.15).as ...

Liebe Grüße,
fudge

Content-ID: 250389

Url: https://administrator.de/contentid/250389

Ausgedruckt am: 22.11.2024 um 07:11 Uhr

colinardo
Lösung colinardo 28.09.2014 aktualisiert um 09:05:05 Uhr
Goto Top
Hallo fudge, Willkommen auf Administrator.de!
NewMail dagegen wird wohl bei jeder eingehenden EMAIL ausgelöst, was wiederum auch sehr nützlich ist.
Das stimmt so nicht ganz ...
Benutze NewMailEx als einziges Event, da du nur mit diesem wirklich jede neue Mail erfassen kannst. Das einfache NewMail wird oft nur einmal abgefeuert auch wenn zwei Mails gleichzeitig zur selben Zeit eintreffen, wohingegen du mit NewMailEx die IDs aller gerade neu eingetroffenen Mails als kommagetrennten String geliefert bekommst über welche du dann mit einer Schleife iterieren kannst !

Beispiele dazu findest du hier im Forum etliche face-wink

Grüße Uwe
bigfudge
bigfudge 28.09.2014 um 09:09:00 Uhr
Goto Top
Hi Uwe,

vielen Dank, scheint hier ein klasse Forum zu sein, lese zwar schon länger mit aber habe nun auch wirklich mal eine Frage - netter Empfang! ;)

Meine Hauptsorge ist einfach, dass laut oben verlinktem Artikel nicht nur eMails sondern auch "von mehreren verschiedenen Elementtypen , z.B.MailItem, MeetingItem oder SharingItem" ausgelöst wird. Gibt es eine Möglichkeit mit diesem Event nur MailItems (olMail) zu verarbeiten?

Sers, fudge
colinardo
Lösung colinardo 28.09.2014 aktualisiert um 09:17:56 Uhr
Goto Top
Zitat von @bigfudge:
Meine Hauptsorge ist einfach, dass laut oben verlinktem Artikel nicht nur eMails sondern auch "von mehreren verschiedenen
Elementtypen , z.B.MailItem, MeetingItem oder SharingItem" ausgelöst wird. Gibt es eine Möglichkeit mit diesem
Event nur MailItems (olMail) zu verarbeiten?

kein Problem, in den oben verlinkten Beispielen kannst du sehen das ich den Typ bzw. die Klasse des Objektes vor der Verarbeitung prüfe:
if objItem.Class = olMail then
...
..
end If
so kannst du unterscheiden mit was für einem Objekt du es zu tun hast.
bigfudge
bigfudge 28.09.2014 um 09:24:14 Uhr
Goto Top
Ja, das ergibt Sinn. Habe das jetzt mal so wie in den oben verlinkten Beispielen die Prüfung eingefügt.
Falls ich nun noch die Inbox durchsuchen will, kann ich diese schätze ich mal über .Parent setzen. Dieser ganze Mechanismus geschieht
zeitlich meine ich VOR der Ausführung der Outlook-Regeln oder? Soll heißen, wenn nach dem Event die Mail per Regel in ein anderes Postfach/Ordner
verschoben wird kommt es zu Fehlern? Hoffe du verstehst was ich meine, gibt es dafür vllt. einen Fix? Vielleicht ist es möglich einfach alle Mails in Outlook
zu durchsuchen?
colinardo
colinardo 28.09.2014 aktualisiert um 09:37:42 Uhr
Goto Top
Zitat von @bigfudge:

Ja, das ergibt Sinn. Habe das jetzt mal so wie in den oben verlinkten Beispielen die Prüfung eingefügt.
Falls ich nun noch die Inbox durchsuchen will, > kann ich diese schätze ich mal über .Parent setzen.
Das wäre im Falle von weiteren Regeln im Posteingang nicht gut, denn dann würde dir der Ordner zurückgegeben in den die Mail verschoben worden ist.
Dieser ganze
Mechanismus geschieht
zeitlich meine ich VOR der Ausführung der Outlook-Regeln oder?
jein eher gleichzeitig.
Soll heißen, wenn nach dem Event die Mail per Regel in
ein anderes Postfach/Ordner
verschoben wird kommt es zu Fehlern?
es kommt nicht zu Fehlern, aber die Mail befindet sich dann halt nicht mehr in der Inbox, deswegen ist .Parent da nicht so gut. Die ItemID liefert dir ja das Objekt egal wo es im Postfach hin verschoben wird.

Hoffe du verstehst was ich meine, gibt es dafür vllt. einen Fix?
setze den Posteingang fix als Folder-Objekt:
set objInbox = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
dann kannst du mit einer Schleife über alle Objekte in einem Ordner iterieren:
for each mail in objInbox.Items
...
Next
bigfudge
bigfudge 28.09.2014 um 09:50:29 Uhr
Goto Top
Also Ziel des Macros ist es genau den Ordner später zu durchsuchen wo Mails dieser Art letztendlich landen. Dann wäre .Parent wohl gar nicht so falsch?

Ich ginge davon aus, dass ich mit .Parent die normale Inbox kriege (da zeitl. vor Regelausführung) und die eMail dannach verschoben wird (in den Ordner den ich durchsuchen will) womit der durch Parent gesetzte Ordner falsch wäre.

Wenn ich den Ordner fix setze, welchen Wert nehme ich für "olFolderInbox" ? Einfach den Ordnernamen den ich in Outlook sehe? Diese zusätzlichen Ordner
befinden sich ja schätze ich mal alle in der "Inbox", weshalb es ja am einfachsten wäre einfach diese komplett zu durchsuchen.

Denke aber mal bei einem normalen Schleifendurchlauf wird nicht über Items in Unterordnern iteriert?
colinardo
Lösung colinardo 28.09.2014 aktualisiert um 10:30:57 Uhr
Goto Top
Zitat von @bigfudge:

Also Ziel des Macros ist es genau den Ordner später zu durchsuchen wo Mails dieser Art letztendlich landen. Dann wäre .Parent wohl gar nicht so falsch?
In diesem Fall natürlich richtig ...
Ich ginge davon aus, dass ich mit .Parent die normale Inbox kriege (da zeitl. vor Regelausführung) und die eMail dannach verschoben wird (in den Ordner den ich durchsuchen will) womit der durch Parent gesetzte Ordner falsch wäre.
den genauen zeitlichen Ablauf muss ich später nochmal genau checken, bin gerade auf dem Smartphone.
Wenn ich den Ordner fix setze, welchen Wert nehme ich für "olFolderInbox" ? Einfach den Ordnernamen den ich in
Outlook sehe?
olFolderInbox ist eine Konstante und bezeichnet den Standardposteingang im Hauptstore.

Denke aber mal bei einem normalen Schleifendurchlauf wird nicht über Items in Unterordnern iteriert?
Richtig, Dazu müsstest du dann eine Rekursive Funktion nehmen. Hatte ich hier schon mal eine Funktion gepostet, finde sie gerade nur nicht ...
bigfudge
bigfudge 28.09.2014 um 10:28:00 Uhr
Goto Top
Alles klar, dann hier schonmal vielen Dank für deine Hilfe! Falls du etwas genaueres zu dem zeitl. Ablauf herausfindest kannst du es ja hier noch posten.
Ich werde demnächst abklären was für Regeln es gibt und wie die Ordnerstruktur wirklich ist.

Bis dann, schönen Sonntag wünsche ich dir
colinardo
Lösung colinardo 28.09.2014 aktualisiert um 13:56:26 Uhr
Goto Top
Also, es gibt hier eine Race-Condition (d.h. Event und Regel starten gleichzeitig, bzw kurz nach dem Eintreffen), es kann also sein das eine Mail wenn das Event auftritt bereits verschoben wurde. Die zugeordneten IDs sind nicht die endgültigen für die Elemente im Store. Es gibt aber in der MAPI-Definition eine Eigenschaft namens PR_SEARCH_ID welche beim Eintreffen der Mail sowie später gleich bleiben. Man kann also danach im Store suchen.
Man muss also diese PR_SEARCH_ID so schnell wie möglich im NewMailEx-Event in eine Collection speichern und dann die Ordner des Stores nach dieser ID rekursiv durchforsten.
Siehe dazu auch: http://stackoverflow.com/questions/2301999/vsto-process-mail-using-newm ...

In VBA könnte das so aussehen (ACHTUNG nicht geeignet für IMAP-Konten, da hier das Mailverschieben verzögert stattfindet und die Mails dann nicht gefunden werden), ansonsten nur grob angetestet. In Zeile 4 den Storenamen angeben, der dann durchsucht wird. Man kann das ganze natürlich auch auf alle Stores ausweiten, aber als Beispiel sollte das reichen. Im Beispiel werden dann das Subject der Mail und der Ordner in dem die Mail sich nun befindet mit einer MsgBox ausgegeben.

Weitere Kommentare im Code.

Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
    Dim varEntryIDs, objItem As Object, startFolder As Folder, i As Integer, colPRIds As New Collection
    ' Rootfolder des Stores angeben  
    Set startFolder = Application.Session.Stores("user@domain.de").GetRootFolder  
    
    varEntryIDs = Split(EntryIDCollection, ",")  
    For i = 0 To UBound(varEntryIDs)
        'Objekt holen  
        Set objItem = Application.Session.GetItemFromID(varEntryIDs(i))
        'wenn Objekt ein Mailitem ist  
        If objItem.CLASS = olMail Then
            'extrahiere die PR_SEARCH_ID Eigenschaft und füge sie der Collection hinzu  
            colPRIds.add getPRSearchKey(objItem)
        End If
    Next
    'kurz warten das die Regeln angewendet wurden  
    pause 1
    'Rekursive Funktion um alle Ordner nach den IDs zu durchsuchen  
    parseFolder startFolder, colPRIds
    
End Sub

'Rekursive Prozedur zumm Suchen in einer Ordnerstruktur  
Sub parseFolder(ByVal fldr As Folder, ByRef colMails As Collection)
    'Wenn der Ordner Mailitems enthält  
    If fldr.DefaultItemType = olMailItem Then
        'für jede ID in der Collection  
        For Each sID In colMails
            'Nur auf ungelesene Mails filtern  
            For Each itm In fldr.items.Restrict("[UNREAD] = True")  
                'wenn die ID in der Collection mit der des ITEMS übereinstimmt ...  
                If getPRSearchKey(itm) = sID Then
                    MsgBox "Die neue Mail mit dem Subject '" & itm.Subject & "' liegt jetzt im Ordner " & itm.Parent.FolderPath  
                End If
            Next
        Next
    End If
    'Prozedur ruft sich eslbst für alle Unterordner erneut auf  
    For Each subfolder In fldr.Folders
        parseFolder subfolder, colMails
    Next
End Sub

'Funktion die die MAPI Eigenschaft **PR_SEARCH_ID** einer Mail extrahiert  
Function getPRSearchKey(ByVal m As MailItem)
    getPRSearchKey = m.PropertyAccessor.BinaryToString(m.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x300B0102"))  
End Function

'Pause-Prozedur  
Sub pause(t As Integer)
    start = Timer
    Do While Timer < start + t
        DoEvents
    Loop
End Sub
Viel Erfolg
Grüße Uwe
bigfudge
bigfudge 28.09.2014 um 13:59:15 Uhr
Goto Top
Wow, unglaublich wie viel Aufwand du in diese Frage steckst, dafür reicht ein Dankeschön nicht ;) ! Ich werde mir das im Laufe des Tages mal sehr genau ansehen. Schätze aber die sehr viel einfachere Lösung wird sein, falls es Regeln gibt die genau die Mails betreffen mit welchen ich arbeiten möchte, diese zu deaktivieren.

Ich melde mich spätestens Montag nochmal und berichte wie das ganze ausgeht bzw. ausgegangen ist.

Grüße, fudge
bigfudge
bigfudge 29.09.2014 aktualisiert um 10:40:20 Uhr
Goto Top
Ich habe neue Infos zu meiner Frage. Wie es sich herausstellte, werden auf dem betroffenen Rechner die Mails, welche ich verarbeiten will alle über eine Regel in einen bestimmten Ordner verschoben.

Ich habe das ganze dann mal so angepasst (Inbox.Parent ersetzt):

Set Inbox = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Folders("NameDesOrdners")   

Scheint auch wunderbar zu funktionieren, würdest du hier eventuell noch eine Pause o.Ä. hinzufügen?

Ich hatte mir aus einem anderen Thread von dir (finde ich gerade nicht mehr) ein kleines Skript zu einem Button kopiert der in der Toolbar erstellt und über eine Methode getoggled wird. Soll wie auch in dem Thread zum ein-/ausschalten des Macros dienen.

Funktioniert eigentlich auch, mir ist nur eine etwas störende Sache aufgefallen. Wenn ich Outlook schließe und der Button auf End steht (also Start ist aktiv = Skript läuft), Outlook anschließend neustarte (Button steht immer noch auf End), dann funktioniert das Macro nicht mehr. Toggle ich kurz neu (End, Start) funktioniert alles wie gewohnt.

Fällt dir dazu zufällig was ein? Hier kurz der Code (von mir ein bisschen angepasst), falls du dich daran nicht erinnerst.

'Setting up button in toolbar  
Private Sub Application_Startup()

    Dim menueBar As CommandBar, commandButton As CommandBarButton
    Set menueBar = ActiveExplorer.CommandBars("Standard")  
    Set commandButton = menueBar.FindControl(Type:=msoControlButton, Tag:="Toggle")  
    If commandButton Is Nothing Then
        Set commandButton = menueBar.Controls.Add(msoControlButton)
        With commandButton
            .Tag = "Toggle"  
            .Caption = "Start"  
            .Visible = True
            .OnAction = "Toggle"  
        End With
    End If
    Set menueBar = Nothing
    Set commandButton = Nothing
End Sub



'to start/end the newmailex event  
Public start As Boolean
 
'toggling the button in the toolbar  
Sub Toggle()
    Dim commandButton As CommandBarButton, menueBar As CommandBar
    
    Set menueBar = ActiveExplorer.CommandBars("Standard")  
    Set commandButton = menueBar.FindControl(Type:=msoControlButton, Tag:="Toggle")  
    
    If Not commandButton Is Nothing Then
    
        If start Then
            start= False
            commandButton.Caption = "Start"  
        
        Else
            start= True
            commandButton.Caption = "End"  
       End If
    End If
    
    Set menueBar = Nothing
    Set commandButton = Nothing
    
End Sub

EDIT: Habe beim ApplicationStartup Event nach dem ersten Set commandButton diese Zeile hier eingefügt, scheint zu funktionieren:

 If commandButton.Caption = "Deactivate" Then  
    active = True
    End If 
colinardo
colinardo 29.09.2014 um 10:41:15 Uhr
Goto Top
'Setting up button in toolbar  
Private Sub Application_Startup()

    Dim menueBar As CommandBar, commandButton As CommandBarButton
    Set menueBar = ActiveExplorer.CommandBars("Standard")  
    Set commandButton = menueBar.FindControl(Type:=msoControlButton, Tag:="Toggle")  
    If commandButton Is Nothing Then
        Set commandButton = menueBar.Controls.Add(msoControlButton)
        With commandButton
            .Tag = "Toggle"  
            .Caption = "Start"  
            .Visible = True
            .OnAction = "Toggle"  
        End With
    else
       commandButton.Caption = "Start"  
    End If
    Set menueBar = Nothing
    Set commandButton = Nothing
End Sub
bigfudge
bigfudge 29.09.2014 um 14:25:53 Uhr
Goto Top
Ich bins nochmal.. wollte gerade das Tool mit einem Kollegen testen und nun stellte sich heraus, dass er Outlook 2010 hat und nicht wie Anfangs abgeklärt 2007.

Bringt das viele Änderungen mit sich? Haben es einfach mal probiert aber der Button wird logischerweise nicht erstellt, da man dort diese RibbonView hat und keine Toolbar. (Vllt. wird er ja sogar erstellt, ich sehe ihn nur nicht)

Bringt die Anpassung an 2010 große Änderungen mit sich?

Grüße,
fudge
colinardo
colinardo 29.09.2014 aktualisiert um 14:39:47 Uhr
Goto Top
Zitat von @bigfudge:
Bringt das viele Änderungen mit sich? Haben es einfach mal probiert aber der Button wird logischerweise nicht erstellt, da man dort diese RibbonView hat und keine Toolbar. (Vllt. wird er ja sogar erstellt, ich sehe ihn nur nicht)
doch der befindet sich in diesem Fall dann auf dem Tab Add-Ins. Wenn dieser Tab nicht sichtbar ist muss du ihn erst einblenden. Rechtsklick > Menüband anpassen
Bringt die Anpassung an 2010 große Änderungen mit sich?
Für Verteilung auf unterschiedliche Systeme würde ich ein richtiges COM oder VSTO-Addin daraus schreiben, mit VBA lässt sich das Ribbon nicht vernünftig programatisch steuern, das geht nur mit einem richtigen Add-In.

Ansonsten kannst du auch selber einen Button auf dem Ribbon erstellen und diesem halt eine Sub zuweisen die dann je nach Status der Public Variablen diese umschaltet und via MSGBOX eine Meldung ausgibt ob die Funktion aktiviert oder deaktiviert wurde.
bigfudge
bigfudge 29.09.2014 um 14:45:50 Uhr
Goto Top
Ah, also das müsste dann direkt so laufen? Dann habe ich das Tab womöglich grade nicht gesehen.

COM oder VSTO-Addin wäre mit Sicherheit die schönste Variante, aber da das Makro vorerst nur auf einem Rechner laufen soll ist das noch nicht nötig.

Danke!
bigfudge
bigfudge 30.09.2014 aktualisiert um 10:38:19 Uhr
Goto Top
kleine Frage noch face-smile. Wie komme ich an Ordner die auf der selben Ebene wie die Inbox liegen?

 Set Inbox = Application.GetNamespace("MAPI").Folders("xxx")   

funktioniert leider nicht :D

Sorry habs mit dem normalen Pfad zur Inbox (DefaulltFolderInbox) dannach .Parent.Folders("...") gelöst.
colinardo
colinardo 30.09.2014 aktualisiert um 10:40:55 Uhr
Goto Top
Zitat von @bigfudge:
kleine Frage noch face-smile. Wie komme ich an Ordner die auf der selben Ebene wie die Inbox liegen?
Set folder = Application.Session.Stores("user@domain.de").GetRootFolder.Folders("OrdnerXYZ")
oder
Set folder = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Parent.Folders("OrdnerXYZ")
bigfudge
bigfudge 30.09.2014 um 13:58:26 Uhr
Goto Top
Danke! Dann lag ich ja gar nichtmal so falsch wobei die erste Variante wohl etwas schöner ist ;). Eine letzte Frage: Ist es möglich auch auf Webmail Ordner (?) so wurde mir das am Telefon erklärt zuzugreifen?

Habe das nur kurz auf seinem Bildschirm gesehen, er hatte in den Favoriten mehrere Ordner an denen so ein blauer Doppelpfeil dran war, schätze mal die werden irgendwie online synchronisiert.

Grüße,
fudge
colinardo
colinardo 30.09.2014 aktualisiert um 14:04:38 Uhr
Goto Top
Zitat von @bigfudge:
Eine letzte Frage:
hatten wir das oben nicht schon zwei, drei mal ?
ist so langsam Off-Topic
Habe das nur kurz auf seinem Bildschirm gesehen, er hatte in den Favoriten mehrere Ordner an denen so ein blauer Doppelpfeil dran war, schätze mal die werden irgendwie online synchronisiert.
Die Favoriten verlinken ja nur auf einen anderen Ordner in eine Store, er muss halt lokal erreichbar sein.