---
name: "Courier::Filter::Module::Parts"
section: "3pm"
platform: "linux"
package: "courier-filter-perl"
version: "0.200+ds-6"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Courier::Filter::Module::Parts"
---

# Courier::Filter::Module::Parts(3pm)

Message (MIME multipart and ZIP archive) parts filter module for the Courier::Filter framework

## NAME

Courier::Filter::Module::Parts - Message (MIME multipart and ZIP archive) parts filter module for the Courier::Filter framework

## SYNOPSIS

```
    use Courier::Filter::Module::Parts;

    my $module = Courier::Filter::Module::Parts->new(
        max_message_size
                        => $max_message_size,
        max_part_size   => $max_part_size,
        views           => ['raw', 'zip'],
        signatures      => [
            {
                # One or more of the following options:
                mime_type       => 'text/html' || qr/html/i,
                file_name       => 'file_name.ext' || qr/\.(com|exe)$/i,
                size            => 106496,
                digest_md5      => 'b09e26c292759d654633d3c8ed00d18d',
                encrypted       => 0,

                # Optionally any of the following:
                views           => ['raw', 'zip'],
                response        => $response_text
            },
            ...
        ],

        logger          => $logger,
        inverse         => 0,
        trusting        => 0,
        testing         => 0,
        debugging       => 0
    );

    my $filter = Courier::Filter->new(
        ...
        modules         => [ $module ],
        ...
    );
```

## DESCRIPTION

This class is a filter module class for use with Courier::Filter.  It matches a message if one of the message's parts (MIME parts, or files in a ZIP archive) matches one of the configured signatures.

### Constructor

The following constructor is provided:

- **new(%options)**: returns *Courier::Filter::Module::Parts*

  Creates a new **Parts** filter module.

  `%options` is a list of key/value pairs representing any of the following options:

  - **views**

    An arrayref containing the global default set of *views* the filter module should apply to message parts when matching the configured signatures against them.  A view is the way how a MIME part's (MIME-decoded) data is interpreted. Defaults to **\['raw'\]**.

    The following views are supported:

    - **raw**

      The MIME part is MIME-decoded but not otherwise transformed.  The raw MIME part is then matched against the configured signatures.

    - **zip**

      If the MIME part has a file name ending in `".zip"`, it is considered a ZIP archive, and all unencrypted files in the archive are matched as individual message parts against the configured signatures.  The zip view requires the **Archive::Zip** Perl module to be installed.

  - **max\_message\_size**

    - **max\_size** (DEPRECATED)

    An integer value controlling the maximum size (in bytes) of the overall message text for a message to be processed by this filter module.  Messages larger than this value will never be processed, and thus will never match.  If **undef**, there is no size limit.  Defaults to **1024\*\*2** (1MB).

    As MIME multipart and ZIP archive processing can be quite CPU- and memory-intensive (although the **Parts** filter module makes use of temporary files since version 0.13), you should definitely restrict the message size to some sensible value that easily fits in your server's memory.  1024\*\*2 (1MB) should be appropriate for most uses of this filter module.

    The `"max_message_size"` option was previously called `"max_size"`, but the latter is now deprecated and may not be supported in future versions of the **Parts** filter module.

  - **max\_part\_size**

    An integer value controlling the maximum size (in bytes) of any single message part (i.e. MIME part in a message, or file in an archive) for that part to be processed by this filter module.  Parts larger than this value will never be processed, and thus will never match.  If **undef**, there is no size limit.

    Defaults to the value of the `"max_message_size"` option, so you don't really need to specify a part size limit if you are comfortable with using the same value for both.  See the `"max_message_size"` option for its default.

    If you make use of the **'zip'** view, be aware of the risk posed by so-called *decompression bombs*, which allow messages to easily fall below the overall message size limit, while a file in a small attached ZIP archive can decompress to a huge size.  The part size limit prevents huge files from being decompressed.

  - **signatures**

    *Required*.  A reference to an array containing the list of *signatures* against which message parts are to be matched.  A signature in turn is a reference to a hash containing one or more so-called signature *aspects* (as key/value pairs) and any signature *options* (also as key/value pairs).

    *Signature aspects*

    Aspects may either be scalar values (for exact, case-sensitive matches), or regular expression objects created with the `"qr//"` operator (for inexact, partial matches).  For a signature to match a message part, *all* of the signature's specified aspects must match those of the message part.  For the filter module to match a message, *any* of the signatures must match *any* of the message's parts.

    A signature aspect can be any of the following:

    - **mime\_type**

      The MIME type of the message part ('type/sub-type').

    - **file\_name**

      The file name of the message part.

    - **size**

      The exact size (in bytes) of the decoded message part.

    - **digest\_md5**

      The MD5 digest of the decoded message part (32 hex digits, as printed by \`md5sum\`).

    - **encrypted**

      A boolean value denoting whether the message part is encrypted and its contents are inaccessible to the **Parts** filter module.

    *Signature options*

    A signature option can be any of the following:

    - **views**

      An arrayref containing the set of *views* the filter module should apply to message parts when matching *this* signature against them.  For a list of supported views, see the description of the constructor's `"views"` option. Defaults to the global set of views specified to the constructor.

    - **response**

      A string that is to be returned as the match result in case of a match. Defaults to **"Prohibited message part detected."**.

    *Example*

    So for instance, a signature list could look like this:

    ```
        signatures  => [
            {
                mime_type   => qr/html/i,
                response    => 'No HTML mail, please.'
            },
            {
                file_name   => qr/\.(com|exe|lnk|pif|scr|vbs)$/i,
                response    => 'Executable content detected'
            },
            {
                size        => 106496,
                digest_md5  => 'b09e26c292759d654633d3c8ed00d18d',
                views       => ['raw', 'zip'],  # Look into ZIP archives, too!
                response    => 'Worm detected: W32.Swen'
            },
            {
                size        => 22528,
                # Cannot set a specific digest_md5 since W32.Mydoom
                # is polymorphic.
                response    => 'Worm suspected: W32.Mydoom'
            },
            {
                encrypted   => 1,
                views       => ['zip'],
                response    => 'Worm suspected ' .
                               '(only worms and fools use ZIP encryption)'
            }
        ]
    ```

  All options of the **Courier::Filter::Module** constructor are also supported by the constructor of the **Parts** filter module.  Please see "new" in Courier::Filter::Module for their descriptions.

### Instance methods

See "Instance methods" in Courier::Filter::Module for a description of the provided instance methods.

## SEE ALSO

Courier::Filter::Module, Courier::Filter::Overview.

For AVAILABILITY, SUPPORT, and LICENSE information, see Courier::Filter::Overview.

## AUTHOR

Julian Mehnle \<julian@mehnle.net\>
