cornyriegelchen
Goto Top

Powershell - Mailkit - Löschen des Papierkorbs

Hallo zusammen,

ich stehe vor der Herausforderung, den Papierkorb eines IMAP-Providers meines Postfaches zu leeren. Leider bietet der Provider keine automatische Lösung für diese Aufgabe an.

Ich setze bereits PowerShell 7 ein, da das MailKit in Version 4.8.0 nicht mehr mit PowerShell 5.1 kompatibel ist.

Der aktuelle Stand ist, dass die E-Mails zwar zum Löschen markiert werden, aber die Methode, die ich versuche, funktioniert nicht:
$($folder.AddFlags($message.MessageId, [MailKit.MessageFlags]::Deleted, $true))

Leider scheint .AddFlags nicht verfügbar zu sein und es tritt folgender Fehler auf:
InvalidOperation: Method invocation failed because [MimeKit.MimeMessage] does not contain a method named 'AddFlags'.

Ich habe auch bereits versucht, über Fetch zu arbeiten, aber ohne Erfolg. ChatGPT/Gemini konnte mir bisher nicht weiterhelfen.

Hat jemand eine Idee, wie ich diese Herausforderung mit MailKit in PowerShell lösen kann? Ich hoffe auf eure Unterstützung.

Danke im Voraus!


#DLL Laden
Add-Type -Path "C:\admin\MailKit.4.8.0\lib\net48\MailKit.dll"  
Add-Type -Path "C:\admin\MimeKit.4.8.0\lib\net48\MimeKit.dll"  


# IMAP-Server und Anmeldedaten
$imapServer = "imap.xyz.de"  # Ersetzen Sie dies mit Ihrem IMAP-Server  
$imapPort = 993  # IMAP-Port (SSL)
$username = "mail@xyz.de"  
$password = "sfdsdfsdfsdfsdfsdf"  

# Erstellen Sie den IMAP-Client und verbinden Sie sich
$imapClient = New-Object MailKit.Net.Imap.ImapClient
# SSL-Prüfung ausschalten (unsicher, nur zu Testzwecken)
$imapClient.ServerCertificateValidationCallback = { $true }

# Versuchen Sie, die Verbindung erneut herzustellen
$imapClient.Connect($imapServer, $imapPort, $true)  # SSL aktivieren
$imapClient.Authenticate($username, $password)


$allNamespaces = $imapClient.PersonalNamespaces + $imapClient.SharedNamespaces + $imapClient.OtherNamespaces
if ($allNamespaces.Count -gt 0) {
    # Alle Ordner durchgehen, auch in Shared und Other Namespaces
    foreach ($namespace in $allNamespaces) {
        Write-Host "Durchsuche Namespace: $($namespace.Namespace)"  

        try {
            # Alle Ordner im aktuellen Namensraum abrufen
            $folders = $imapClient.GetFolders($namespace)


            if ($($folder.FullName) -eq 'Papierkorb') {  
                # Hole alle UIDs der Nachrichten im Ordner
                $searchResults = $folder.Search([MailKit.Search.SearchQuery]::All)
                
                foreach ($uid in $searchResults) {
                    # Hole die Nachricht mit der UID
                    $message = $($folder.GetMessage(0))  # Hole die Nachricht anhand der UID
                    $message.MessageId
                    $($folder.AddFlags($message.MessageId, [MailKit.MessageFlags]::Deleted, $true))

                    Write-Host "Betreff der Nachricht mit UID $uid: $($message.Subject)"  
                    
                }
      $folder.Expunge($true)
            }
        } catch {
            Write-Host "Fehler beim Abrufen der Ordner im Namespace '$($namespace.Namespace)': $_"  
        }

    }
} else {
    Write-Host "Keine Namensräume gefunden."  
}
#$imapClient.Disconnect($true)

Content-ID: 670029

Url: https://administrator.de/forum/powershell-mailkit-loeschen-des-papierkorbs-670029.html

Ausgedruckt am: 10.01.2025 um 04:01 Uhr

colinardo
Lösung colinardo 06.12.2024 aktualisiert um 12:52:04 Uhr
Goto Top
Servus @CornYriEgelchen, Herzlich Willkommen auf Administrator.de!

In den neueren Mailkit Versionen geht das Versehen von Nachrichten mit Flags jetzt anders und zwar mit der Store Methode.
https://github.com/jstedfast/MailKit/blob/master/README.md

Du kannst der Methode auch gleich direkt eine Liste von UIDs übergeben dann brauchst du keine Schleife
[void]$folder.Store($searchResults,(New-Object MailKit.StoreFlagsRequest ([Mailkit.StoreAction]::Add,[Mailkit.MessageFlags]::Deleted) -P @{Silent = $true}))
$folder.Expunge()

Und das Abrufen der Nachricht ist ebenfalls überflüssig wenn du diese nur löschen willst. Du brauchst dazu ja nur die UIDs und die hast du ja schon in den der Variablen $searchResult.

if ($($folder.FullName) -eq 'Papierkorb') {
Das ermitteln des Papierkorbs geht einfacher und vor allem Sprachunabhängig wenn du es so machst:
$folder = $imapClient.GetFolder([MailKit.SpecialFolder]::Trash)
[void]$folder.Open([MailKit.FolderAccess]::ReadWrite)

Vergesse nicht eventuelle gelöschte Unterodner des Papierkorbs ebenfalls zu löschen sonst bleiben die dort liegen face-wink.

Grüße Uwe
CornYriEgelchen
CornYriEgelchen 06.12.2024 um 16:30:53 Uhr
Goto Top
Besser als KI! 😆
Danke, werde ich am Montag direkt ausprobieren.
CornYriEgelchen
CornYriEgelchen 09.12.2024 um 13:28:22 Uhr
Goto Top
Danke! Hat geklappt. Anbei der ausgebesserte Code:

<#

    Dieses Skript funktioniert nur unter Powershell 7.x
    Mailkit und MimeKit erfordern mindestens .netFramework 4.8. Das Problem ist das die Standardpowershell 5.1 das nicht mehr kann, es gibt auch keine Weiterentwicklung.

#>

#DLL Laden
Add-Type -Path "C:\test\MailKit.4.8.0\lib\net48\MailKit.dll"  
Add-Type -Path "C:\test\MimeKit.4.8.0\lib\net48\MimeKit.dll"  


# IMAP-Server und Anmeldedaten
$imapServer = "imap.server.de"  # Ersetzen Sie dies mit Ihrem IMAP-Server  
$imapPort = 993  # IMAP-Port (SSL)
$username = "mail@domain.de"  
$password = "password"  

# Erstellen Sie den IMAP-Client und verbinden Sie sich
$imapClient = New-Object MailKit.Net.Imap.ImapClient

# SSL-Prüfung ausschalten (unsicher, nur zu Testzwecken)
# WARNUNG: Diese Einstellung sollte in Produktionsumgebungen nicht verwendet werden, da sie Sicherheitsrisiken birgt.
$imapClient.ServerCertificateValidationCallback = { $true }

# Verbinden Sie sich mit dem IMAP-Server
# $imapServer: Adresse des IMAP-Servers
# $imapPort: Portnummer (z. B. 993 für IMAP über SSL)
# Das dritte Argument ($true) aktiviert SSL/TLS für die Verbindung.
$imapClient.Connect($imapServer, $imapPort, $true)

# Authentifizieren Sie sich mit Benutzername und Passwort
# $username: IMAP-Benutzername
# $password: IMAP-Passwort
$imapClient.Authenticate($username, $password)

# Versuch, auf den Papierkorb-Ordner zuzugreifen und darin enthaltene Nachrichten zu löschen
try {
    # Abrufen des Papierkorb-Ordners (Trash) anhand des Standardordners "SpecialFolder.Trash"  
    $folder = $imapClient.GetFolder([MailKit.SpecialFolder]::Trash)
    
    # Öffnen des Ordners im Lese-/Schreibmodus
    $folder.Open([MailKit.FolderAccess]::ReadWrite)

    # Abrufen aller Nachrichten im Ordner basierend auf einer Suchanfrage (in diesem Fall alle Nachrichten)
    $searchResults = $folder.Search([MailKit.Search.SearchQuery]::All)

    # Markieren der gefundenen Nachrichten als gelöscht
    $folder.Store(
        $searchResults, 
        (New-Object MailKit.StoreFlagsRequest(
            [MailKit.StoreAction]::Add, 
            [MailKit.MessageFlags]::Deleted) -P @{Silent = $true})
    )

    # Endgültiges Löschen der Nachrichten aus dem Ordner
    $folder.Expunge()
} catch {
    # Fehlerbehandlung, falls der Zugriff auf den Ordner oder eine andere Aktion fehlschlägt
    Write-Host "Fehler beim Abrufen der Ordner im Namespace '$($namespace.Namespace)': $_"  
}

# Verbindung zum IMAP-Server trennen
# Das Argument $true sorgt dafür, dass die Verbindung ordnungsgemäß geschlossen wird.
$imapClient.Disconnect($true)
colinardo
colinardo 09.12.2024 aktualisiert um 13:37:33 Uhr
Goto Top
👍 Wenn du gelöschte Ordner im Papierkorb (inkl. Inhalt) auch noch entsorgen willst ergänzt du noch folgendes
$subfolders = $folder.GetSubfolders($false)
foreach($subfolder in $subfolders){
    try{
        write-host "Deleting folder '$($subfolder.Name)'" -F Yellow  
        $subfolder.Delete()
    }catch{
         write-host "Error deleting folder: $($_.Exception.Message)" -F Red  
    }
}
CornYriEgelchen
CornYriEgelchen 09.12.2024 um 17:53:02 Uhr
Goto Top
Das ist garnicht notwendig! Aber herzlichen Dank! ☺️
Note 1