Skip to content

Instantly share code, notes, and snippets.

@dziemborowicz
Last active December 30, 2021 18:38
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dziemborowicz/145061dc9a308a37526a to your computer and use it in GitHub Desktop.
Save dziemborowicz/145061dc9a308a37526a to your computer and use it in GitHub Desktop.
PowerShell cmdlet for removing attachments from *.msg files
function Remove-MsgAttachment
{
[CmdletBinding()]
Param
(
[Parameter(ParameterSetName="Path", Position=0, Mandatory=$True)]
[String]$Path,
[Parameter(ParameterSetName="LiteralPath", Mandatory=$True)]
[String]$LiteralPath,
[Parameter(ParameterSetName="FileInfo", Mandatory=$True, ValueFromPipeline=$True)]
[System.IO.FileInfo]$Item
)
Begin
{
# OlInspectorClose constants
$olSave = 0
$olDiscard = 1
$olPromptForSave = 2
# OlSaveAsType constants
$olTXT = 0
$olRTF = 1
$olTemplate = 2
$olMSG = 3
$olDoc = 4
# Load application
Write-Verbose "Loading Microsoft Outlook..."
$outlook = New-Object -ComObject Outlook.Application
}
Process
{
switch ($PSCmdlet.ParameterSetName)
{
"Path" { $files = Get-ChildItem -Path $Path }
"LiteralPath" { $files = Get-ChildItem -LiteralPath $LiteralPath }
"FileInfo" { $files = $Item }
}
$files | % {
# Work out file names
$msgFn = $_.FullName
# Skip non-.msg files
if ($msgFn -notlike "*.msg") {
Write-Verbose "Skipping $_ (not an .msg file)..."
return
}
# Open the msg file
$msg = $outlook.Session.OpenSharedItem($msgFn)
# Do not touch files without attachments
if ($msg.Attachments.Count -eq 0) {
Write-Verbose "Skipping $_ (has no attachments)..."
$msg.Close($olDiscard)
return
}
# Clone message
$msgCopy = $msg.Copy()
$msg.Close($olDiscard)
# Remove attachments from message
Write-Verbose "Removing attachments from $_..."
while ($msgCopy.Attachments.Count -gt 0) {
$msgCopy.Attachments.Remove(1)
}
# Save message
$msgCopy.SaveAs($msgFn, $olMSG)
}
}
End
{
Write-Verbose "Done."
}
}
@ririarte1
Copy link

Hi, this script doesn't seem to do anything. Have any notes on its usage?

@dziemborowicz
Copy link
Author

This script is ancient. If I remember correctly, it's meant to delete attachments from .msg files:

$ Remove-MsgAttachment "C:\Some\Folder\Email.msg"

It doesn't extract the attachments; it just deletes them. There's a script (which is also ancient) for extracting attachments from .msg files here.

@ririarte1
Copy link

ririarte1 commented Dec 28, 2021 via email

@dziemborowicz
Copy link
Author

I assume there are no error messages?

If you change --

$msgCopy.SaveAs($msgFn, $olMSG)

to --

$msgCopy.SaveAs($msgFn + "_new.msg", $olMSG)

does it create a new .msg file?

@ririarte1
Copy link

ririarte1 commented Dec 29, 2021 via email

@ririarte1
Copy link

ririarte1 commented Dec 29, 2021 via email

@dziemborowicz
Copy link
Author

Hmm. Could you try running it with the -Verbose flag:

$ Remove-MsgAttachment "C:\Some\Folder\Email.msg" -Verbose

@ririarte1
Copy link

ririarte1 commented Dec 30, 2021 via email

@dziemborowicz
Copy link
Author

No worries. I'm starting to run out ideas though...

Could you post the exact command that you're running?

@dziemborowicz
Copy link
Author

I think the only prerequisite should be an installation of Office (or Outlook specifically), but I would expect an error if it's missing.

@ririarte1
Copy link

ririarte1 commented Dec 30, 2021 via email

@dziemborowicz
Copy link
Author

Ah! I see... You have to first load the .ps1 file as a module to make the Remove-MsgAttachment cmdlet available in the current PowerShell session before running it (rather than running the .ps1 directly)... which I now realize I completely forgot to mention.

$ Import-Module "C:\Some\Folder\Remove-MsgAttachment.ps1"
$ Remove-MsgAttachment "C:\Some\Folder\Email.msg"

@ririarte1
Copy link

ririarte1 commented Dec 30, 2021 via email

@dziemborowicz
Copy link
Author

No worries. Any time. :)

If you unwrap everything in the .ps1 file so that it's not enclosed in a function, then I think you can run the script directly as you were doing it (without having to Import-Module first).

That is, if you change --

function Remove-MsgAttachment
{
    [CmdletBinding()]
    Param
    (
        # ...
    )

    # ...

    End
    {
        Write-Verbose "Done."
    }
}

to --

[CmdletBinding()]
Param
(
    # ...
)

# ...

End
{
    Write-Verbose "Done."
}

in the Remove-MsgAttachment.ps1 file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment