<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Viruses and dangerous attachments: ClamAV, custom scanners, the sandbox, sealed mail]]></title><description><![CDATA[<p dir="auto"><em>Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) calls the anti-virus action that strips attachments Remove all attachments and deliver the text (Delete infected attachments only in 6.3.6's Control Panel), and under it a message whose one part is an attachment, and an S/MIME message signed as one part, now arrive as the action's note alone, where every version to 6.3.6 delivered them as they arrived with what the scanner had found in them; a message the server cannot read is deleted and each of its recipients sent the "message deleted" notice whatever the two notify settings say, while an encrypted message, and one that is one text part, are delivered as they are. In the Control Panel the sidebar has a Virus scanning group, and Ctrl+K takes every old title to its page. See <a href="/topic/28277">the 6.3.7 announcement</a>. hMailServer 6.3.8 (2 November 2026) lets the Linux server reach clamd over its Unix socket: <code>ClamAVHost</code> takes the absolute path of clamd's <code>LocalSocket</code>, such as <code>/var/run/clamav/clamd.ctl</code> for Debian's and Ubuntu's <code>clamav-daemon</code>, which listens on nothing else by default, and <code>ClamAVPort</code> is then not used; no connection test is offered for it on Linux, so a test message and the log show the scan (<a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.8/hmailserver/docs/ClamAV.md" rel="nofollow ugc">ClamAV.md</a>). See <a href="/topic/28278">the 6.3.8 announcement</a>.</em></p>
<p dir="auto">hMailServer does not scan for viruses itself. It hands each message to an engine you install (ClamAV, ClamWin or any command-line scanner) and acts on the answer, and nothing described here is enabled on a fresh install. This topic covers the three scanners, what happens when one finds something or cannot run, the blocked-attachment list, and what 6.3.4 added: the sandbox, and the handling of mail sealed end to end. The one thing to know first is the failure mode: a configuration that <strong>looks enabled and is inert</strong>. A scanner switched on with a wrong host or a missing executable does not refuse mail and does not disable itself; when every scanner has errored the verdict is <code>NoVirusFound</code>, which from the message's point of view is identical to having been examined and found clean. 6.3.4 fixed one such case in the custom scanner, described below.</p>
<h3><a class="anchor-offset" name="what-runs-and-when"></a>What runs, and when</h3>
<p dir="auto">Scanning happens on the delivery side, not during the SMTP conversation: the message has already been accepted and spooled by the time any scanner sees it.</p>
<p dir="auto"><strong>Which messages are scanned.</strong> For SMTP, a message is flagged when the connecting IP's security range has the virus-protection option; both default ranges ("Internet" and "My computer") have it. For mail this server fetches over POP3 or IMAP, the flag is the external account's own "use anti-virus" setting. A flagged message larger than <code>AntiVirus.MaximumMessageSize</code> is not scanned at all, silently; the default is <code>0</code>, no limit.</p>
<p dir="auto"><strong>Two passes.</strong> The whole spool file is scanned first; then every MIME attachment is written to a temporary file and scanned separately, which is what matters for a scanner that does not decode MIME itself. If the message cannot be parsed for the second pass, error <code>HM6001</code> is reported and only the whole file was scanned; if one attachment cannot be written to the temp directory, <code>HM6002</code> is reported and that attachment was not examined.</p>
<p dir="auto"><strong>Concurrency.</strong> At most 10 scans run at once (<code>MaxRunningScanners</code>). A thread that cannot get a slot waits up to 60 seconds and then scans anyway, writing <code>Scanning message without an available virus scanner slot.</code> to the debug log.</p>
<p dir="auto"><strong>The read-only overview.</strong> <strong>Spam &amp; virus filtering → Virus scanning overview</strong> in the Control Panel (Windows only) answers the question the settings page cannot: will an infected message be caught here.</p>
<h3><a class="anchor-offset" name="the-three-scanners"></a>The three scanners</h3>
<p dir="auto">All three can be enabled at once. They run in the order ClamWin, custom, ClamAV, stopping at the first that reports a virus. A scanner that errors does not stop the others.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>ClamAV (clamd)</th>
<th>ClamWin (<code>clamscan.exe</code>)</th>
<th>Custom scanner</th>
</tr>
</thead>
<tbody>
<tr>
<td>Switch</td>
<td><code>AntiVirus.ClamAVEnabled</code></td>
<td><code>AntiVirus.ClamWinEnabled</code></td>
<td><code>AntiVirus.CustomScannerEnabled</code></td>
</tr>
<tr>
<td>Default</td>
<td>off</td>
<td>off</td>
<td>off</td>
</tr>
<tr>
<td>Reached by</td>
<td>TCP socket, <code>INSTREAM</code></td>
<td>one process per file</td>
<td>one process per file</td>
</tr>
<tr>
<td>Settings</td>
<td><code>AntiVirus.ClamAVHost</code> (<code>localhost</code>), <code>AntiVirus.ClamAVPort</code> (<code>3310</code>)</td>
<td><code>AntiVirus.ClamWinExecutable</code>, <code>AntiVirus.ClamWinDBFolder</code></td>
<td><code>AntiVirus.CustomScannerExecutable</code></td>
</tr>
<tr>
<td>"Infected" is</td>
<td>a reply matching <code>stream…: &lt;name&gt; FOUND</code></td>
<td>exit code 1</td>
<td>exit code equal to <code>AntiVirus.CustomScannerReturnValue</code></td>
</tr>
<tr>
<td>Timeout</td>
<td><code>ClamMinTimeout</code> 15 s to <code>ClamMaxTimeout</code> 90 s</td>
<td><code>ExternalProcessTimeout</code>, 300 s</td>
<td><code>ExternalProcessTimeout</code>, 300 s</td>
</tr>
<tr>
<td>Virus name reported</td>
<td>the name clamd returned</td>
<td>always <code>Unknown</code></td>
<td>always <code>Unknown</code></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>ClamAV.</strong> Install ClamAV, run <code>freshclam</code> to download signatures, run <code>clamd</code> listening on TCP 3310, set the host and port, and press <strong>Test ClamAV connection</strong>. The button does three things in order:</p>
<ol>
<li>It sends <code>nPING</code> and requires <code>PONG</code>, so "nothing is listening" is told apart from "something else is listening".</li>
<li>It sends <code>nVERSION</code> and reports what answered.</li>
<li>It streams a harmless sample and then the EICAR test string, both from memory, and requires the first to come back clean and the second <code>FOUND</code>.</li>
</ol>
<p dir="auto">A success looks like <code>ClamAV 1.4.2/27700/Mon Sep  8 09:12:11 2026. Result: stream: Eicar-Signature FOUND</code>; a failure names the step, for example <code>Unable to connect to ClamAV server at localhost:3310.</code></p>
<p dir="auto"><strong>The custom scanner.</strong> Any program that exits with a distinguishable code will do. Put <code>%FILE%</code> where the file to scan belongs; without it, the file name is appended as the single quoted argument. The Control Panel ships presets, all of them Windows programs:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Preset</th>
<th>Command line</th>
<th>"Infected" exit code</th>
</tr>
</thead>
<tbody>
<tr>
<td>Microsoft Defender</td>
<td><code>"C:\Program Files\Windows Defender\MpCmdRun.exe" -Scan -ScanType 3 -File "%FILE%" -DisableRemediation</code></td>
<td>2</td>
</tr>
<tr>
<td>Sophos</td>
<td><code>"C:\Program Files\Sophos\Sophos Anti-Virus\savscan.exe" -ss -archive "%FILE%"</code></td>
<td>3</td>
</tr>
<tr>
<td>ESET</td>
<td><code>"C:\Program Files\ESET\ESET Security\ecls.exe" "%FILE%"</code></td>
<td>50</td>
</tr>
<tr>
<td>Bitdefender</td>
<td><code>"C:\Program Files\Bitdefender\Endpoint Security\bdscan.exe" "%FILE%"</code></td>
<td>1</td>
</tr>
<tr>
<td>Kaspersky</td>
<td><code>"C:\Program Files (x86)\Kaspersky Lab\Kaspersky Endpoint Security\avp.com" SCAN "%FILE%"</code></td>
<td>2</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The 6.3.4 fix: a bare <code>%FILE%</code>.</strong> CHANGELOG records that a custom scanner whose command line holds a bare, unquoted <code>%FILE%</code> was handed the message file's path cut at its first space, and the default data directory, under <code>C:\Program Files</code>, has one. The scanner therefore scanned no file, answered with an exit code other than the virus one, and the message was delivered as clean. Since 6.3.4 a <code>%FILE%</code> outside double quotes is replaced by the path in quotes. One already inside them, <code>"%FILE%"</code> as the documented examples above write it, was not affected and is replaced as before. If you run an earlier release with a command line of your own, check it for an unquoted <code>%FILE%</code>. The same fix removes a trailing backslash from ClamWin's database and temporary folders, which escaped the closing quote of <code>--database="..."</code> and took the file to scan with it.</p>
<p dir="auto"><strong>The service account must be able to run the scanner.</strong> A new 6.3.4 installation on Windows runs the service as <code>NT SERVICE\hMailServer</code> by default; an upgrade keeps the account it had, LocalSystem unless the installer's page is answered otherwise (<a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/ServiceAccount.md" rel="nofollow ugc">docs/ServiceAccount.md</a>; the wiki's "<code>LocalSystem</code> by default" describes earlier releases and upgraded servers). Under the virtual account a custom scanner or ClamWin runs as that account: it reads the message in the temp folder, which is granted, and its own program and signatures, which the Users group can normally read; a scanner that needs more has to be granted it (<a href="/topic/28227">Installing on Windows</a> covers the account and its grants). Whichever account runs yours, the executable, its database directory and the temp directory must all be reachable by it. The symptom of getting it wrong is <code>Unable to launch the virus scanner…</code> reported as <code>HM5406</code>, once per message.</p>
<p dir="auto">For an engine with no command-line interface, the wiki points to an <code>OnAcceptMessage</code> event script or the HTTP filter hook. If you edit <code>hm_settings</code> by hand, note that the custom scanner's return value is stored under the misspelled name <code>customviursscannerreturnvalue</code>.</p>
<h3><a class="anchor-offset" name="testing-it-end-to-end"></a>Testing it end to end</h3>
<p dir="auto">The test buttons check the scanner. To check the pipeline, send yourself a message with the EICAR test file attached and watch the application log:</p>
<pre><code class="language-text">Virus found in message from someone@example.com. Taking actions
SMTPDeliverer - Message 4711: Message will be deleted (contained virus Eicar-Signature).
</code></pre>
<p dir="auto">Two things spoil that test on Windows. The host antivirus eats the EICAR file before hMailServer sees it, so exclude the mail store and the temp directory from real-time scanning. And your own outbound mail is not scanned by this server if it never comes back in through SMTP from an unauthenticated range, so send the test from an external address.</p>
<h3><a class="anchor-offset" name="what-happens-when-a-virus-is-found"></a>What happens when a virus is found</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th><code>AntiVirus.Action</code></th>
<th>What happens</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Delete entire e-mail</strong> (0, the default)</td>
<td>The message is delivered to nobody. Logged as <code>Message will be deleted (contained virus X).</code></td>
</tr>
<tr>
<td><strong>Delete infected attachments only</strong> (1; <strong>Remove all attachments and deliver the text</strong> in 6.3.7's Control Panel)</td>
<td>The message is rebuilt, not edited: the first <code>text</code> part is kept, everything else is discarded, the <code>VIRUS_ATTACHMENT_REMOVED</code> server message is prepended to the body and the subject is prefixed with the <code>VIRUS_FOUND</code> message. Logged as <code>Message attachments stripped (contained virus X).</code> Since 6.3.7 a message whose one part is an attachment arrives as the note alone, where every version to 6.3.6 delivered it as it arrived, and one the server cannot read is deleted, each recipient sent the "message deleted" notice whatever the two notify settings say</td>
</tr>
</tbody>
</table>
<p dir="auto">Understand the rebuild before you choose it: an HTML alternative, inline images and every clean attachment go with the infected one. <code>AntiVirus.NotifySender</code> and <code>AntiVirus.NotifyReceiver</code> are both off by default, and the wiki's advice is to leave them off: the sender address on a virus is virtually always forged, so a notification is backscatter.</p>
<h3><a class="anchor-offset" name="when-a-scanner-cannot-run"></a>When a scanner cannot run</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Setting</th>
<th>Default</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AVFailAction</code></td>
<td>0</td>
<td><code>0</code> delivers the message anyway. <code>1</code> never delivers unscanned mail</td>
</tr>
<tr>
<td><code>AVFailRetryMinutes</code></td>
<td>15</td>
<td>Minutes between scan attempts while a message is held</td>
</tr>
<tr>
<td><code>AVFailMaxHolds</code></td>
<td>16</td>
<td>Holds before the message is returned to its sender. <code>0</code> tells the sender immediately</td>
</tr>
</tbody>
</table>
<p dir="auto">They are on <strong>Anti-virus settings → General</strong>, card <strong>When a scanner cannot run</strong>. The wiki describes them as stored in <code>hMailServer.INI</code>; since 6.3.4 the database is the settings store and a <code>[Settings]</code> line edited in the file is put back, so change them in the Control Panel, over REST (<code>PUT /api/v1/settings/ini/{name}</code>) or, on Linux, with <code>hmailserver --set-setting NAME=VALUE</code>. At the defaults, <code>AVFailAction</code> 1 gives a message about four hours to be scanned before its sender is told. The hold counter is the policy's own, not the message's try counter, because incrementing that would make the pass that finally scans the message skip DKIM signing. It lives in memory, so a restart gives every held message a fresh budget, and it is bounded at 100,000 tracked messages; beyond that messages are still held, never delivered unscanned, and <code>HM6195</code> is reported. Every scanner error is reported as <code>HM5406</code> with the failing scanner's own text.</p>
<h3><a class="anchor-offset" name="blocked-attachments"></a>Blocked attachments</h3>
<p dir="auto"><strong>Spam &amp; virus filtering → Blocked attachments</strong> refuses files by name pattern. The master switch is <code>AntiVirus.EnableAttachmentBlocking</code>, default off. The wiki's starting list:</p>
<pre><code class="language-text">*.exe   *.scr   *.pif   *.bat   *.cmd   *.com   *.vbs
*.js    *.jse   *.wsf   *.wsh   *.hta   *.jar   *.msi
*.msp   *.cpl   *.lnk   *.reg   *.ps1   *.iso   *.img
</code></pre>
<p dir="auto"><strong>The attachment is not deleted.</strong> Its file name has <code>.txt</code> appended and its content is replaced by the <code>ATTACHMENT_REMOVED</code> server message, which names the original file through the <code>%MACRO_FILE%</code> macro, so the recipient receives <code>invoice.exe.txt</code> containing an explanation. Matching is a case-insensitive wildcard over the declared file name. It does not look inside archives and cannot see the real type of a file whose extension lies: it is a policy control, not a scanner.</p>
<p dir="auto"><strong>Since 6.3.4 the rewrite is logged.</strong> A rewritten message produces <code>VirusScanner - Message 1234 from a@example.com: the attachment(s) invoice.exe matched the blocked-attachment list. Their content has been replaced with a notice and the message rewritten.</code> Before this the rewrite left no record anywhere but inside the message itself.</p>
<h3><a class="anchor-offset" name="sealed-mail-what-the-list-and-the-scanner-do-with-it"></a>Sealed mail: what the list and the scanner do with it</h3>
<p dir="auto"><em>Since 6.3.4.</em> A message encrypted end to end, S/MIME or PGP/MIME, is <strong>opaque</strong> to the server, which decides that from the body, never from the <code>Content-Type</code> label, so a message only labelled encrypted is blocked, stripped and scanned like any other. What opaque means exactly, and what the rest of the server does with such a message, is in <a href="/topic/28260">the topic on end-to-end encryption and sealed mail</a>. For the list and the scanner, none of it is a setting:</p>
<ul>
<li><strong>The blocked-attachment list never rewrites an opaque message.</strong> In 6.3.3 and earlier blocking <code>*.asc</code>, <code>*.p7m</code>, <code>*.p7s</code> or <code>*.*</code> replaced the content of every sealed message with the notice, with no log line, and the plaintext existed nowhere else. It is now delivered as it arrived, and the application log says it was not checked against the list. A signed message is checked like any other, with its detached signature left alone.</li>
<li><strong>The scanner still scans it, and what it examines is ciphertext</strong>, so a clean result is not a verdict on the message; the log says its content <code>COULD NOT BE EXAMINED for viruses</code>. It is deliberately not treated as a scanner failure, so a server with <code>AVFailAction</code> 1 does not hold every encrypted message it receives; a policy that unscannable mail must not be delivered belongs in a rule or a Sieve script, not the scanner.</li>
<li><strong>The "delete attachments" action never strips an encrypted message.</strong> When the scanner objects to one, the message is left as it arrived and the log ends <em>Set the anti-virus action to delete the message if such a message must not be delivered</em>. That is not a quiet pass: the message still carries what the scanner objected to. To 6.3.6 this held for every opaque message; since 6.3.7 an S/MIME message signed as one part (<code>application/pkcs7-mime</code> holding signed-data, which is opaque but not encrypted) is replaced by the action's note, as any other single-part attachment is.</li>
</ul>
<h3><a class="anchor-offset" name="the-sandbox"></a>The sandbox</h3>
<p dir="auto"><em>Since 6.3.4 (schema 6091).</em> ClamAV says whether a file is known to be bad. What an unknown file does when it is opened takes a sandbox, a service outside this server which you run or subscribe to. <strong>It does nothing until you name one</strong>: <code>SandboxEnabled</code> is off, and cannot be saved on while <code>SandboxSubmitUrl</code> or <code>SandboxVerdictUrl</code> is empty. Both addresses must be https, or plain http to this machine.</p>
<p dir="auto">After the anti-virus scan and before the rules, a message that no signed-in user of this server submitted, with an attachment whose extension or media type is in <code>SandboxTypes</code>, is <strong>held</strong>: in no mailbox, not in the quarantine, and in nobody's digest. The default types are:</p>
<pre><code>exe,dll,scr,js,jse,vbs,wsf,hta,msi,bat,cmd,ps1,jar,lnk,iso,img,docm,xlsm,pptm,
doc,xls,ppt,rtf,pdf,zip,7z,rar
</code></pre>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>The sandbox says</th>
<th>What happens</th>
</tr>
</thead>
<tbody>
<tr>
<td>every file clean</td>
<td>delivered, with an <code>X-hMailServer-Sandbox</code> header reading <code>clean (&lt;n&gt; file(s), &lt;seconds&gt;s)</code></td>
</tr>
<tr>
<td>any file malicious, or suspicious at or above <code>SandboxScoreThreshold</code> (70)</td>
<td>quarantined with the verdict as the reason; returned to its sender with 5.7.1 while <code>QuarantineEnabled</code> is off</td>
</tr>
<tr>
<td>an error, once every file has answered, or no answer within <code>SandboxTimeoutMinutes</code> (15)</td>
<td><code>SandboxTimeoutAction</code>: <code>deliver</code> (0, the default) delivers with a header saying so; <code>bounce</code> (1) returns it to its sender</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The contract.</strong> One POST per file to <code>SandboxSubmitUrl</code> as <code>multipart/form-data</code> with four fields (<code>file</code>, <code>filename</code>, <code>sha256</code>, <code>message_id</code>), then a GET to <code>SandboxVerdictUrl</code> every <code>SandboxPollSeconds</code> (30), answered with JSON such as <code>{"state":"done","verdict":"clean","score":3,"detail":"opened, nothing happened"}</code>. With <code>SandboxToken</code> set, every request carries <code>Authorization: Bearer &lt;token&gt;</code>; the token is not in the backup archive. <strong>No vendor adapter is shipped.</strong> The document notes that a service which shares what it is sent, as VirusTotal shares uploads with its subscribers, is a place the attachments of the mail you receive go.</p>
<p dir="auto"><strong>What is exempt.</strong> What your own signed-in users submit (authenticated SMTP, the webmail, the send API) is not uploaded unless <code>SandboxInternalMail</code> is on. The document states the threat model of that default: a stolen password used to send attachments to colleagues is not examined by the sandbox, though ClamAV, the blocked-attachment list and compromised-account detection still apply.</p>
<p dir="auto"><strong>Limits.</strong> An attachment larger than <code>SandboxMaxSizeKB</code> (20480) is not submitted. A message with more files to submit than <code>SandboxMaxFiles</code> (10) is not held, and <code>SandboxTimeoutAction</code> decides it at once. Archives are submitted whole; links are not opened anywhere. A clean or malicious verdict is remembered by the file's SHA-256 for <code>SandboxCacheHours</code> (24), server-wide.</p>
<p dir="auto"><strong>What the administrator sees.</strong> <code>GET /api/v1/sandbox/held</code> lists what is held; <code>POST /api/v1/sandbox/held/{queue_id}/release</code> delivers without the verdict and <code>DELETE /api/v1/sandbox/held/{queue_id}</code> discards, both on the audit trail. The Control Deck's queue page has a <em>Held for a sandbox</em> box, and <code>hmctl queue list</code> has a <code>held</code> column. The settings are on the Control Panel's Anti-virus page, <em>Sandbox</em> tab (Windows only), and on <code>PUT /api/v1/settings</code>.</p>
<h3><a class="anchor-offset" name="rules-and-the-message-store"></a>Rules, and the message store</h3>
<p dir="auto">Since 6.3.4 the mail flow rules can match the attachment's name and, in the outbound content policy, its type read from its bytes, so a rule can hold or refuse what the blocked-attachment list would only rename; that is in <a href="/topic/28251">the topic on mail flow rules</a>. <a href="/topic/28233">The message store options added in 6.3.4</a> change nothing for a scanner: a message is scanned as plain RFC 822 in the queue and only placed in the mailbox in its stored form afterwards. A scanner pointed at the data directory from outside the server reads a compressed or encrypted container, not a message.</p>
<h3><a class="anchor-offset" name="error-codes"></a>Error codes</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Code</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>HM5406</code></td>
<td>An enabled scanner errored; the detail names the scanner and the failure</td>
</tr>
<tr>
<td><code>HM6001</code></td>
<td>The message could not be parsed, so only the whole file was scanned</td>
</tr>
<tr>
<td><code>HM6002</code></td>
<td>An attachment could not be written to the temp directory for scanning</td>
</tr>
<tr>
<td><code>HM6195</code></td>
<td>100,000 messages are already held for want of a scan; further holds are not counted</td>
</tr>
<tr>
<td><code>HM7272</code></td>
<td>The sandbox called a message malicious and the quarantine could not store it; it is held again, never delivered</td>
</tr>
</tbody>
</table>
<h3><a class="anchor-offset" name="where-to-read-more"></a>Where to read more</h3>
<ul>
<li>Wiki: <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Stopping-Viruses" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/wikis/Stopping-Viruses</a></li>
<li><a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Sandbox.md" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Sandbox.md</a></li>
<li><a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SealedMail.md" rel="nofollow ugc">https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SealedMail.md</a></li>
<li>Public documentation: <a href="https://www.progressiverobot.com/hmailserver-documentation/#11-stopping-viruses" rel="nofollow ugc">https://www.progressiverobot.com/hmailserver-documentation/#11-stopping-viruses</a>, <a href="https://www.progressiverobot.com/hmailserver-documentation/#111-clamav" rel="nofollow ugc">https://www.progressiverobot.com/hmailserver-documentation/#111-clamav</a> and <a href="https://www.progressiverobot.com/hmailserver-documentation/#112-blocked-attachments" rel="nofollow ugc">https://www.progressiverobot.com/hmailserver-documentation/#112-blocked-attachments</a></li>
<li><a href="/topic/28193">Upgrading to 6.3.4</a> and <a href="/topic/28218">the 6.3.4 security announcement</a></li>
</ul>
]]></description><link>https://www.hmailserver.co.uk/topic/28250/viruses-and-dangerous-attachments-clamav-custom-scanners-the-sandbox-sealed-mail</link><generator>RSS for Node</generator><lastBuildDate>Fri, 06 Nov 2026 09:05:53 GMT</lastBuildDate><atom:link href="https://www.hmailserver.co.uk/topic/28250.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Sep 2026 19:32:13 GMT</pubDate><ttl>60</ttl></channel></rss>