Im ersten Teil dieser Beitragsreihe haben wir die Grundlagen geschaffen, um die E-Mails aus den verschiedenen Ordnern von Outlook zu importieren. Im zweiten Teil schauen wir uns das notwendige Datenmodell an und schreiten zur Tat: Die E-Mails aus den ausgewählten Outlook-Ordnern sollen importiert und den einzelnen Kunden zugeordnet werden.
Wenn Sie die E-Mails von Kunden importieren möchten, gibt es gleich mehrere Gründe, sich genauer um das Thema E-Mail-Adressen zu kümmern. Im einfachsten Fall haben Sie als Betreiber der Datenbank eine einzige E-Mail-Adresse, mit der Sie E-Mails an die Kunden verschicken. Über diese Adresse sollten optimalerweise auch die E-Mails der Kunden bei Ihnen eintreffen.
Andersherum wird jeder Kunde mit einer einzigen E-Mail-Adresse in Ihrer Datenbank gespeichert – zum Beispiel mit der E-Mail-Adresse, die dieser beim Absenden der Bestellung über einen Internetshop angegeben hat.
Dummerweise ist aber weder die eine noch die andere Annahme realitätsnah. Wenn Sie selbst tatsächlich nur eine einzige E-Mail-Adresse verwenden, sind Sie fein raus – dann kann der Kunde sich ja nur unter dieser Adresse bei Ihnen melden. Aber wenn Sie auch nur eine Adresse etwa namens info@minhorst.com und eine namens support@minhorst.com betreiben, können Sie davon ausgehen, dass es dem Kunden erstmal egal ist, wohin die Mail geht – Hauptsache, die Domain stimmt. Dementsprechend gibt es ja unter Outlook sogar schon die Möglichkeit, für jede einzelne Adresse eine eigene .pst-Datei zu betreiten.
Andersherum hat vielleicht nicht die Mehrzahl der Kunden mehrere E-Mail-Adressen, aber selbst wenn es nur ganz wenige sind, müssen Sie diesen Fall berücksichtigen (zum Beispiel eine private und eine berufliche E-Mail-Adresse – und die wirft man erfahrungsgemäß schnell mal durcheinander …).
Also müssen Sie wohl oder übel nicht nur für sich selbst, sondern auch für die Kunden mehrere E-Mail-Adressen prüfen, wenn es um die Zuordnung der E-Mails zum entsprechenden Kunden geht.
Wie aber läuft der Abgleich der vielen E-Mails in Outlook mit den vorhandenen Kunden überhaupt ab Hier gibt es zunächst zwei Möglichkeiten: Die erste geht vom Optimalfall aus und nimmt an, dass alle E-Mails, die Ihnen von Kunden zugesendet wurden, sich im oder unterhalb des Ordners Posteingang befinden. Dementsprechend sollten alle E-Mails, die Sie verschickt haben, im Ordner Gesendete Objekte enthalten sein.
Dies ist aber in vielen Fällen nicht gegeben, weil Sie vielleicht bereits selbst ein wenig Struktur in in Ihre Mailordner gebracht haben und etwa alle E-Mails zum Thema Support oder zum Thema Buchhaltung in einem Ordner gespeichert haben – unabhängig davon, ob es sich um Ihre eigenen E-Mails handelt oder um die E-Mails Ihrer Kunden.
Schauen wir uns zunächst an, wie die Beispiellösung die E-Mail-Adressen des Benutzers selbst verwaltet. Dazu gibt es zwei Tabellen – eine Optionentabelle namens tblOptionen und eine Tabelle namens tblEMailAdressen, die alle E-Mail-Adressen der kompletten Lösung speichert.
Die Tabelle tblOptionen enthält derzeit nur ein einziges Feld namens StandardEMailAdresseID. Dieses ist ein Fremdschlüsselfeld und mit dem Feld EMailAdresseID der Tabelle tblEMailAdressen verknüpft. Diese Tabelle wiederum enthält das entsprechende Primärschlüsselfeld, das Feld EMailAdresse zum Speichern der E-Mail-Adresse und ein Feld namens KundeID, mit dem eine E-Mail-Adresse einem Kunden zugewiesen werden kann. Die beiden Tabellen und deren Beziehung sehen in der Übersicht wie in Bild 1 aus.
Bild 3: Das Formular frmOptionen in der Entwurfsansicht
Der Benutzer der Anwendung soll nun mehrere E-Mail-Adressen eingeben und eine davon als seine Standard-E-Mail-Adresse festlegen können. Diese soll standardmäßig beim Versenden von E-Mails eingesetzt werden. Dazu stellt die Lösung das Formular frmOptionen mit dem Unterformular sfmEMailAdressen zur Verfügung. Im Unterformular kann der Benutzer alle verfügbaren E-Mail-Adressen eintragen, mit dem Kombinationsfeld im oberen Bereich wählt er die aktuelle Standardadresse aus (s. Bild 2).
Bild 1: Beziehungsfenster mit den beiden Tabellen tblOptionen und tblEMailAdressen
Das Hauptformular frmOptionen hat keine eigene Datenherkunft. Es enthält im oberen Bereich ein Kombinationsfeld namens cboEMailAdresseID und darunter ein Unterformular (s. Bild 3).
Bild 2: Verwalten der eigenen E-Mail-Adressen
Das Kombinationsfeld verwendet eine Abfrage auf Basis der Tabelle tblEMailAdressen als Datenherkunft, die alle Datensätze liefert, deren Fremdschlüsselfeld KundeID den Wert NULL enthält – also alle E-Mail-Adressen, die nicht anderweitig mit einem Kunden verknüpft sind (s. Bild 4).
Bild 4: Datensatzherkunft des Kombinationsfeldes zur Auswahl der Standard-E-Mail-Adresse
Das im Hauptformular befindliche Unterformular heißt sfmEMailAdressen und verwendet die gleiche Datenherkunft wie das Kombinationsfeld cboEMailAdresseID. Der Benutzer kann hier E-Mail-Adressen einfügen und die vorhandenen Einträge bearbeiten und löschen. Bei jeder Aktion sollen die Ônderungen jedoch in die Datenherkunft des Kombinationsfeldes cboEMailAdressen übertragen werden. Dazu legen Sie für das Ereignis Nach Aktualisieren des Unterformulars die folgende Ereignisprozedur an:
Private Sub Form_AfterUpdate() Me.Parent!cboStandardEMailID.Requery End Sub
Die Requery-Methode sorgt jeweils für die Aktualisierung der Datensatzherkunft des Kombinationsfeldes.
Kunden verwalten
Die Verwaltung der Kunden soll hier im Hintergrund stehen, es geht schließlich um die Kommunikation. Deshalb haben wir das Datenmodell für die Kundentabelle etwas knapper gehalten (s. Bild 5). Hier sind die Eigenschaften des Fremdschlüsselfeldes StandardEMailAdresseID sichtbar. Ach, das Feld kennen Sie schon Stimmt: Neben dem Benutzer soll auch jeder Kunde eine Standard-E-Mail-Adresse erhalten, und die wird mit diesem Feld ausgewählt.
Bild 5: Entwurfsansicht der Kundentabelle
Die Datensatzherkunft und die übrigen Nachschlageeigenschaften haben wir nun schon eingestellt, damit das Feld beim Anlegen im Formular gleich als Kombinationsfeld ausgeführt wird. Später wird die Abfrage mit den E-Mail-Adressen natürlich nach dem Wert des Feldes KundeID gefiltert.
Die Tabelle enthält noch ein Feld namens AnredeID, mit dem die Anrede des jeweiligen Kunden eingestellt werden kann. Die möglichen Werte speichert die Tabelle tblAnreden, die Auswahl erfolgt wiederum per Kombinationsfeld.
Formular zur Kundenverwaltung
Das Formular zur Verwaltung der Kunden verwendet die Tabelle tblKunden als Datenherkunft und zeigt alle Felder dieser Tabelle an.
Daneben enthält das Formular genau wie das Formular frmOptionen ein Unterformular, mit dem Sie die E-Mail-Adressen für den Kunden eintragen können. Genau genommen verwenden Sie dort fast genau das gleiche Formular als Unterformular. Das hier verwendete heißt sfmEMailAdressenKunden. Ziehen Sie das Unterformular in das Hauptformular und prüfen Sie, ob die Eigenschaften Verknüpfen von und Verknüpfen nach automatisch von Access wie in Bild 6 eingerichtet wurden.
Bild 6: Prüfen der Verknüpfung von Haupt- und Unterformular
Der wesentliche Unterschied vom Unterformular sfmEMailAdressenKunden zum Formular sfmEMailAdressen ist die Datenherkunft. Das Unterformular zur Anzeige der E-Mail-Adressen des Kunden verwendet die Abfrage aus Bild 7 als Datenherkunft. Der entscheidende Unterschied ist hier, dass diese Abfrage nicht die Datensätze der Tabelle tblEMailAdressen liefert, deren Feld KundeID leer ist, sondern genau die übrigen Datensätze – nämlich jene, die im Feld KundeID mit einem Wert ausgestattet sind.
Bild 7: Datenherkunft des Unterformulars sfmEMailAdressenKunden
Auch für das Unterformular sfmEMailAdressenKunden legen Sie zwei Ereignisprozeduren an, und zwar für die Ereignisse Nach Aktualisierung und Beim Löschen. Die folgende Prozedur wird nach dem Aktualisieren eines Datensatzes ausgelöst, also beim Neuanlegen oder beim Ôndern eines bestehenden Datensatzes:
Private Sub Form_AfterUpdate() Me.Parent!cboStandardEMailID.Requery If Me.Recordset.RecordCount = 1 Then Me.Parent!cboStandardEMailID = Me.Parent!cboStandardEMailID.ItemData(0) End If End Sub
Die Prozedur aktualisiert zunächst die Datenherkunft des Kombinationsfeldes cboStandardEMailID im Hauptformular. Dann prüft sie, ob der geänderte Datensatz der einzige Datensatz im Unterformular ist, und stellt gegebenenfalls das Kombinationsfeld im Hauptformular auf diesen Datensatz ein. Dies ist hilfreich, wenn der Benutzer beispielsweise gerade den ersten Datensatz im Unterformular angelegt hat. Dieser wird dann direkt als Standard-E-Mail-Adresse angelegt.
Wenn der Benutzer einen oder mehrere Einträge im Unterformular löscht, löst dies die folgende Prozedur aus:
Private Sub Form_Delete(Cancel As Integer) Me.Parent!cboStandardEMailID.Requery If Me.Parent!cboStandardEMailID = Me!EMailAdresseID Then If Me.Recordset.RecordCount = 0 Then Me.Parent!cboStandardEMailID = Null Else Me.Parent!cboStandardEMailID = Me.Parent!cboStandardEMailID.ItemData(0) End If End If Me.Parent.Requery End Sub
Auch diese Prozedur aktualisiert zunächst die Datenherkunft des Kombinationsfeldes cboStandardEMailID im Hauptformular. Dann prüft sie, ob das Kombinationsfeld im Hauptformular die soeben gelöschte E-Mail-Adresse angezeigt hat, und aktualisiert gegebenenfalls das Kombinationsfeld im Hauptformular. Wurde der letzte Datensatz im Unterformular gelöscht, leert die Prozedur das Kombinationsfeld cboStandardEMailID im Hauptformular, anderenfalls stellt sie dieses auf den ersten verfügbaren Wert ein.
Auch das Hauptformular statten wir noch mit zwei Ereignisprozeduren aus. Die erste wird durch das Ereignis Beim Anzeigen ausgelöst. Sie sorgt schlicht und einfach dafür, dass das Kombinationsfeld cboStandardEMail beim Anzeigen eines Datensatzes nur die E-Mails zur Auswahl anbietet, die auch mit dem aktuellen Kunden verknüpft sind:
Private Sub Form_Current() Me!cboStandardEMailID.RowSource = "SELECT EMailAdresseID, EMailAdresse " _ "FROM tblEMailAdressen WHERE KundeID = " & Me!KundeID End Sub
Die zweite Ereignisprozedur wird ausgelöst, wenn der Benutzer einen noch nicht vorhandenen Eintrag in das Kombinationsfeld cboStandardEMailID eingibt:
Private Sub cboStandardEMailID_NotInList(NewData As String, Response As Integer) Dim db As DAO.Database Set db = CurrentDb db.Execute "INSERT INTO tblEMailAdressen(EMailAdresse, KundeID) VALUES(''" _ & NewData & "'', " & Me!KundeID & ")" Me!sfmEMailAdressen.Form.Requery Set db = Nothing Response = acDataErrAdded End Sub
Die Prozedur füllt ein Database-Objekt mit einem Verweis auf die aktuelle Datenbank und führt mit dessen Execute-Anweisung eine INSERT INTO-Aktionsabfrage aus, die einen neuen Datensatz zur Tabelle tblEMailAdressen hinzufügt. Diese wird mit der frisch eingegebenen E-Mail-Adresse und dem Wert des Feldes KundeID des aktuellen Kundendatensatzes im Hauptformular gefüllt.
Behandlung eingelesener E-Mails
Kommen wir zum Einlesen der E-Mails, die aufgrund der Absender- oder Empfängeradresse mit einem der Kunden in Zusammenhang gebracht werden können. Diesen Vorgang haben wir durch die Bereitstellung eines Formulars zum Auswählen der zu durchsuchenden Outlook-Ordner bereits gut vorbereitet.
Wir müssen nun noch eine Prozedur bereitstellen, welche in mehr oder weniger regelmäßigen Abständen die kundenrelevanten E-Mails aus Outlook importiert und in der Datenbank dem Kunden zuordnet. Dabei stellt sich zunächst die folgende Frage: Was geschieht mit einer einmal in die Datenbank eingelesenen E-Mail in Outlook Es gibt verschiedene Szenarien:
- Die E-Mail wird nach dem Einlesen schlicht und einfach gelöscht. Warum sollte man diese auch doppelt vorhalten
- Die E-Mail wird in einen speziellen Ordner verschoben, der alle E-Mails enthält, die in die Datenbank eingelesen wurden.
- Die E-Mail verbleibt an Ort und Stelle. Man sollte diese jedoch zumindest in geeigneter Art und Weise markieren – erstens, damit man beim Lesen der übrigen E-Mails, die nicht einer Kundenbeziehung zugeordnet werden können, nicht immer wieder auf bereits in die Datenbank importierte E-Mails stößt. Und zweitens muss man auch irgendwie dafür sorgen, dass E-Mails nur ein einziges Mal in die Datenbank eingelesen werden.
Welche Möglichkeiten gibt es, die Mails zu markieren und somit zu verhindern, dass diese erneut eingelesen werden beziehungsweise sowohl in der Datenbank als auch in Outlook vom Empfänger bearbeitet werden Die erste ist eine optische: Dabei erstellen Sie in Outlook eine eigene Kategorie für eingelesene E-Mails und weisen diese den entsprechenden E-Mails zu. In Outlook werden diese mit einer entsprechenden Farbe markiert (s. Bild 8).
Bild 8: Die gelb markierten E-Mails wurden bereits in die Datenbank eingelesen
Wenn man sich vorstellt, dass die bereits eingelesenen E-Mails zwar markiert werden, jedoch im Ordner Posteingang verbleiben, ist bezüglich der Übersichtlichkeit in Outlook nur wenig gewonnen. Besser wäre es tatsächlich, die eingelesenen E-Mails auch gleich zu löschen oder in einen anderen Ordner zu verschieben. Das Löschen scheint etwas rabiat, also verschieben wir diese in einen speziell für bereits eingelesene E-Mails angelegten Ordner.
Flexibles Einlesen
Damit Sie die vorhergehenden Varianten beim Einlesen alle einsetzen können, haben wir die entsprechende Prozedur EMailsEinlesen (s. Listing 1) mit zwei entsprechenden Parametern ausgestattet:
- strZielordner: Erwartet den Ordner, in den die eingelesenen E-Mails verschoben werden sollen, zum Beispiel \\Outlook\Posteingang\Test
- strKategorie: Erwartet den Namen der Kategorie, mit dem die eingelesenen E-Mails versehen werden sollen.
Listing 1: Einlesen von E-Mails in die Tabelle tblKommunikation
Public Sub EMailsEinlesen(Optional strZielordner As String, Optional strKategorie As String) Dim db As DAO.Database Dim rstMailordner As DAO.Recordset, rstMails As DAO.Recordset Dim objFolder As Outlook.MAPIFolder, objZielordner As Outlook.Folder Dim obj As Object, objMail As Outlook.MailItem Dim objOutlook As Outlook.Application Dim strMailordner As String, strEmail_From As String, strEMail_To As String Dim lngKundeID As Long, i As Integer Set objOutlook = New Outlook.Application Set db = CurrentDb Set rstMailordner = db.OpenRecordset("SELECT * FROM tblMailordner", dbOpenDynaset) If Len(strZielordner) > 0 Then Set objZielordner = GetFolder(objOutlook, strZielordner, True) End If Set rstMails = db.OpenRecordset("tblKommunikation", dbOpenDynaset) If Len(strKategorie) > 0 Then If KategoriePruefen(objOutlook, strKategorie) = False Then MsgBox "Richten Sie zunächst die Kategorie ''" & strKategorie & "'' unter Outlook ein." Exit Sub End If End If Do While Not rstMailordner.EOF strMailordner = rstMailordner!Mailordner Set objFolder = GetFolder(objOutlook, strMailordner, False) For i = objFolder.Items.Count To 1 Step -1 Set obj = objFolder.Items(i) If TypeName(obj) = "MailItem" Then Set objMail = obj strEmail_From = objMail.SenderEmailAddress strEMail_To = Replace(objMail.To, "''", "") lngKundeID = Nz(DLookup("KundeID", "tblEmailadressen", "(EMailadresse = ''" _ & strEmail_From & "'' OR EMailadresse = ''" & strEMail_To & "'') AND KundeID IS NOT NULL"), 0) If lngKundeID > 0 And Einlesen(objMail, strZielordner, strKategorie) Then With rstMails .AddNew !EMail_From = strEmail_From !EMail_To = strEMail_To !Betreff = Replace(objMail.Subject, "''", "''''") !Inhalt = Replace(objMail.Body, "''", "''''") !DatumZeit = objMail.SentOn !KundeID = lngKundeID !EntryID = objMail.EntryID If Len(strKategorie) > 0 Then objMail.Categories = objMail.Categories & ";" & strKategorie End If objMail.Save If Not objZielordner Is Nothing Then objMail.Move objZielordner End If .Update End With End If End If Next i rstMailordner.MoveNext Loop Set objOutlook = Nothing Set db = Nothing End Sub