This article outlines a quick Drupal hack for controlling how mail gets sent. It was originally posted on matthine.com.
After setting a Drupal site recently up I found that the contact form wasn't working. That is, it would report that email was being sent, but no email would arrive at its destination. From past experience I guessed this might be something to do with my ISP's email configuration. It was a bit difficult to tell without a meaningful (or any) error message, and another site with a very similar configuration was sending out emails fine, probably via a different mail server, but it seemed like the best place to start.
I looked briefly into adding an SMTP module, but didn't see the need. Instead, I used the smtp_library variable to force drupal to include and execute a drupal_mail_wrapper() function. If this variable is set, Drupal loads the file in the variable and calls this function, passing $message, which is an array containing the message data.
I have a general purpose module that provides minor bits of additional functionality, so I put this there. It could go anywhere - just put your own mail() function in its own file somewhere, and put the path to that file in smtp_library in your config.
Here's how I did mine:
My module is called 'coherent'. Here is the line in the init function that sets the smtp_library variable.
1: function coherent_init() {
2: // snip
3: variable_set('smtp_library', drupal_get_path('module','coherent') . '/smtp.inc.php');
4: }
The file smtp.inc.php is actually empty. I put my own mail function in the coherent module. This could potentially cause function name collisions but I am using this in a controlled environment.
The mail function is very similar to Drupal's own. The only difference is that it adds a '-f' additional parameter to the mail() call, this being the extra information required by my ISP's security.
1: function drupal_mail_wrapper($message) {
2: $mimeheaders = array();
3: foreach ($message['headers'] as $name => $value) {
4: $mimeheaders[] = $name .': '. mime_header_encode($value);
5: }
6: return mail(
7: $message['to'],
8: mime_header_encode($message['subject']),
9: // Note: e-mail uses CRLF for line-endings, but PHP's API requires LF.
10: // They will appear correctly in the actual e-mail that is sent.
11: str_replace("\r", '', $message['body']),
12: // For headers, PHP's API suggests that we use CRLF normally,
13: // but some MTAs incorrecly replace LF with CRLF. See #234403.
14: join("\n", $mimeheaders),
15: // Add in an explicit sendmail '-f' from arg
16: '-f'.$message['from']
17: );
18: }
The Drupal mail function, then, looks like this:
1: function drupal_mail_send($message) {
2: // Allow for a custom mail backend.
3: if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) {
4: include_once './'. variable_get('smtp_library', '');
5: return drupal_mail_wrapper($message);
6: }
7: // etc...
With the smtp_library function set, and a file present (hence the blank include file described above), the drupal_mail_wrapper() function gets called, and the mail gets sent.