Home / Alt manpages / pam_mail(8)

  • pam_mail(8)
  • Admin command
  • linux

Show New Mail at Login with pam_mail

By the end of this guide, a PAM-managed login will report whether the user has mail and, unless you disable it, expose the mail spool through the MAIL PAM environment variable. The examples match the installed Linux-PAM module on this machine, from Ubuntu package libpam-modules 1.5.3-5ubuntu5.7.

Allow about 10 minutes. You need root access to edit a PAM service file and a test account whose login session you can reopen. This module reports mail; it does not fetch messages, deliver mail, or create a mailbox.

1. Check the current spool layout

The default location is /var/mail/<login>. Before changing PAM, check whether that path exists and whether it is a regular spool file or a Maildir directory. Replace alice with the account you will test.

$ getent passwd alice
$ sudo ls -ld /var/mail/alice

These are ordinary, read-only checks. A directory is treated as Maildir by pam_mail. A regular file is treated as the traditional mailbox spool. Do not create an empty mailbox merely to make the check pass: the module can also report that the user has no mail when the empty option is used.

2. Add the module to the right PAM service

PAM configuration is service-specific. The service named in /etc/pam.d/ must be the one that starts the login session you care about. For a local console or SSH setup, inspect the relevant file first.

$ sudo grep -nE '^(auth|account|password|session)' /etc/pam.d/login
$ sudo grep -nE '^(auth|account|password|session)' /etc/pam.d/sshd

The module supports session and auth types. For a login notification, add this line to the service file that owns the session:

session optional pam_mail.so

optional keeps a mail-spool problem from becoming an authentication or session failure in the usual PAM stack. The module still returns errors such as PAM_USER_UNKNOWN or PAM_SERVICE_ERR; the control flag determines how the surrounding stack handles them.

Copy the file to a temporary location before editing it, then make one small change as root:

$ sudo cp -p /etc/pam.d/login /etc/pam.d/login.before-pam-mail
$ sudoedit /etc/pam.d/login

Warning: a malformed PAM file can lock you out of a service. Keep an already-open root session while testing. To undo this example, remove the new session optional pam_mail.so line, or restore the backup with sudo cp -p /etc/pam.d/login.before-pam-mail /etc/pam.d/login if you made no other changes.

Checkpoint: confirm the line before logging out

$ sudo grep -nF 'session optional pam_mail.so' /etc/pam.d/login
42:session optional pam_mail.so

The line number will differ. If the command prints nothing, stop and fix the file before closing your existing session.

3. Test the notification and the MAIL variable

Open a new login through the selected service. A successful session should display one mail-status message when mail is present. The exact wording depends on the module's detected spool state and on the application handling PAM conversation.

To check the environment variable inside the new session, use:

$ printf 'MAIL=%s\n' "$MAIL"
MAIL=/var/mail/alice

The path is an example. If MAIL is empty, check that the PAM line is in the service actually used, that nopen was not supplied by another edit, and that the login application imports PAM environment values into the shell.

The module's default message can include the spool being used. Add standard only when you need the older "You have ..." style; it also implies empty. Add quiet when you want output only for new mail.

4. Choose options deliberately

Options are appended to the module name. For example, this configuration sets the variable but prints no login mail information:

session optional pam_mail.so nopen

Use noenv when the application must not receive MAIL:

session optional pam_mail.so noenv quiet

That combination reports only new mail and suppresses the environment variable. Do not add both nopen and noenv while troubleshooting: together they hide both visible output and the variable, making a working module look absent.

For a non-default spool, use dir=. The module looks for the login name below the supplied location:

session optional pam_mail.so dir=/srv/mail

This means /srv/mail/alice, not an arbitrary file selected by the user. If the value starts with ~, it is interpreted as a path in the user's home directory. A directory at the resulting path is treated as Maildir.

For a hashed spool, set the depth explicitly. With hash=2, the module looks for a layout such as /var/spool/mail/u/s/alice:

session optional pam_mail.so dir=/var/spool/mail hash=2

Do not guess the hash depth. Compare the option with the actual mail transport layout, then test a fresh session.

5. Diagnose without turning on more output than necessary

If the session behaves unexpectedly, first reduce the configuration to the default line and verify the service path. The debug option prints diagnostic information, which may expose local paths in logs or terminal output, so use it briefly and remove it after testing:

session optional pam_mail.so debug

A bad argument can produce PAM_SERVICE_ERR. An unknown account can produce PAM_USER_UNKNOWN. Those are module results, not proof that the account's mailbox is corrupt. Check the account with getent passwd, check the resolved path with ls -ld, and inspect the service file for spelling errors.

The close option also reports mail when the user logs out. Add it only if logout-time messages are useful in your application; otherwise the default login-only behaviour is less distracting.

Done means

  • The module is present in the PAM service that starts the intended session.
  • A fresh test login reports the expected mail state, or stays quiet when nopen or quiet requires it.
  • printf 'MAIL=%s\n' "$MAIL" shows the expected path unless noenv is intentional.
  • The configured dir= and hash= values match the real spool layout.
  • Your backup remains available until the next login test succeeds.