Posted by RvdH under hMailserver on Jun 27 2016

As hMailServer lacks the abbillity to block contents inside zip files and I can not block all zip attachments using the 'blocked attachments' panel in hmailadmin as many of clients use them to send/receive pictures and design stuff like Illustrator or Photoshop graphics i needed to find a different approach to block harmfull files inside zip archives like exe, vbs en js files nowadays used to infect people with malware/trojans/virusses.

I ended up with writing a little .NET application that looks inside a zip file (if it is able to) and then list its content and deny the attachment if one or more disallowed file extensions are found inside the Zip archive.


  • Examine Zip Archive header (confirm it is actually a Zip Archive)
  • List files contained within the Zip Archive
  • Compare the list with files within the Zip Archive with a array of disallowed extensions (for example: *.js, *.vbs)

With the above program returning exitcodes I managed script eventhandlers.vbs to:
  • Delete archives with disallowed extensions in it
  • Quarantine damaged, fake and/or Zip attachments with disallowed extensions in it
  • Add Pseudo Attachment with blocked message


Note: In this short quick start guide I adapted hMailServer default paths for simplicity, you need to change if you installed it elsewhere

Extract the contents inside attached ZipArchive to:
C:\Program Files (x86)\hMailServer\Events\

If you like to adapt quarantine functionality of zip attachments, create folder:
C:\Program Files (x86)\hMailServer\Quarantine\

Edit ScanZipArchive.exe.config to suite your needs (included in download)

Note: ScanZipArchive.exe uses .NET Path.Combine function to catch common file/path errors so it uses defined "Path" parameter (normally this would be: C:\Program Files (x86)\hMailServer\Temp\) in combination with archive filename passed to ScanZipArchive.exe 
<?xml version="1.0" encoding="utf-8"?>
    <add key="Path" value="C:\Program Files (x86)\hMailServer\Temp\"/>
    <add key="Extensions" value="bat|cmd|com|cpl|csh|docm|exe|pif|hta|htb|inf|js|jse|lnk|msi|msp|pif|reg|scf|scr|shs|shb|vbe|vbs|wsf|wsh"/>
    <!-- Value in kilobytes, 1024 kB is 1 MB, 0 or empty value disables this feature -->
    <add key="MaximumSize" value="0"/> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
	// exit codes //
	-1 = File not found error and/or Filename argument is missing
	 0 = Clean and/or Zip archive size > MaximumSize
	 1 = Zip archive contains file with disallowed extension
	 2 = This archive is not a valid Zip archive

Edit template.txt to suite your needs (included in download)
The attachment [%1] was blocked for delivery by the e-mail server because its content presents a potential security issue. Please contact your system administrator if you have any questions regarding this.


Edit EventHandlers.vbs, Add the subs below (To debug, uncomment REM EventLog.Write statements)
Sub ScanZipAttachments(oMessage)

   Dim Quarantine
   Quarantine = false
   Dim QuarantineFolder
   QuarantineFolder = "C:\Program Files (x86)\hMailServer\Quarantine\"   

   Dim Changed
   Changed = false
   Dim TempFolder
   TempFolder = "C:\Program Files (x86)\hMailServer\Temp\" 
   Dim QuarantineFile, ZipFile, ZipPath
   Dim PseudoFile
   Dim oAttachment   
   Dim ExitCode, WshShell 
   If oMessage.Attachments.Count > 0 then
      dim fso
      Set fso = CreateObject("Scripting.FileSystemObject")
      For oAttachment = 0 to oMessage.Attachments.Count-1
         If Lcase(fso.GetExtensionName(oMessage.Attachments(oAttachment).Filename)) = "zip" Then
            ZipFile = Left(Right(oMessage.Filename,42),38) & "." & oAttachment & "." & oMessage.Attachments(oAttachment).Filename
            ZipPath = fso.BuildPath(TempFolder,ZipFile)
            REM EventLog.Write("Temp file saved as: " & ZipPath)
            Set WshShell = CreateObject("WScript.Shell")
            ExitCode = WshShell.Run("""C:\Program Files (x86)\hMailServer\Events\ScanZipArchive.exe"" """ & ZipFile & """",0,True)
            REM EventLog.Write("ExitCode: " & ExitCode)
            If fso.FileExists(ZipPath) Then
               fso.DeleteFile ZipPath, True
               REM EventLog.Write("Temp file deleted: " & ZipPath)
            End If

            if (ExitCode > 0) Then
               If (Quarantine) Then
                  QuarantineFile = fso.BuildPath(QuarantineFolder, Left(Right(oMessage.Filename,42),38) & "." & oAttachment & "." & oMessage.Attachments(oAttachment).Filename & ".Quarantined")
                  EventLog.Write("Attachment quarantined as: " & QuarantineFile)
               End If 
               Select Case ExitCode
               case 1
                  EventLog.Write("Attachment " & oMessage.Attachments(oAttachment).Filename & " deleted because it contained a file with disallowed extension")
                  Changed = true
               Case 2
                  EventLog.Write("Attachment " & oMessage.Attachments(oAttachment).Filename & " deleted because it is a invalid or corrupted archive")
                  Changed = true
               End Select
               PseudoFile = fso.BuildPath(TempFolder, oMessage.Attachments(oAttachment).Filename & ".txt")
               If fso.FileExists(PseudoFile) Then
                  fso.DeleteFile PseudoFile, True
               end if
            End If
            Set WshShell = Nothing
         End If 
      If (Changed) then
      End If
      Set fso = Nothing
   End If
End Sub
Sub WriteFile(filename)
   Dim TempFolder
   TempFolder = "C:\Program Files (x86)\hMailServer\Temp\"
   Dim TemplateFile : TemplateFile = "C:\Program Files (x86)\hMailServer\Events\template.txt"
   Dim vBody : vBody = Empty
   Dim vLine : vLine = Empty
   dim fso, PseudoFile
   Set fso = CreateObject("Scripting.FileSystemObject")
      PseudoFile = fso.BuildPath(TempFolder, filename & ".txt")
   Set fso = nothing
   Dim objStreamBody
   Set objStreamBody = CreateObject("ADODB.Stream")

    Const CdoBIG5        = "big5"
    Const CdoEUC_JP      = "euc-jp"
    Const CdoEUC_KR      = "euc-kr"
    Const CdoGB2312      = "gb2312"
    Const CdoISO_2022_JP = "iso-2022-jp"
    Const CdoISO_2022_KR = "iso-2022-kr"
    Const CdoISO_8859_1  = "iso-8859-1"
    Const CdoISO_8859_2  = "iso-8859-2"
    Const CdoISO_8859_3  = "iso-8859-3"
    Const CdoISO_8859_4  = "iso-8859-4"
    Const CdoISO_8859_5  = "iso-8859-5"
    Const CdoISO_8859_6  = "iso-8859-6"
    Const CdoISO_8859_7  = "iso-8859-7"
    Const CdoISO_8859_8  = "iso-8859-8"
    Const CdoISO_8859_9  = "iso-8859-9"
    Const cdoKOI8_R      = "koi8-r"
    Const cdoShift_JIS   = "shift-jis"
    Const CdoUS_ASCII    = "us-ascii"
    Const CdoUTF_7       = "utf-7"
    Const CdoUTF_8       = "utf-8"
   objStreamBody.Mode = 3
   objStreamBody.LineSeparator = -1
   objStreamBody.Type = 2
   objStreamBody.Charset = CdoUS_ASCII



   objStreamBody.Position = 0
   Do Until objStreamBody.EOS
      vLine = objStreamBody.ReadText()
      vLine = Replace(vLine,"[%1]",filename)
      vBody = vBody & vLine
   objStreamBody.Position = 0
   objStreamBody.SaveToFile PseudoFile, 2
   Set objStreamBody = Nothing
End Sub

As final step first add a global rules which says: 

Predefined field: Message size > 0
Custom header field: X-hMailServer-LoopCount < 1


Run function ScanZipAttachments

  1. NET Framework 4.5 or higher (the program uses System.IO.Compression which did not exist in .NET prior version 4.5)
  2. Make sure "Scripts" usage is enabled in hMailServer Administrator under  Settings -> Advanced -> Scripts
  3. Make sure the executable (ScanZipArchive.exe) is not blocked by the Windows SmartScreen Filter
    (This could be a problem assuming one of the comments)

Version history: (18/01/2019)
  • Check and verify ScanZipArchive.exe.config file exists
  • Exit loop of the files inside the Zip archive as soon as one blocked file extension is found
  • Sub ScanZipAttachments, fix a issue where uppercase ZIP archives where ignored
    If Lcase(fso.GetExtensionName(oMessage.Attachments(oAttachment).Filename)) = "zip" Then 
  • Abbility to assign a MaximumSize of zip archive to scan
    value in kilobytes, 1024 kB is 1 MB, 0 or empty value disables this feature
  • Initial release

Last edited Jan 18 2019


Well that's harder... theoretical it would be possible to build in support for other file types, but then again, you probably better off using a full blown virus scanner.

I personally don't allow any other archive types then Zip archives, I have .arj, .7z, .rar specified within hMailServer blocked attachments types list.

Posted by RvdH on Jul 09 2019 14:34
How to scan other archives like .arj, .7z, .rar etc ?

Posted by BorizzK on Jul 09 2019 14:21
Yes, its working
I confused

Posted by BorizzK on Jul 09 2019 11:44
What exactly is not working?
The message "Executing event Unknown" is normal, as this is a script event hMailServer doesn't know it's name

Posted by RvdH on Jul 05 2019 18:02
Not Working

"DEBUG" 5812 "2019-07-04 16:10:45.353" "Applying rules"
"DEBUG" 5812 "2019-07-04 16:10:45.354" "Applying rule 000. SCAN ARCHIVE"
"DEBUG" 5812 "2019-07-04 16:10:45.354" "Performing rule action"
"DEBUG" 5812 "2019-07-04 16:10:45.355" "Executing event Unknown"
"DEBUG" 5812 "2019-07-04 16:10:45.358" "Event completed"

Posted by BorizzK on Jul 04 2019 15:12
Alex, you need to put ScanZipArchive.exe.config beside ScanZipArchive.exe as it loads it's settings from it

Posted by RvdH on Jan 18 2019 08:46
Hi, I have a problem in command line:
D:\15>scanziparchive.exe "d:\15\"

System.NullReferenceException: Object reference does not indicate an object instance
in ScanZipArchive.Program.Main(String[] args)

Windows 7 SP1, NET Framework 4.6

Posted by Alex on Dec 20 2018 08:26

You mean the Windows SmartScreen Filter? Sounds like it, so i will put a remark in the article

Thx for replying!

Posted by RvdH on Dec 13 2016 16:39
Hi RvdH
Sorry for the late respone.
I have tested and tried for some time. Finally I found that it's the .exe file which is downloaded from internet, locked by Windows to protect the computer. So, after unlocking , things become normal. Thank you for your brillant work.

Posted by Wallace on Dec 12 2016 06:57

That does not make any sense... if the messages reach the delivery queue the script is finished already. If you open a message in the delivery queue, is the attached zip file there?
And please also check if anything written to 'hmailserver_events.log'?

Posted by RvdH on Nov 24 2016 14:07
To be exact, all emails with zip attachments are found in delivery queue and these emails are never received by users.

Posted by Wallace on Nov 24 2016 12:30
Hi , I have the same problem with Damien. All emails with zip attachment was blocked and not received. They are found in the delivery queue . When click resend now , nothing happens.
I can run ScanZipArchive.exe with no problem from command line.

btw, thank you very much for your work.

Posted by Wallace on Nov 24 2016 11:51
Hi Damien, do you have all paths setup correctly? NET Framework 4.5 installed?

Also, you could try to run ScanZipArchive.exe from the command line, eg:
ScanZipArchive.exe "FULL PATH TO ZIP"

Do yo get a error message while using it from the command line?

Posted by RvdH on Nov 02 2016 12:53
hi , love and using your script, but it is blocking all zip files even my own images and gernal pdf's ???

any ideas ??

Posted by Damien Porter on Oct 28 2016 16:36
thanks for great script. Exactly what I need.
You should mention that you need to enable "Scripts" under Advanced->Scripts.

Posted by Tomaz on Sep 13 2016 13:13

post your comment

 (*) - required