Understanding dnl vs dnl # in sendmail.mc: Syntax Differences & Practical Usage


2 views

In Sendmail's sendmail.mc configuration files, dnl stands for "delete through newline." It serves two primary purposes:

  1. Commenting out configuration lines
  2. Preventing blank lines in the generated sendmail.cf file

While both are used for commenting, they have distinct behaviors:

Syntax Effect Output in sendmail.cf
dnl Completely removes the line No trace remains
dnl # Creates a commented line Appears as # comment

Here's how to properly use these directives:

Enabling Features

FEATURE(masquerade_envelope')dnl
FEATURE(virtusertable')dnl

Commenting Out Features

For temporary disabling (preserves documentation):

dnl # FEATURE(access_db')dnl
dnl # This controls access control rules

For permanent removal:

dnl FEATURE(no_default_msa')dnl
  • Use dnl # when you want to keep documentation in the generated file
  • Use plain dnl when you want complete removal of configuration lines
  • For operational comments, prefer dnl # as it makes debugging easier
dnl FEATURE(delay_checks')dnl # Wrong - comment will be removed
dnl # FEATURE(delay_checks')dnl # Correct - comment preserved

Remember to rebuild your configuration after changes:

m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
service sendmail restart

In Sendmail's configuration files (sendmail.mc), both dnl and dnl # serve as commenting mechanisms, but with critical behavioral differences:

dnl # This is a comment that will be discarded during m4 processing
dnl This entire line (including the dnl) will be removed before processing

To disable a configuration line:

dnl FEATURE(virtusertable')dnl  // Completely removes this feature
dnl # FEATURE(access_db')dnl    // Creates a commented reference

To enable a feature:

FEATURE(masquerade_envelope')dnl  // Active configuration
# FEATURE(no_default_msa')dnl    // Still inactive despite removing dnl

Here's how these markers appear in production configurations:

dnl # Uncomment to enable STARTTLS
dnl define(confCACERT_PATH', /etc/pki/tls/certs')dnl
dnl define(confCACERT', /etc/pki/tls/certs/ca-bundle.crt')dnl
dnl define(confSERVER_CERT', /etc/pki/tls/certs/sendmail.pem')dnl
dnl define(confSERVER_KEY', /etc/pki/tls/certs/sendmail.pem')dnl

dnl # For debugging purposes:
dnl define(confLOG_LEVEL', 14')dnl

The m4 macro processor handles these directives sequentially:

  1. dnl lines are eliminated before macro processing
  2. # comments are preserved in intermediate files
  3. Combined dnl # acts as documentation that won't appear in output
  • Use dnl for temporary feature disabling
  • Use dnl # for permanent documentation
  • Always rebuild after changes: make -C /etc/mail
  • Verify with: sendmail -d0.1 -bv root