Mail::...PDFInfo(3pm)

πŸ’– NAME πŸ’–

Mail::SpamAssassin::Plugin::PDFInfo β€” bestie, this is the SpamAssassin plugin that catches spam by staring real hard at the PDF files people attach to your mail. It's the plugin page from the User Contributed Perl Documentation collection, section 3pm of the manual, and yes she's a whole vibe. πŸŽ€


✨ SYNOPSIS ✨

loadplugin     Mail::SpamAssassin::Plugin::PDFInfo

That's it. One line and she's loaded into your config. Slay. πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

So this plugin exists to help detect spam using attached PDF files. That's the whole mission statement, no cap. πŸ“„βœ‹

And then it says: see "Usage:" below β€” and for more documentation go look at 20_pdfinfo.cf.

After that, the page just keeps a big ol' slab of original info for the history books, because the maintainers are sentimental like that. For later changes you go check the SVN repo. Here's the vintage text, preserved exactly as she was born, no edits, no filter, iconic behavior:

Original info kept for history. For later changes see SVN repo
-------------------------------------------------------
PDFInfo Plugin for SpamAssassin
Version: 0.8
Info: $Id: PDFInfo.pm 904 2007-08-12 01:36:23Z root $
Created: 2007-08-10
Modified: 2007-08-10
By: Dallas Engelken

Changes:
  0.8 - added .fdf detection (thanks John Lundin) [axb]
  0.7 - fixed empty body/pdf count buglet(thanks Jeremy) [axb]
  0.6 - added support for tags - PDFCOUNT, PDFVERSION, PDFPRODUCER, etc.
      - fixed issue on perl 5.6.1 where pdf_match_details() failed to call
        _find_pdf_mime_parts(), resulting in no detection of pdf mime parts.
      - quoted-printable support - requires MIME::QuotedPrint (which should be in everyones
        install as a part of the MIME-Base64 package which is a SA req)
      - added simple pdf_is_empty_body() function with counts the body bytes minus the
        subject line.  can add optional <bytes> param if you need to allow for a few bytes.
  0.5 - fix warns for undef $pdf_tags
      - remove { } and \ before running eval in pdf_match_details to avoid eval error
  0.4 - added pdf_is_encrypted() function
      - added option to look for image HxW on same line
  0.3 - added 2nd fuzzy md5 which uses pdf tag layout as data
      - renamed pdf_image_named() to pdf_named()
         - PDF images are encapsulated and have no names.  We are matching the PDF file name.
      - renamed pdf_image_name_regex() to pdf_name_regex()
         - PDF images are encapsulated and have no names.  We are matching the PDF file name.
      - changed pdf_image_count() a bit and added pdf_count().
         - pdf_count() checks how many pdf attachments there are on the mail
         - pdf_image_count() checks how many images are found within all pdfs in the mail.
      - removed the restriction of the pdf containing an image in order to md5 it.
      - added pdf_match_details() function to check the following 'details'
         - author: Author of PDF if specified
         - producer: Software used to produce PDF
         - creator: Software used to produce PDF, usually similar to producer
         - title: Title of PDF
         - created: Creation Date
         - modified: Last Modified
  0.2 - support PDF octet-stream
  0.1 - just ported over the imageinfo code, and renamed to pdfinfo.
        - removed all support for png, gif, and jpg from the code.
        - prepended pdf_ to all function names to avoid conflicts with ImageInfo in SA 3.2.

she's been through eight glow-ups and every single one ate πŸ‘‘

🌸 Usage: 🌸

Okay bestie, here's the menu of eval functions you can call from your rules. Each one goes in a body rule with a RULENAME you pick, like:

body RULENAME  eval:pdf_count(<min>,[max])

Let's go one by one, no skipping, I know you'd never. 🫢

πŸ’œ pdf_count()

body RULENAME  eval:pdf_count(<min>,[max])
  • min: required β€” the message contains at least x pdf mime parts.
  • max: optional β€” if you specify it, the message must not contain more than x pdf mime parts.

πŸ’œ pdf_image_count()

body RULENAME  eval:pdf_image_count(<min>,[max])
  • min: required β€” the message contains at least x images in pdf attachments.
  • max: optional β€” if you specify it, it must not contain more than x pdf images.

πŸ’œ pdf_uri_count()

body RULENAME  eval:pdf_uri_count(<min>,[max])
  • min: required β€” the message contains at least x uris in pdf attachments.
  • max: optional β€” if you specify it, it must not contain more than x pdf uris.

πŸ’œ pdf_pixel_coverage()

body RULENAME  eval:pdf_pixel_coverage(<min>,[max])
  • min: required β€” the message contains at least this much pixel area.
  • max: optional β€” if you specify it, the message must not contain more than this much pixel area.

πŸ’œ pdf_named()

body RULENAME  eval:pdf_named(<string>)
  • string: exact file name match. If you need a partial match, go see pdf_name_regex() instead, bestie, they're a duo. ✌️

πŸ’œ pdf_name_regex()

body RULENAME  eval:pdf_name_regex(<regex>)
  • regex: a regular expression β€” peep the examples in the ruleset.

πŸ’œ pdf_match_md5()

body RULENAME  eval:pdf_match_md5(<string>)
  • string: 32-byte md5 hex.

πŸ’œ pdf_match_fuzzy_md5()

body RULENAME  eval:pdf_match_fuzzy_md5(<string>)
  • string: 32-byte md5 hex β€” see the ruleset for how to obtain the fuzzy md5.

πŸ’œ pdf_match_details()

body RULENAME  eval:pdf_match_details(<detail>,<regex>);
  • detail: author, creator, created, modified, producer, title
  • regex: a regular expression β€” see the examples in the ruleset.

πŸ’œ pdf_is_encrypted()

body RULENAME eval:pdf_is_encrypted()

πŸ’œ pdf_has_form()

body RULENAME eval:pdf_has_form()

πŸ’œ pdf_has_script()

body RULENAME eval:pdf_has_script()

πŸ’œ pdf_has_auto_script()

body RULENAME eval:pdf_has_auto_script()

πŸ’œ pdf_is_empty_body()

body RULENAME eval:pdf_is_empty_body(<bytes>)
  • bytes: maximum byte count to allow and still consider it empty.

πŸ’œ pdf_image_to_text_ratio()

body RULENAME eval:pdf_image_to_text_ratio(<min>,<max>)
  • Ratio calculated as body_length / total_image_area
  • min: minimum ratio
  • max: maximum ratio

πŸ’œ pdf_image_size_exact()

body RULENAME eval:pdf_image_size_exact(<h>,<w>)
  • h: image height is exactly h
  • w: image width is exactly w

πŸ’œ pdf_image_size_range()

body RULENAME eval:pdf_image_size_range(<minh>,<minw>,[<maxh>],[<maxw>])
  • minh: image height is atleast minh
  • minw: image width is atleast minw
  • maxh: (optional) image height is no more than maxh
  • maxw: (optional) image width is no more than maxw
NOTE: See the ruleset for more examples that are not documented here. πŸ‘€ The plugin is lowkey keeping secrets from this manual and honestly? relatable.

and that's the whole page, periodt. πŸŽ€ This little legend came to you from perl v5.40.1, dated 2026-07-23, and it lives under Mail::...PDFInfo(3pm). Take care of her, she's been catching bad PDFs since 2007. πŸ¦‹πŸ’–πŸ‘‘

πŸ“¦ where this page comes from