Home / Alt manpages / pam_mail(8)

  • pam_mail(8)
  • Admin command
  • linux

Show New Mail at Login with pam_mail

pam_mail is the module that prints "You have new mail" at login and can export a MAIL variable too. This guide wires it into a real PAM service, on 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. The module only 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 touching 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 just to make the check pass: the module can also report "no mail" honestly when the empty option is used.

2. Add the module to the right PAM service

PAM configuration is service-specific. The service named under /etc/pam.d/ must be the one that actually 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 just decides how the surrounding stack reacts.

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 on your system. 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 service you edited. 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 the PAM conversation.

To check the environment variable inside the new session:

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

The path shown is an example. If MAIL is empty, check that the PAM line is in the service actually used, that nopen was not added elsewhere, 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. 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 pairing reports only new mail and suppresses the environment variable. Do not combine nopen and noenv while troubleshooting: together they hide both the visible output and the variable, which makes a working module look completely 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

That means /srv/mail/alice, not an arbitrary file the user picks. If the value starts with ~, it is read as a path inside 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 against your actual mail transport layout, then test a fresh session.

5. Diagnose without turning on more output than necessary

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

session optional pam_mail.so debug
  • PAM_SERVICE_ERR usually points to a bad argument.
  • PAM_USER_UNKNOWN means the account was not found. Neither error is proof that the mailbox itself 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 actually useful for your application; otherwise the default login-only behaviour is less distracting.

Done means

  • Module placed. pam_mail.so is in the PAM service that starts the intended session.
  • Fresh login tested. A new session reports the expected mail state, or stays quiet when nopen or quiet requires it.
  • Variable checked. printf 'MAIL=%s\n' "$MAIL" shows the expected path unless noenv is intentional.
  • Spool options matched. The configured dir= and hash= values reflect the real spool layout.
  • Backup kept until the next login test succeeds.