NAME

Mail::SpamAssassin::Handler::Image - A MIME-part handler for image/* parts

SYNOPSIS

loadhandler Mail::SpamAssassin::Handler::Image

imagetext  RULE_NAME  /pattern/modifiers

body  IMAGE_TEXT_HEAVY  eval:check_image_text_ratio('0.75')
describe IMAGE_TEXT_HEAVY  Most of the body text came from images

DESCRIPTION

A handler that registers itself as the MIME-part handler for image/* parts, runs the tesseract OCR engine on them, and injects the recognised text into the message body, so ordinary body rules can match text that would otherwise be hidden inside an image.

It also provides the imagetext rule type, which matches a regular expression specifically against the OCR'd image text:

imagetext  RULE_NAME  /pattern/modifiers

These rules behave like body rules and support the multiple and maxhits=N tflags. By default a rule stops at its first match.

TFLAGS

multiple

Match the rule more than once (for use with meta rules counting hits).

maxhits=N

With multiple, stop after N hits.

CONFIGURATION

image_tesseract_path /path/to/tesseract

Full path to the tesseract executable. If unset, the plugin looks for tesseract on the PATH. If it cannot be found OCR is disabled with a warning, so --lint never fails merely because the binary is absent.

image_ocr_lang eng

Language(s) passed to tesseract -l (default eng).

image_heif_convert_path /path/to/heif-convert

Full path to heif-convert (from libheif), used to convert HEIF/HEIC images to PNG before OCR, since tesseract cannot read HEIF natively. If unset, the plugin looks for heif-convert on the PATH. If it is unavailable, HEIF images are skipped while all other image types are still OCR'd. The real image type is detected from the file's leading bytes, not its declared Content-Type, so a HEIF image mislabelled as e.g. image/png is still handled.

image_ocr_min_width N (default: 0)

Skip OCR for any image narrower than N pixels. Small images (logos, icons, spacers, tracking pixels) rarely contain readable text, so this avoids wasting tesseract on them. 0 disables the check. Dimensions are read from the image header (PNG, JPEG, GIF, WebP, BMP); when they cannot be determined the image is OCR'd anyway, so this is a best-effort optimisation, not an anti-evasion control.

image_ocr_min_height N (default: 0)

As image_ocr_min_width, but for image height. 0 disables the check. An image is skipped if it is below either the minimum width or the minimum height.

check_image_text_ratio(MIN_RATIO)

Eval rule: true if the fraction of the message's body text that came from images is greater than or equal to MIN_RATIO. The numerator is the number of words OCR'd from all image parts; the denominator is the total number of words in the rendered body (which, since OCR text is injected into the body, includes those image words). A high fraction means the readable content is mostly text rendered as a picture -- a classic image-spam evasion. MIN_RATIO is a fraction from 0 to 1 and defaults to 0.5.