Hi,
In meiner Applikation nutze ich zur zeit zum Versenden von Mails über Outlook eine Klasse, die ein Outlook.MailItem kapselt. Das Speichern der Mail beim Versenden wird dadurch bewerkstelligt, dass ich im Falle, dass ich einen Speicherungswunsch vermerkt habe, eigene Handler für das Send und das Close-Ereignis hinzufüge.
[highlight=vbnet]
Public Sub SaveOnSend(ByVal dstDirName As String, ByVal dstFileName As String, Optional ByVal UseTimeStamp As Boolean = True, Optional ByVal OwnSubfolder As Boolean = True)
If ok = False Then ShowInternalError("Fehlerhafter Aufruf von 'clsOutlookMail.SaveOnSend'.") : Return
If dstDirName = "" Or dstFileName = "" Then Return
If Not IO.Directory.Exists(dstDirName) Then
If Not DirectoryMake(dstDirName) Then Return
End If
activeSaveOnSend = True
Me.withTimeStamp = UseTimeStamp
Me.useSubfolder = OwnSubfolder
pdstDirName = dstDirName
pdstFileName = dstFileName
End Sub
Public Sub Display()
If ok = False Then ShowInternalError("Fehlerhafter Aufruf von 'clsOutlookMail.Display'.") : Return
If activeSaveOnSend Then
AddHandler m.Send, AddressOf m_Send
AddHandler m.Close, AddressOf m_Close
HandlerAdded = True
'clsOutlookMail-Objekt selbst sichern, dass es nicht bei GarbageCollection zerstört wird, bevor es gesendet wird
If mArr Is Nothing Then mArr = New ArrayList
mArr.Add(Me)
End If
m.Display()
Try
AppActivate(m.Subject & " - Nachricht (HTML)")
Catch ex As Exception
End Try
If Not activeSaveOnSend Then
EmailFreigeben()
End If
End Sub
Private Sub m_Send(ByRef Cancel As Boolean)
EmailSpeichern()
EmailFreigeben()
'kann anschließend im Fall einer GarbageCollection zerstört werden
mArr.Remove(Me)
End Sub
Private Sub m_Close(ByRef Cancel As Boolean)
'Problem, wenn Benutzer bei Sicherheits-Abfrage "Abbrechen" wählt; das ist nicht erkennbar
EmailFreigeben()
'kann anschließend im Fall einer GarbageCollection zerstört werden
mArr.Remove(Me)
End Sub
Private Sub EmailSpeichern()
If pdstDirName = "" Or pdstFileName = "" Then Return
If Not activeSaveOnSend Then Return
Dim d As String = pdstDirName & IIf(useSubfolder, "\" & "Emails", "")
If Not IO.Directory.Exists(d) Then
If Not DirectoryMake(d) Then ShowError("Fehler beim Zugrif auf Dateiordner" & vbCrLf & "'" & d & "'") : Return
End If
Dim f As String = IIf(withTimeStamp, Now.ToString("yyyy-MM-dd_HH-mm-ss") & "_", "") & pdstFileName & ".msg"
Try
m.SaveAs(d & "\" & f)
Catch ex As Exception
ShowError("Fehler beim Speichern der E-Mail unter" & vbCrLf & "'" & d & "'" & vbCrLf & "(" & ex.Message & ")")
End Try
End Sub
Private Sub EmailFreigeben()
If HandlerAdded Then
RemoveHandler m.Send, AddressOf m_Send
RemoveHandler m.Close, AddressOf m_Close
HandlerAdded = False
End If
Marshal.FinalReleaseComObject(m)
m = Nothing
ok = False
End Sub
[/highlight]
Das "Problem" dabei ist, dass wenn die gespeicherte Mail geöffnet wird, Outlook sagt, sie sei noch nicht gesendet worden, was bei unseren Anwendern zu Verwirrung führt, weil die Tatsache, dass die Mail mit Timestamp des Sendezeitpunkts als Dateinamen abgespeichert wird, anscheinend nicht so aussagekräftig ist, wie die Bestätigung des Mailprogramms wenn man die Datei öffnet.
Gut, VB führt zuerst meinen Handler aus, speichert das MailItem und gibt das Event dann an Outlook zurück, der die Mail absendet. Daher war mein zweiter Ansatz, die Mail erst im Close-Ereignis zu speichern, da bekomme ich aber den Fehler "Das Element wurde verschoben oder gelöscht" oder so ähnlich, also ist das MailItem hier anscheinend nicht mehr verfügbar.
Der nächste Ansatz wäre, den Sent-Ordner des aktuellen Users zu durchsuchen, und die aktuelle Mail suchen (nach welchen Kriterien vergleiche ich am besten, denn bei automatisch erzeugten Mails muss das Subject nicht unbedingt Hauptkriterium sein, oder gibt es eine spezielle MailItemID oder Handle, die ich nutzen kann?), aber was mache ich, wenn jemand die Option, gesendete Emails im Sent-Ordner zu speichern deaktiviert hat, oder Outlook mit Regeln konfiguriert hat, die gesendete Mails je nach Subject in Unterordnern oder ganz wo anders speichern?
Sent und SentOn sind ja ReadOnly Properties , sonst hätte ich das MailItem künstlich in den Sent-Zustand versetzt bevor ich es speichere (oder hätte das das Senden durch Outlook behindert?), und andere Möglichkeiten, das System auszutricksen fallen mir nicht ein. Vielleicht kann mir ja hier jemand helfen.
Mit freundlichen Grüßen
Martin Dietz
In meiner Applikation nutze ich zur zeit zum Versenden von Mails über Outlook eine Klasse, die ein Outlook.MailItem kapselt. Das Speichern der Mail beim Versenden wird dadurch bewerkstelligt, dass ich im Falle, dass ich einen Speicherungswunsch vermerkt habe, eigene Handler für das Send und das Close-Ereignis hinzufüge.
[highlight=vbnet]
Public Sub SaveOnSend(ByVal dstDirName As String, ByVal dstFileName As String, Optional ByVal UseTimeStamp As Boolean = True, Optional ByVal OwnSubfolder As Boolean = True)
If ok = False Then ShowInternalError("Fehlerhafter Aufruf von 'clsOutlookMail.SaveOnSend'.") : Return
If dstDirName = "" Or dstFileName = "" Then Return
If Not IO.Directory.Exists(dstDirName) Then
If Not DirectoryMake(dstDirName) Then Return
End If
activeSaveOnSend = True
Me.withTimeStamp = UseTimeStamp
Me.useSubfolder = OwnSubfolder
pdstDirName = dstDirName
pdstFileName = dstFileName
End Sub
Public Sub Display()
If ok = False Then ShowInternalError("Fehlerhafter Aufruf von 'clsOutlookMail.Display'.") : Return
If activeSaveOnSend Then
AddHandler m.Send, AddressOf m_Send
AddHandler m.Close, AddressOf m_Close
HandlerAdded = True
'clsOutlookMail-Objekt selbst sichern, dass es nicht bei GarbageCollection zerstört wird, bevor es gesendet wird
If mArr Is Nothing Then mArr = New ArrayList
mArr.Add(Me)
End If
m.Display()
Try
AppActivate(m.Subject & " - Nachricht (HTML)")
Catch ex As Exception
End Try
If Not activeSaveOnSend Then
EmailFreigeben()
End If
End Sub
Private Sub m_Send(ByRef Cancel As Boolean)
EmailSpeichern()
EmailFreigeben()
'kann anschließend im Fall einer GarbageCollection zerstört werden
mArr.Remove(Me)
End Sub
Private Sub m_Close(ByRef Cancel As Boolean)
'Problem, wenn Benutzer bei Sicherheits-Abfrage "Abbrechen" wählt; das ist nicht erkennbar
EmailFreigeben()
'kann anschließend im Fall einer GarbageCollection zerstört werden
mArr.Remove(Me)
End Sub
Private Sub EmailSpeichern()
If pdstDirName = "" Or pdstFileName = "" Then Return
If Not activeSaveOnSend Then Return
Dim d As String = pdstDirName & IIf(useSubfolder, "\" & "Emails", "")
If Not IO.Directory.Exists(d) Then
If Not DirectoryMake(d) Then ShowError("Fehler beim Zugrif auf Dateiordner" & vbCrLf & "'" & d & "'") : Return
End If
Dim f As String = IIf(withTimeStamp, Now.ToString("yyyy-MM-dd_HH-mm-ss") & "_", "") & pdstFileName & ".msg"
Try
m.SaveAs(d & "\" & f)
Catch ex As Exception
ShowError("Fehler beim Speichern der E-Mail unter" & vbCrLf & "'" & d & "'" & vbCrLf & "(" & ex.Message & ")")
End Try
End Sub
Private Sub EmailFreigeben()
If HandlerAdded Then
RemoveHandler m.Send, AddressOf m_Send
RemoveHandler m.Close, AddressOf m_Close
HandlerAdded = False
End If
Marshal.FinalReleaseComObject(m)
m = Nothing
ok = False
End Sub
[/highlight]
Das "Problem" dabei ist, dass wenn die gespeicherte Mail geöffnet wird, Outlook sagt, sie sei noch nicht gesendet worden, was bei unseren Anwendern zu Verwirrung führt, weil die Tatsache, dass die Mail mit Timestamp des Sendezeitpunkts als Dateinamen abgespeichert wird, anscheinend nicht so aussagekräftig ist, wie die Bestätigung des Mailprogramms wenn man die Datei öffnet.
Gut, VB führt zuerst meinen Handler aus, speichert das MailItem und gibt das Event dann an Outlook zurück, der die Mail absendet. Daher war mein zweiter Ansatz, die Mail erst im Close-Ereignis zu speichern, da bekomme ich aber den Fehler "Das Element wurde verschoben oder gelöscht" oder so ähnlich, also ist das MailItem hier anscheinend nicht mehr verfügbar.
Der nächste Ansatz wäre, den Sent-Ordner des aktuellen Users zu durchsuchen, und die aktuelle Mail suchen (nach welchen Kriterien vergleiche ich am besten, denn bei automatisch erzeugten Mails muss das Subject nicht unbedingt Hauptkriterium sein, oder gibt es eine spezielle MailItemID oder Handle, die ich nutzen kann?), aber was mache ich, wenn jemand die Option, gesendete Emails im Sent-Ordner zu speichern deaktiviert hat, oder Outlook mit Regeln konfiguriert hat, die gesendete Mails je nach Subject in Unterordnern oder ganz wo anders speichern?
Sent und SentOn sind ja ReadOnly Properties , sonst hätte ich das MailItem künstlich in den Sent-Zustand versetzt bevor ich es speichere (oder hätte das das Senden durch Outlook behindert?), und andere Möglichkeiten, das System auszutricksen fallen mir nicht ein. Vielleicht kann mir ja hier jemand helfen.
Mit freundlichen Grüßen
Martin Dietz