Outlook Events - handling, diverse Problematiken Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
Frosti
Posts: 426
Joined: 27 Oct 2017, 14:30
Contact:

Outlook Events - handling, diverse Problematiken

Post by Frosti » 07 Aug 2020, 11:38

An folgendem Skript probiere ich schon länger herum. Heute habe ich es erstmals geschafft das ich verstanden habe wie ich an dem Event ein paar Daten entlocken kann.

Code: Select all

#NoEnv
#Persistent
SetBatchLines, -1
CoordMode, ToolTip, Screen

; Instantiate the event handler class.
EMail := new OutlookApplicationEvents()

return  ; End of Auto-execute section.

Esc::
	EMail.Quit()
return

^!l::Reload

; Basic Outlook events class. Can be connected to an Outlook Application object.
class OutlookApplicationEvents {

	__New(olApp := "")    {

		; If nothing was passed to this method, then use the active instance of Outlook. This will throw an error if
		; Outlook is not running.
		if (olApp = "")
			try olApp := ComObjActive("Outlook.Application")

		If IsObject(olApp)
			TrayTip, % "Outlook Eventhandler", % "COM-Connection established", 1

		; Store Outlook application object for later use (optional).
		this.olApp := olApp

		; Connect Outlook Application object events to this instance.
		ComObjConnect(this.olApp, this)

	}

	__Call(Event, Args*) {

			msg := "--- >>>> " A_Hour ":" A_Min ":" A_Sec " - Event: " Event " <<<< "

			if !IsFunc( this[Event] ) {             ; If this event does not correspond to a method...
				msg .= ": Event is not supported"             ; Display the event name.
			}

			For idx, param in Args
			{
					;str .= idx ":`n"
					If IsObject(param) {
						For key, val in param
							str .= "`t" key ": " val "`n"
					} else {
							str .= "`t" param "`n"
					}
			}

			SciTEOutput(msg "`nArgs:`n" str)

	}

	ItemLoad() {

			SciTEOutput("Event (Itemload): " this.olApp.CurrentItem.name)
			t:= ""
			For key, val in this
				t.= key ": " val "`n"
			SciTEOutput(t)

	}

	NewMail() {

			;For key, val in this
			;	SciTEOutput("`t" key ": " (IsObject(val) ? " is object": val))

			Subject 	:= this.Subject
			SciTEOutput("~" this.Body)
			SciTEOutput("~" this.SendUsingAccount)
			SciTEOutput("~" Subject)

			attachments := this.attachments
			Loop % Attachments.Count
			{
				thisattachment := attachments.Item(A_Index)
				SciTEOutput("attachment: " thisattachment.DisplayName)

			}

	}

	Send(Cancel) 	{

		if InStr(Email.Body, "stupid") {
			MsgBox The new company policy is to NOT call our customers "stupid".`nPlease rephrase your email.
			return ComObject(0xB,0)
		}

	}

	ExtractAttachment(folderName, EmailSubject, attachmentname, PathToSaveTo) {

		attachmentname := "i)" attachmentname
		olApp := ComObjActive("Outlook.Application")
		outlooknamespace := olApp.GetNameSpace("MAPI")
		folder := outlooknamespace.Folders(folderName)

		Loop % folder.items.count {

			email := folder.items.Item(A_Index)
			if(InStr(email.Subject, EmailSubject)) 	{

				attachments := email.Attachments
				Loop % Attachments.Count		{

						thisattachment := attachments.Item(A_Index)
						if RegExMatch(thisattachment.DisplayName , attachmentname )	{

								Fullpath := pathtosaveto "\" thisattachment.DisplayName
								thisattachment.SaveAsFile(FullPath)
								return thisattachment.DisplayName ; disable this line and it will extract every attachments and same name attachment get renames,

							}
				}
			}
		}

		msgbox, no email found Having Subject = %EmailSubject% `n specially having attachment with name = %attachmentname%
	}

	Quit()     {  ; Occurs when Outlook begins to close.
		ComObjConnect(this.olApp)                    ; Disconnect application events.
		ExitApp                                                   ; Exit this script.
	}
}

SciTEOutput(Text:="", Clear=false, LineBreak=true, Exit=false) {

		static SCI_GETLENGTH	:= 2006, SCI_GOTOPOS	:= 2025

		try
			SciObj := ComObjActive("SciTE4AHK.Application")           	;get pointer to active SciTE window
		catch
			return                                                                            	;if not return

		; move Caret to end of output window
		ControlSend, Scintilla2, {LControl Down}{End}{LControl Up} , % "ahk_id " SciObj.SciTEHandle

		If Clear || (StrLen(Text) = 0) {
			SendMessage, SciObj.Message(0x111, 420)                   	;If clear=true -> Clear output window
			return
		}

		SciObj.Output(Text (LineBreak ? "`r`n": ""))                            	;send text to SciTE output pane

		If Exit {
			MsgBox, 36, Exit App?, Exit Application?                         	;If Exit=1 ask if want to exit application
			IfMsgBox,Yes, ExitApp                                                       	;If Msgbox=yes then Exit the appliciation
		}

}

Was funktioniert ist das ich nun weiß wer der Absender ist. Der Betreff und der Inhalt der Mail gelesen werden.
Allerdings habe ich keine Ahnung wie ich erkennen kann ob die eingetroffene EMail einen Anhang enthält.

Code: Select all

NewMail() {
	For key, val in this
		SciTEOutput("`t" key ": " (IsObject(val) ? " is object": val))
	....
Hier habe ich mir versuchsweise den Inhalt des Objektes ausgeben lassen.
Dieser enthält olApp, logischerweise ein Objekt und die Daten SendUsingAccount, Body, Subject, To. Mehr allerdings nicht.

Und an diesem Punkt komme ich nicht weiter.
Ich könnte jetzt das Event (Aufruf der Funktion) als Trigger nutzen und jedesmal das Outlook.Folders-Objekt durchsuchen.
Nun erhoffe ich mir von Euch allerdings mehr Einblicke in das COM-Konzept von Outlook. Ich hoffe das wirkt nicht zu frech auf Euch.

Und da ich mich selbst nicht als allzu frech empfinde, mache ich die Beantwortung meiner Frage noch umfangreicher.

Die funktionierende Ausgabe der key:value Daten im Event-Objekt hat mich auf die Idee gebracht, dann auch noch für alle Events bei __Call(Event, Args*) { die erhaltenden variadischen Argumente ausgeben zu lassen.
Outlook übergibt hier in manchen Fällen auch Objekte, deren Namen ich allerdings nicht ermitteln kann.
Deshalb habe ich versucht zumindestens die key:value's zu ermitteln.
Allerdings ist das dann völlig ergebnislos geblieben. Da hab ich wohl etwas nicht verstanden.

Code: Select all

For idx, param in Args
{
		If IsObject(param) {
			For key, val in param
 				str .= "`t" key ": " val "`n"
		} else {
			str .= "`t" param "`n"
		}
}
Sinn der Übung ist mein Wunsch neue Mails zu filtern, aufzuarbeiten und dann alles über Telegram an mich selbst zu senden. Ich möchte nur noch ein Programm für den Nachrichteneingang auf der Arbeit haben.
Last edited by Frosti on 22 Aug 2020, 10:52, edited 1 time in total.

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Outlook Events - handling, diverse Problematiken

Post by just me » 08 Aug 2020, 05:14

Moin,

ich verwende Outlook nicht, aber ich habe versucht, mich etwas einzulesen (https://docs.microsoft.com/de-de/office/vba/api/overview/outlook). Klug bin ich dabei aber nicht geworden. Mir ist eher unklar, weshalb Du überhaupt vernünftige Daten bekommst.

Das NewMail Ereignis übergibt nach der MS-Doku keine Parameter. Auf AHK-Seite verbirgt sich innerhalb der Methode in This das umschließende AHK-Objekt. Das kennt die in der __New() Methode hinterlegte Eigenschaft olApp mit einem Verweis auf das Outlook-Objekt. Und das war's dann eigentlich auch schon. Woher eine EIgenschaften wie OutlookApplicationEvents.Body oder OutlookApplicationEvents.Subject stammen sollen, verstehe ich nicht.

Ich habe während meiner Recherchen ein paar Beispiele dafür gefunden, dass neue Mails über das Ereignis NewMailEx abgegriffen wurden. Da hat man weinigstens eine MailID.

Hast Du Dein Skript aus Beispielen im AHK-Forum aufgebaut?


User avatar
Frosti
Posts: 426
Joined: 27 Oct 2017, 14:30
Contact:

Re: Outlook Events - handling, diverse Problematiken

Post by Frosti » 08 Aug 2020, 08:06

Ist tatsächlich einem Forumbeispiel entnommen. Dort hat er aber nur ein Beispiel für das Unterbrechen eines Send Events beschrieben. Woher die Daten kommen und da sie auch nur Teile enthalten, ist mir natürlich auch unklar. Es hat anfänglich auch nicht immer geklappt. Es könnte auch sein das es meine eigenen Daten sind. In der nicht mehr genutzten Version wollte ich mir die Arbeit des Versendens ersparen und habe das Skript eine Mail versenden lassen um diese anschliessend zu empfangen. Allerdings habe ich dies wieder herausgenommen. Das Skript wurde mehrfach beendet und gestartet und ich bekam immer noch Informationen. Schätze ich sollte überprüfen ob ich das ComObject richtig beendet habe.

Danke erstmal. Vielleicht hat ja irgendwann noch jemand eine Idee wie ich auf OutlookApplicationEvent zugreifen kann. Ich werde Deinen Hinweis in mein Skript aufnehmen. Vielleicht war es das schon.
Wenn es das war. Könnte das auch mit dem Attachmentlink von Bobo funktionieren.

Ich frage mich aber immer noch wie ich mit AHK die bei __Call eingehenden Parameter analysieren/untersuchen kann.

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Outlook Events - handling, diverse Problematiken

Post by just me » 08 Aug 2020, 08:37

An sich sollte das Eventobjekt arbeiten. Das Event NewMail ist allerdings eine reine Benachrichtigung ohne ergänzende Informationen. Man muss selbst versuchen, die auslösende Mail zu ermitteln.

NewMailEx macht es etwas einfacher, weil hier eine Mail-ID geliefert wird. Damit ist die Mail eindeutig identifiziert. Ich glaube, ich könnte Dir bei der Umsetzung helfen.

Wenn als __Call() Parameter Objekte übergeben werden, handelt es sich i.d.R. um COM-Objekte. Du kannst ja zunächst einmal versuchen, Informationen per ComObjType() zu bestimmen:

Code: Select all

Typ     := ComObjType(ComObject)
IName   := ComObjType(ComObject, "Name")
IID     := ComObjType(ComObject, "IID")
CName   := ComObjType(ComObject, "Class")  ; Requires [v1.1.26+]
CLSID   := ComObjType(ComObject, "CLSID")  ; Requires [v1.1.26+]
MsgBox, Typ: %Typ%`nInterface Name: %IName%`nInterface ID: %IID%`nClass Name: %CName%`nClass ID: %CLSID
Wichtiger finde ich aber den ersten Parameter mit dem Eventnamen. Darüber kannst Du in der Outlook-Doku die konkreten Parametereigenschaften ermitteln.

User avatar
Frosti
Posts: 426
Joined: 27 Oct 2017, 14:30
Contact:

Re: Outlook Events - handling, diverse Problematiken

Post by Frosti » 08 Aug 2020, 11:44

NewMailEx wird aus irgendwelchen Gründen nur bei jeder 6. bis 10. Mail als Event parametriert. So jedenfalls mein bescheidener Eindruck. Also muss ich wohl NewMail als Trigger nutzen. Outlook macht es einem leider nicht einfach. Meinem Eindruck nach hat Outlook ein z.T. anderes Konzept als der Rest des Officepaketes. Da ich die Mails von Outlook in 25 Kategorien/Ordner sortieren lasse, muss ich nun wohl doch jeden Ordner untersuchen.

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Outlook Events - handling, diverse Problematiken  Topic is solved

Post by just me » 09 Aug 2020, 05:55

Ok, dann probier mal das. Es sollte sich (theoretisch) bei allen Zugängen in der Inbox melden:

Code: Select all

#NoEnv
#Persistent
SetBatchLines, -1
ComObjError(0)
OL_App := ComObjActive("Outlook.Application")
If !IsObject(OL_App) {
   MsgBox, 16, Fehler!, Bitte vor dem Start des Skripts Outlook öffnen!
   ExitApp
}
ComObjError(1)
OL_Items := OL_App.GetNamespace("MAPI").GetDefaultFolder(6).Items ; olFolderInbox = 6
ComObjConnect(OL_Items, "Inbox_")
Return

Inbox_ItemAdd(Item) { ; docs.microsoft.com/en-us/office/vba/api/outlook.items.itemadd
   Tooltip, % "New Mail:`n`n"
            . "From: " . Item.SenderEmailAddress . "`n"
            . "Subject: " . Item.Subject
}
Ich habe das erst einmal ohne Klasse realisiert.

User avatar
Frosti
Posts: 426
Joined: 27 Oct 2017, 14:30
Contact:

Re: Outlook Events - handling, diverse Problematiken

Post by Frosti » 09 Aug 2020, 13:31

Ach danke für Deine Mühe. Ich werde das in den vorhandenen Code einpassen. Mal sehen was sich realisieren läßt und das dann hier darstellen.


WIE KRIEGE ICH DEN HAKEN FÜR SOLVED JETZT AUF just me's Antwort?
Last edited by Frosti on 10 Aug 2020, 06:48, edited 1 time in total.

User avatar
Frosti
Posts: 426
Joined: 27 Oct 2017, 14:30
Contact:

Re: Outlook Events - handling, diverse Problematiken

Post by Frosti » 10 Aug 2020, 06:47

Deine Variante funktioniert! Ich komme an alle Outlook Properties und insbesondere auch an .Attachments.Item(Nr).
Damit kann ich jetzt die schon im Forum vorhandenen Methodenaufrufe für das Speichern eines Anhangs anwenden.
Ich brauche auch keine Klasse. Ich hab die Klasse als Übungsaufgabe verwendet. Mal sehen wie weit ich als nächstes komme.
Danke

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Outlook Events - handling, diverse Problematiken

Post by just me » 10 Aug 2020, 08:49

Frosti wrote:WIE KRIEGE ICH DEN HAKEN FÜR SOLVED JETZT AUF just me's Antwort?
Weiß ich nicht, ist doch aber auch egal. ;)

User avatar
LuckyJoe
Posts: 335
Joined: 02 Oct 2013, 09:52

Re: Outlook Events - handling, diverse Problematiken

Post by LuckyJoe » 11 Aug 2020, 10:34

Hallo,
noch eine kleine Ergänzung: falls Outlook noch nicht gestartet wurde, dürfte es durch ComObjCreate erzeugt werden können, so dass die Abfrage auch lauten könnte:

Code: Select all

If !IsObject(OL_App) {
	OL_App := ComObjCreate("Outlook.Application")
	If !IsObject(OL_App) {
	   MsgBox, 16, Fehler!, ...
	   ExitApp
	}
}
Herzliche Grüße aus dem Rheinland
Lucky Joe

halweg
Posts: 93
Joined: 17 Apr 2018, 10:34
Location: Dresden

Re: [solved] Outlook Events - handling, diverse Problematiken

Post by halweg » 05 Jan 2021, 06:42

Ich häng mich noch mal kurz rein:

Man kann über das Outlook Objekt ja keine Outlook-VBA-Skripte fernstarten (im Unterschied z. B. zu Excel)
Leider ist das genau eine meiner häufigen Aufgabenstellungen, d. h. ich triggere aus AHK heraus diverse VBA Routinen.

Wäre es über das oben beschriebene Triggern von Outlook Events möglich, an Outlook aus AHK Parameter zu übergeben?
Momentan mache ich das nur über Tastenkombinationen und das ist natürlich sehr umständlich.
Ich hoffe, ihr versteht, was ich meine.

Besten Dank fürs Mitdenken im voraus.

Halweg

Post Reply

Return to “Ich brauche Hilfe”