Notice: Undefined index: headers in DefaultMailSystem->mail() (line 54 of /var/www/example.com/public_html/modules/system/system.mail.inc).

Notice: Undefined index: headers in DefaultMailSystem->mail() (line 54 of /var/www/example.com/public_html/modules/system/system.mail.inc).

if you get this message, you will also see the following message.
Warning: Invalid argument supplied for foreach() in DefaultMailSystem->mail() (line 54 of /var/www/example.com/public_html/modules/system/system.mail.inc).

Somebody broke the following line of code. You are sending mail without the header component or with the header component in the wrong place.
foreach ($message['headers'] as $name => $value) {

Well, it might not be you who broke it. It might be termites in your hard drive. One common cause is code that adds headers based on conditions and none of the conditions occurred so no headers were added. More about that later.

If your code uses the following Drupal function, the function will build a minimum header array and you will not get this error. The same applies when using any function that passes the mail to this function.
drupal_mail($module, $key, $to, $language, $params, $from, $send)

You can get this error when you try to use the following underlying mail function direct, a function hidden for your protection. There is also a PHP mail function that can fail for similar reasons but with different error messages.
mail(array $message);

I mentioned those conditional headers are a problem when you send mail direct. Here is code of the type you might see on occasions.

if($a == 3) {
   $header['from'] = 'me@example.com';
}
if($b == 5) {
   $header['from'] = 'webmaster@example.com';
}

Notice the code will not produce a header of none of the conditions are met. The following code is a slight improvement to create an empty array so the code never fails due to a missing header.

$header = array();
if($a == 3) {
   $header['from'] = 'me@example.com';
}
if($b == 5) {
   $header['from'] = 'webmaster@example.com';
}

Now we improve the code to always have a default from address.

$header = array('from' => 'webmaster@example.com');
if($a == 3 and $b != 5) {
   $header['from'] = 'me@example.com';
}

Next we improve the code with modern readable formatting.

$header = array('from' => 'webmaster@example.com');
if($a == 3 and $b != 5)
   {
   $header['from'] = 'me@example.com';
   }