VB .NET - E-Mails mit Indy empfangen und Anhänge abspeichern

Um in VB .NET E-Mails zu versenden, verwendet man am besten den Namespace Net.Mail.

Leider gibt es in VB .NET allerdings noch keine Möglichkeit, E-Mails zu empfangen um beispielsweise die Dateianhänge abzuspeichern.

Um dieses Problem zu beseitigen, zeige ich im Folgenden, wie man mit Hilfe von Indy eine E-Mail von einem POP3 Postfach herunterlädt und eventuelle Anhänge der E-Mails auf dem Dateisystem abspeichert.

Wichtig, zur Verwendung von Indy muss als Referenz die Indy.Sockets und Mono.Security DLL in das Projekt eingebunden werden.

Zu erst einmal eine kleine Hilfsklasse, in der wir die Konten-Informationen unseres POP3 Kontos ablegen:

Public Class MailAccount
 
  ''' <summary>
  ''' Hostname des E-Mail Servers
  ''' </summary>
  ''' <remarks></remarks>
  Public Host As String
 
  ''' <summary>
  ''' Benutzername des E-Mail Kontos
  ''' </summary>
  ''' <remarks></remarks>
  Public Username As String
 
  ''' <summary>
  ''' Benutzer-Passwort des E-Mail Kontos
  ''' </summary>
  ''' <remarks></remarks>
  Public Password As String
 
End Class

Nun der interessantere Teil. Die Methode SaveAllAttachments speichert vom übergebenen Mailkonto alle Anhänge aller E-Mails temporär auf der Festplatte lokal ab.

Hierfür verbinden wir uns erst mit dem Mailkonto, ermitteln dann die Menge aller E-Mails auf dem Postfach und iterieren dann durch jede einzelne E-Mail.

Eine E-Mail besteht aus mehreren sogenannten Messageparts. Ist ein Messagepart vom Typ Octet-Stream, handelt es sich um einen Dateianhang, den wir ja abspeichern wollen.

Public Class IndyTools
 
  ''' <summary>
  ''' Speichert alle Dateianhänge des Postfachs aAccount im Verzeichnis
  ''' </summary>
  ''' <param name="aAccount">Postfach Konto</param>
  ''' <remarks></remarks>
  Public Sub SaveAllAttachments(ByVal aAccount As MailAccount)
 
    Dim tempfilename As String
    Dim IsAttachment As Boolean
 
    Dim o As NewIndy.Sockets.TIdNetNativeComponent
    Dim p As NewIndy.Sockets.POP3(o)
    Dim att As Indy.Sockets.Attachment
 
    ' Verbindungsdaten an Indy übergeben
    With p
      .Host = aAccount.Host
      .Username = aAccount.Username
      .Password = aAccount.Password
    End With
 
    Try
 
      Try
        ' Verbinden und Mailmenge feststellen
        p.Connect()
 
        ' Anzahl der Mails auf dem Postfach ermitteln
        Dim Amount As Integer = p.CheckMessages
 
        ' Für alle Mails
        For i As Integer = 1 To Amount
 
          ' Mail abholen
          Dim msg As New Indy.Sockets.Message
          p.Retrieve(i, msg)
 
          ' Für jeden Messagepart
          For x As Integer = 1 To msg.MessageParts.Count - 1
 
            ' Ist dieser Messagepart ein Anhang?
            IsAttachment = msg.MessageParts.Items(x).ContentType = "application/octet-stream"
 
            If IsAttachment Then
 
              Try
                ' Anhang holen
                att = msg.MessageParts.Items(x)
 
                ' Anhang temporär speichern
                tempfilename = System.IO.Path.GetTempFileName
                att.SaveToFile(tempfilename)
 
              Catchex As Exception
                MsgBox(ex.Message, MsgBoxStyle.Critical)
              End Try
 
            End If
 
          Next
 
        Next
 
      Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical)
      End Try
 
    Finally
      p.Disconnect()
      p.Dispose()
    End Try
 
  End Sub
 
End Class

Hier noch ein Modul mit einem kleinen Beispielaufruf obiger Klassen:

Module modTest
 
  Sub Main()
    Dim it As New IndyTools
    Dim ac As New MailAccount
 
    ac.Username = "frank.miller@gmx.net"
    ac.Password = "BestMovie300"
    ac.Host = "pop.gmx.de"
 
    it.SaveAllAttachments(ac)
  End Sub
 
End Module