Kundenkommunikation per E-Mail verwalten, Teil 2

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.

pic007.png

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).

pic005.png

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).

pic006.png

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).

pic008.png

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.

pic009.png

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.

pic010.png

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.

pic011.png

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).

pic012.png

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

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

TestzugangOder bist Du bereits Abonnent? Dann logge Dich gleich hier ein. Die Zugangsdaten findest Du entweder in der aktuellen Print-Ausgabe auf Seite U2 oder beim Online-Abo in der E-Mail, die Du als Abonnent regelmäßig erhältst:

Schreibe einen Kommentar