MAILMUNGE(8)

πŸ“¦ version 3.20, in alpine 3.24

πŸ’Œ MAILMUNGE(8) β€” aka mailmunge(8), and we're making it make sense πŸ’Œ

User Contributed Perl Documentation realness, bestie. This is the MAILMUNGE(8) page, and it's giving "the boss behind the scenes" energy. Let's get into it.

🌸 NAME 🌸

mailmunge β€” Milter for writing mail policy in Perl

πŸŽ€ SYNOPSIS πŸŽ€

okay so the two shapes this command takes are literally:

mailmunge prcap

mailmunge -p connection -m mx_socket_name -U user [options]

That's the vibe check. prcap is its own little solo era; the second line is the main-character invocation.

πŸ’– DESCRIPTION πŸ’–

So mailmunge is a filter built around Sendmail 8.11 and later's Milter API for mail filters. It lets you write Milter filtering policy in Perl. Perl girlies rise πŸ’…

But plot twist: mailmunge does not actually run the Perl filter. Instead, it communicates with mailmunge-multiplexor, which manages a pool of persistent Perl processes. See the mailmunge-multiplexor man page for additional information. That's the whole "I don't do the work, I know the people who do" situation.

✨ OPTIONS ✨

If you invoke mailmunge with the single argument prcap, it prints information about the version of Milter it is linked against and exits. Otherwise, you should invoke mailmunge as shown in the second line of the SYNOPSIS. Yes bestie, that line matters.

  • -C β€” conserve file descriptors by opening and closing disk files more often. Disk files will be closed when a Milter callback ends and reopened when another callback is invoked. While this shortens the length of time a file descriptor is open, it also leaves more opportunities for the open to fail. We do not recommend the use of this flag except on very busy systems that exhibit failures due to a shortage of file descriptors.
  • -D β€” do not fork into the background and become a daemon. Instead, stay in the foreground. Useful mainly for debugging or if you have a supervisory process such as systemd managing mailmunge.
  • -G β€” normally, mailmunge uses a umask of 077 when creating the milter socket and files. If you would like the socket to be readable and writeable by the group and files to be group-readable, supply the -G option. This causes the umask to be 007 whenever UNIX-domain sockets are created and 027 whenever files are created. Note: if your milter library is too old to have the smfi_opensocket function, the -G option causes mailmunge to use a umask of 007 throughout its execution.
  • -H β€” causes mailmunge to perform a HELO check when the SMTP client issues a HELO or EHLO command. It causes the filter's filter_helo method to be invoked. (See Mailmunge::Filter for details.)
  • -N β€” normally, mailmunge sees all envelope recipients, even ones that Sendmail knows to be invalid. If you don't want Sendmail to perform a milter callback for recipients it knows to be invalid, invoke mailmunge with the -N flag. Please note that this flag only works with Sendmail and Milter 8.14.0 and newer. It has no effect if you're running an older version of Sendmail or Milter.
  • -P fileName β€” causes mailmunge to write its process-ID (after becoming a daemon) to the specified file. The file will be owned by root.
  • -Q num β€” sets the libmilter debug level using smfi_setdbg. Useful values of num are 0 (no debugging) through 6 (extensive debugging.) The libmilter log lines will be prefixed by milter-mailmunge-3.20.
  • -R num β€” normally, mailmunge tempfails a new SMTP connection if there are no free workers. Supplying the -R num option makes mailmunge tempfail new connections if there are fewer than num free workers, unless the connection is from the local host. This allows you to favour connections from localhost so your clientmqueue doesn't build up. Note that supplying -R 0 is subtly different from omitting the option; in this case, mailmunge permits new connections from localhost to queue, but not connections from other hosts (unless you also supply the -q option.)

The purpose of the -R option is to reserve resources for clientmqueue runs. Otherwise, on a very busy mail server, clientmqueue runs can starve for a long time, leading to delays for locally-generated or streamed mail. We recommend using a small number for num; probably no more than 3 or 10% of the total number of workers (whichever is smaller.)

Note that this option and the -q option are mutually-exclusive. If you supply -q, then -R is ignored.

  • -S facility β€” specifies the syslog facility for log messages. The default is mail. See the openlog man page for a list of valid facilities. You can use either the short name (mail) or long name (LOG_MAIL) for the facility name.
  • -T β€” causes mailmunge to log the run-time of the Perl filter using syslog.
  • -U user β€” runs mailmunge as user rather than root. The user argument must match the argument to mailmunge-multiplexor's -U option as well.
  • -X β€” do not add an X-Scanned-By: header. Specifying -X is equivalent to specifying -x "".
  • -a macro β€” pass the value of the specified Sendmail macro through to the Perl filter. You can repeat the -a option to write more macros than the built-in defaults. Note that in addition to asking mailmunge to pass the macro value to the filter, you must configure Sendmail to pass the macro through to mailmunge using the confMILTER_MACROS_ENVFROM definition in Sendmail's m4 configuration file.
  • -b backlog β€” sets the backlog argument to the listen system call to backlog. If this option is omitted, then the operating-system default backlog is used.
  • -c β€” strip "bare" carriage-returns (CR) characters from the message body. A bare CR should never appear in an e-mail message. Older versions of mailmunge used to strip them out automatically, but now they are left in by default. The -c option enables the older behavior.
  • -d β€” the -d switch causes mailmunge not to delete the temporary spool files it creates for incoming messages. This is for debugging purposes only and should never be used on a production mail server.
  • -h β€” print usage information and exit.
  • -k β€” causes mailmunge not to delete working directories if a filter fails. This lets you obtain the message which caused the filter to fail and determine what went wrong. mailmunge logs the directory containing the failed message using syslog.
  • -m mx_socket_name β€” specifies the socket for communicating with mailmunge-multiplexor. The mx_socket_name specifies the path of the UNIX-domain socket. See mailmunge-multiplexor for details and SOCKET SPECIFICATION for the format of mx_socket_name.
  • -o fileName β€” causes mailmunge to use fileName as a lock file to avoid multiple instances from running. If you supply -P but not -o, then mailmunge constructs a lock file by appending .lock to the pid file. However, this is less secure than having a root-owned pid file in a root-owned directory and a lock file writable by the user named by the -U option. (The lock file must be writable by the -U user.)
  • -p connection β€” the -p switch is required and specifies the milter connection type. Typically, you should run mailmunge on the same computer as sendmail. Therefore, you may use a UNIX-domain socket or an INET socket for the connection type. The suggested value for the -p switch is mailmunge.sock under the spool directory if you are running Sendmail, or an INET socket on a convenient port if you are running Postfix. Postfix often runs in a chroot environment, so using UNIX-domain sockets is a problem if the socket is not in Postfix's chroot jail.

The format of connection is determined by the Sendmail Milter library, and is one of the following:

  • unix:/path/to/file β€” a local UNIX-domain socket.
  • local:/path/to/file β€” the same thing as unix:/path/to/file.
  • /path/to/file β€” the same thing as unix:/path/to/file.
  • inet:port[@host] β€” listen on the TCP port port over IPv4. If the @host portion is given, listen on the specified address. Normally, you should listen only on the localhost address and should specify a Milter TCP socket as inet:port@127.0.0.1.
  • inet6:port[@host] β€” similar to inet:port[@host], but use an IPv6 socket.
  • -q β€” permits the multiplexor to queue new connections. See the section QUEUEING REQUESTS in the mailmunge-multiplexor man page. Note that this option and the -R option are mutually-exclusive. If you supply -q, then -R is ignored.
  • -r β€” causes mailmunge to perform a relay check before processing any messages. It causes the filter's filter_relay method to be invoked. (See Mailmunge::Filter for details.)
  • -s β€” causes mailmunge to perform a sender check before processing the message body. It causes the filter's filter_sender method to be invoked. (See Mailmunge::Filter for details.)
  • -t β€” causes mailmunge to perform recipient checks before processing the message body. It causes the filter's filter_recipient method to be invoked. (See Mailmunge::Filter for details.)
  • -x string β€” add string as the content of the X-Scanned-By: header. If you set string to the empty string (i.e. -x ""), then no X-Scanned-By: header will be added.
  • -y β€” if the -y command-line option is given, Mailmunge will call smfi_setsymlist to set the list of macros it wants. This function leaked memory in versions of libmilter shipped with Sendmail prior to 8.16.1 so by default we do not call it. If you are running an older version of sendmail, you should explicitly set the list of macros you want in the Sendmail configuration file.
  • -z spooldir β€” set the spool directory to spooldir. If this option is omitted, the spool directory defaults to /var/spool/mailmunge.

πŸ”Œ SOCKET SPECIFICATION πŸ”Œ

The -m option takes a socket as an argument. This socket can be specified as:

  • /path/to/socket β€” a UNIX-domain socket.
  • inet:portnum β€” a TCP socket bound to port portnum, but that accepts connections only from the IPv4 loopback address (127.0.0.1).
  • inet_any:portnum β€” a TCP socket bound to port portnum that will accept connections from any address. Use inet_any with caution!
  • inet6:portnum β€” a TCP socket bound to port portnum listening on the IPv6 loopback address.
  • inet6_any:portnum β€” a TCP socket bound to port portnum listening on the IPv6 wildcard address.

πŸŽ€ OPERATION πŸŽ€

okay so here's the whole pipeline, bestie, and honestly it's giving elegant 😭✨

When mailmunge starts up, it creates a listening socket β€” and this is the socket that Sendmail or Postfix connects to. The MTA talks to mailmunge using the Milter protocol. That's the whole handshake situation. 🫢

For each incoming message, mailmunge creates a temporary directory and saves information in that directory. Like, per-message temp dir, no sharing, no chaos. πŸ’…

Then, at various phases during the SMTP conversation, mailmunge communicates with mailmunge-multiplexor to perform various operations. So mailmunge is basically the go-between β€” it's not doing the scanning itself, it's coordinating. icon behavior, fr fr πŸ‘‘

And mailmunge-multiplexor? It manages a pool of persistent Perl processes that actually perform the mail scanning operations. Persistent = they stick around, they don't get reincarnated for every single email, which is lowkey the whole reason this design slaps πŸ”₯

After all that, mailmunge communicates the results of those operations back to the MTA over the milter socket. Full circle. The MTA asked, the MTA received. periodt πŸ’–

One more thing β€” when a Perl process scans an e-mail, the temporary spool directory contains certain files. The details of the communication protocol between mailmunge and the Perl script? Those live in mailmunge-protocol. Go read it, iykyk πŸ“–βœ¨


πŸ’– SEE ALSO πŸ’–

  • Mailmunge
  • mailmunge-multiplexor
  • mailmunge-protocol

the whole squad, all linked up, all iconic 🌈

✨ AUTHOR ✨

mailmunge was written by Dianne Skoll <dianne@skollsoft.com>. absolute legend behavior, we stan πŸ‘‘πŸ’œ

🌸 LICENSE 🌸

This code is licensed under the terms of the GNU General Public License, version 2. That's the legal tea, bestie β˜• β€” GPLv2, no cap πŸŽ€


and that's the page!! πŸ¦‹ this one came from perl v5.42.2, dated 2025-10-05 β€” like, that's the version and the date of the doc itself, cute right? take care of your mail server and it'll take care of you πŸ’Œβœ¨ mwah! πŸ“

πŸ“¦ where this page comes from