Summary

The Bounce module collects non-delivery reports generated by remote mail servers in response to emails sent from your Drupal site. It parses these non-delivery reports for response codes, scores those codes, and blocks further emails from being sent to email addresses that have passed a score threshold. This helps prevent your site from looking like a spam source by being a good internet citizen and respecting non-delivery responses, such as a notice that a recipient email account no longer exists.

This module is a rewrite of non-Drupal code that itself resulted from some years of experience running a few-thousand-subscriber mailing list covering the sane end of a topic that, unfortunately, tends to trigger spam filters - because there is a large and obnoxious spam-generating industry over at the other, less sane end of the pool. The default settings in Bounce are geared towards helping to maintain good long-term deliverability of mail under that sort of circumstance.

Bounce employs a modular design in which the functionality necessary to analyze and respond to non-delivery reports is split between Connector, Analyst, and Blocker components. Default, working versions of these components are provided, and developers can easily add other implementations through hooks defined in this module.

Alternatives for Drupal 8

Bounce as yet is not ported to Drupal 8. One viable alternative is Inmail.

Requirements

1) Drupal Core Version

Bounce requires Drupal 7.12 or later, as that is the earliest version to support cancellation of mail sending via setting $message['send'] = FALSE in an implementation of hook_mail_alter().

2) A Mail Account for Non-Delivery Reports

You must have a mail account set up to receive non-delivery report emails. e.g. automatic responses sent to the account bounces@example.com. That account must be accessible via POP or IMAP protocols from the server hosting your Drupal site.

3) Mail is Sent Through drupal_mail()

For Bounce to know about outgoing mail, suitably alter it, and record the fact that it was sent, that mail must be sent through drupal_mail() - or at least through some similar mechanism that will invoke hook_mail_alter() so that Bounce can do its work. Not all modules that provide new options for sending mail do this - some skip the implementation of a MailSystemInterface class and do not use the core Drupal mail APIs.

Methods of sending mail that bypass hook_mail_alter() can still be used with Bounce, but will require a little work and additional code to integrate. See the Bounce documentation section on "Working With Bounce Without Using hook_mail_alter()" for instructions.

4) Mail Delivery Mechanism Allows Return-Path to be Set

Bounce sets the Return-Path mail header to a different value than the From header. Not all modules that provide new options for sending mail (i.e. implement a MailSystemInterface class) permit this, and some ignore the Return-Path setting entirely.

Again, modules that bypass hook_mail_alter() prevent Bounce from working, and that includes preventing Bounce from setting the necessary Return-Path header.

5) (Optional, but Very Much Recommended) Mail is Sent Using SMTP

Ideally you should have your own mail server set up for your domain, and the mail module you are using will send all outgoing mail from your Drupal site through that server via the SMTP protocol. If you are not doing this, then you have far more serious issues with mail deliverability than Bounce can help you with - for example, sending from the Drupal server using sendmail on a Linux system cannot respond correctly to greylisting, which looks very much like a spam sending robot's behavior.

Mail Modules Known to Work or Not Work With Bounce

Works

  • Drupal DefaultMailSystem (via sendmail, so not ideal)
  • PHPMailer (7.x-3.x-dev)
  • SMTP Authentication Support (7.x-1.x-dev or 7.x-1.1 or later)
  • Swift Mailer

Requires integration to work, as it bypasses hook_mail_alter()

  • ManyMail

Installation and Configuration

Enable the Bounce module, then navigate to the module's configuration page. On installation, default configuration is provided for all values except:

  • the mail server and account that will receive non-delivery reports
  • the Return-Path header for outgoing mail

Enter these values and you are good to go. e.g. if your site is at example.com and you have a mailserver at mail.mydomain.com, then you might set the following values in the General Settings page:

Return-Path header: bounce@example.com

and the following values in the Connector settings page:

Server: mail.example.com
Protocol: POP3
Encryption: SSL
Port: 995
Login: bounce
Password: my_obscure_password

Note that depending on your mailserver, login may be the account name ('bounce') or the full account email address ('bounce@example.com').

How Bounce Marks and Blocks Addresses

Bounce consists of three major component parts, the Connector, the Analyst, and the Blocker:

1) On each cron run the Connector logs in to the Return-Path account and retrieves mail items, the non-delivery reports, that it passes to the Analyst.

2) The Analyst identifies the original recipient email address and assigns a code to each non-delivery report.

3) Bounce then writes the codes, email addresses, and reports to the database.

4) The Blocker peruses the report records on each cron run. Every response code is associated with a score, with higher scores indicating response codes that more urgently require action. The Blocker checks to see whether the sum of recorded scores for any particular email address exceeds a threshold: those that do are marked and future delivery to these email addresses is blocked.

Note that because the Blocker runs first in a cron run, and because the Connector and Analyst run as queues, it takes two cron runs for a mail to become blocked. On the first run, the non-delivery report is obtained and analyzed. On the second run that analysis is used to block the mail.

Records of past non-delivery reports are cleared out when they become too old, so an address will only be marked and blocked if it gains enough non-delivery reports in a short enough time. The default settings for Bounce will block email addresses fairly aggressively, reasoning that it is better to deliver too few emails than to look like a spammer or a mailbot by being non-responsive to non-delivery reports. This is not an exact science by any means, and different content in mails will trigger wildly different responses. If there is no big horrible spam-generating industry spawning spam that shares topics with your site and its emails, then you can probably set your score threshold higher than the default.

The scoring for specific codes, the threshold for marking emails, and the age at which records of non-delivery reports are cleared out can all be configured in the Bounce administration settings pages.

Return-Path Notes

The Return-Path mail header set by Bounce is crucial to the operation of this module: it is how you tell remote mail servers where you want non-delivery reports sent to. If the Return-Path header is not set in the outgoing emails sent by the server, then non-delivery report emails sent back to you will most likely return directly to the sending account, which in most circumstances is the site email address set in the administrative interface. Bounce empties out the email account it is configured to access, so you want it to have its own account for non-delivery reports.

As noted in the Requirements section above, not all of the options for sending mail from Drupal respect the Return-Path set in a mail message.

Out of the box, Drupal 7 will correctly set the Return-Path header if sending using the DefaultMailSystem mail system. This uses sendmail, however, to send mail from the local server directly. This will cause you all sorts of other issues - such as being unable to respond properly to greylisting, which is definitely going to make you look like a spam source or mailbot. If you are serious about being a good internet citizen when it comes to sending mail to your users, then you really should set up a mail server and send your outgoing mail through that server.

If you are using a mail module that correctly preserves the Return-Path but you are still losing the Return-Path header between sending and receiving then the problem is a mail server configuration issue, not a Drupal issue. It is quite possible, though not commonplace, for a mail server to be configured to override the Return-Path passed to it in an SMTP session.

Use a Mail Server!

You should absolute, definitely, always be sending outgoing mail through a full-featured mail server, and not via sendmail on the local web server. For most Drupal developers, this means using a mail module like SMTP Authentication Support or PHPMailer.

In terms of looking like a spammer, the harm you do yourself by sending from the local web server will likely outweigh most of what Bounce can do for you. For example, not correctly handling greylisting is the sign of a mailbot or compromised server, and that is exactly what will happen if you send only via sendmail.

There are a range of other important topics relating to deliverability of email and marking of servers as spam sources, such as the Sender Policy Framework and other similar schemes, and you are encouraged to research further.

Blocked Mails, Not Blocked Users

Blocked mails are maintained independently of users. An email address can be blocked due to non-delivery reports even if no user is associated with it, and a blocked mail is not removed when an associated user account is removed.

When an email address is blocked, all emails sent to that address through the Drupal mail API will be blocked by Bounce. Any attempt to register or request a password reminder for that email address will display a warning message and fail.

If the blocked email address is associated with a user account, then that user is not blocked from logging in. The user will receive no mail from the site, and will be warned that their email address is blocked and should be changed when logging in and when visiting their account page.

The administrative settings for Bounce allow notifications to be set for login, user account editing, password reset, and registration using blocked email addresses: the general idea is to let the user know that he or she will not receive mail rather than just silently failing.

Component Definition Hooks

1) hook_bounce_connector()
2) hook_bounce_connector_alter(&$connectors)
3) hook_bounce_analyst()
4) hook_bounce_analyst_alter(&$analysts)
5) hook_bounce_blocker()
6) hook_bounce_blocker_alter(&$blockers)

If you want to make available new components then you can create the component and declare it as an option for use via implementations of these hooks in your own module. Once declared, a component will show up as a selectable option in the general settings administrative form.

Other Hooks

1) hook_bounce_mails_blocked($mails)
2) hook_bounce_mails_unblocked($mails)

React to the blocking and unblocking of mails via these hooks.

3) hook_bounce_code_type()
4) hook_bounce_code_type_alter(&$types)

These fairly trivial hooks provide a list of different categories for the response code that are assigned to non-delivery reports. The categories have no material effect.

5) hook_bounce_analysis_alter(&$analysis, $report)

Use this hook to alter the analysis settled on for a particular non-delivery report.

Working With Bounce Without Using hook_mail_alter()

So your method of sending mail bypasses drupal_mail() and hook_mail_alter()? You should still be able to use Bounce to manage non-delivery report tracking provided you do a little additional work in code.

1) Add a unique identifier header to each outgoing mail

How this is done is up to you. You can use any header key, and any form of unique ID provided it is no longer than 255 characters (i.e. it will fit into Bounce's schema).

2) Let Bounce know about the unique identifier header key

If you are setting the header "x-my-unique-mail-id" in your outgoing mails then you will have to set the "bounce_mail_header_name" variable, either in code or configured via the general settings administration form.

variable_set('bounce_mail_header_name', 'x-my-unique-mail-id');

3) Tell Bounce about outgoing mail as it is sent

Every time you send mail, you must call the following function in order to pass to Bounce the email addresses you are sending to and the unique header IDs in each piece of outgoing mail:

bounce_record_sent_mails($mail_data)

The function is more efficient if you pass in information in batches, so if you send in batches then call it less frequently and with larger sets of data.

4) Ask Bounce which email addresses are blocked

Before sending mail, ask Bounce which email addresses are blocked and should not be sent further mail by using this function. Given an array of addresses, it will return those that are blocked:

bounce_determine_blocked_addresses($addresses)

It is up to you to then remove these addresses and refrain from sending them mail. This function is more efficient if you pass in sets of addresses rather than one email address at a time, so if you send mail in batches than call this function once per batch to give it all of the addresses you intend to send to.

Project information

  • caution Minimally maintained
    Maintainers monitor issues, but fast responses are not guaranteed.
  • caution Maintenance fixes only
    Considered feature-complete by its maintainers.
  • chart icon185 sites report using this module
  • Created by exratione on , updated
  • shieldStable releases for this project are covered by the security advisory policy.
    Look for the shield icon below.

Releases