Removing Deleted Items Left by the iPhone

Wed, Oct 28, 2009 2-minute read

One thing you might notice if you have an iPhone connecting to an Inbox via the IMAP protocol is that messages you delete tend to stick around when viewed from other devices (such as Outlook, Outlook Web Access, etc.)

This is caused by an out-of-date view of mail management, where your Inbox handles everything. When you delete an item, some IMAP clients (such as the iPhone) mark them as deleted, but don’t actually remove the item from the server. Some clients hide these deleted items. Some show them with a line through them. Some ignore the deleted flag altogether.

Most email clients (including iPhone) move deleted items to their own sub-folder, so marking items as deleted just ends up being an annoyance:

The solution is the IMAP ‘EXPUNGE’ command. It permanently deletes items that have been marked for deletion (while of course leaving everything in Deleted Items untouched.) The iPhone has an option to do this once a day, but it doesn’t seem to work very well (and a day lag feels like an eternity, anyways.)

The folks at freshlogic have a fine application to run the command against your mail server. We can improve on it in a few ways by writing it in PowerShell. Our version:

  • Enables support for securely cached credentials
  • Doesn’t require an always-running application
  • Runs in the background

To do this, our script imports our saved password, and then uses Send-TcpRequest to simply connect to the server and send the EXPUNGE command. Finally, we use schtasks.exe to automate it.

# 1) Get your password into a securestring:
# $ss = Read-Host -AsSecureString
# 2) Export it to disk
# $ss | ConvertFrom-SecureString |
# Out-File (Join-Path (Split-Path $profile) Sync-MailboxDeletedState.ps1.credential)
# 3) Create the scheduled task
# schtasks /Create /TN MailboxUpdater /SC MINUTE /MO 5 /TR
# "powershell -NoProfile -WindowStyle Hidden -File 'c:\path\to\Sync-MailboxDeletedState.ps1'"
$username = "[email protected]"
$server = ""
$port = 993

$passwordPath = Join-Path (Split-Path $profile) Sync-MailboxDeletedState.ps1.credential
$password = Get-Content $passwordPath | ConvertTo-SecureString

$cred = New-Object System.Management.Automation.PsCredential $username,$password

$nc = $cred.GetNetworkCredential()
$commands = "A1 LOGIN $($nc.UserName + '@' + $nc.Domain) $($nc.Password)",
            'A2 SELECT INBOX',
            'A3 EXPUNGE',
            'A4 LOGOUT'

$commands | Send-TcpRequest $server $port -UseSSL